diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:53:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:53:01 +0000 |
commit | ead246455adf1a215ec2715dad6533073a6beb4e (patch) | |
tree | f3f97a47d77053bf96fe74cdbd6fae74380e8a92 /source/Plugins | |
parent | fdb00c4408990a0a63ef7f496d809ce59f263bc5 (diff) |
Notes
Diffstat (limited to 'source/Plugins')
252 files changed, 11181 insertions, 10492 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 362a80be4b0d..9dff12bcc748 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -1326,7 +1326,8 @@ ABIMacOSX_arm::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) { if (vendor_type == llvm::Triple::Apple) { if ((arch_type == llvm::Triple::arm) || (arch_type == llvm::Triple::thumb)) { - return ABISP(new ABIMacOSX_arm(process_sp)); + return ABISP( + new ABIMacOSX_arm(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1846,6 +1847,7 @@ bool ABIMacOSX_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm-apple-ios default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index ac9ba00b9d91..e512651f86e5 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -85,7 +85,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABIMacOSX_arm(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIMacOSX_arm(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 368e37213249..6473ccf9a19a 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -1665,8 +1665,10 @@ ABIMacOSX_arm64::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) { const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor(); if (vendor_type == llvm::Triple::Apple) { - if (arch_type == llvm::Triple::aarch64) { - return ABISP(new ABIMacOSX_arm64(process_sp)); + if (arch_type == llvm::Triple::aarch64 || + arch_type == llvm::Triple::aarch64_32) { + return ABISP( + new ABIMacOSX_arm64(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1710,9 +1712,8 @@ bool ABIMacOSX_arm64::PrepareTrivialCall( for (size_t i = 0; i < args.size(); ++i) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%d (0x%" PRIx64 ") into %s", - static_cast<int>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s", + static_cast<int>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } @@ -2011,6 +2012,7 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm64-apple-darwin default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h index bfacbcd54a94..c7a91ba9c468 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h @@ -93,7 +93,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABIMacOSX_arm64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIMacOSX_arm64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 67371b432ff8..76ebd6476ffd 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -710,7 +710,8 @@ ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) if ((arch.GetTriple().getArch() == llvm::Triple::x86) && (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS())) { - return ABISP(new ABIMacOSX_i386(process_sp)); + return ABISP( + new ABIMacOSX_i386(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -1055,6 +1056,7 @@ bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("i386 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index 57def683283f..50062b84d878 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -92,7 +92,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABIMacOSX_i386(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIMacOSX_i386(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-arc/ABISysV_arc.cpp b/source/Plugins/ABI/SysV-arc/ABISysV_arc.cpp new file mode 100644 index 000000000000..715b5e5d2b95 --- /dev/null +++ b/source/Plugins/ABI/SysV-arc/ABISysV_arc.cpp @@ -0,0 +1,614 @@ +//===-- ABISysV_arc.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 "ABISysV_arc.h" + +// C Includes +// C++ Includes +#include <array> +#include <limits> +#include <type_traits> + +// Other libraries and framework includes +#include "llvm/ADT/Triple.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/Support/MathExtras.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" + +#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString() +#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString() + +// The ABI is not a source of such information as size, offset, encoding, etc. +// of a register. Just provides correct dwarf and eh_frame numbers. + +#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \ + { \ + DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), \ + 0, 0, eEncodingInvalid, eFormatDefault, \ + { dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num }, \ + nullptr, nullptr, nullptr, 0 \ + } + +#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \ + DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM) + +using namespace lldb; +using namespace lldb_private; + +namespace { +namespace dwarf { +enum regnums { + r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, + r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, + r27, fp = r27, r28, sp = r28, r29, r30, r31, blink = r31, + r32, r33, r34, r35, r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46, + r47, r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59, r60, + /*reserved,*/ /*limm indicator,*/ r63 = 63, pc = 70, status32 = 74 +}; + +static const std::array<RegisterInfo, 64> g_register_infos = { { + DEFINE_GENERIC_REGISTER_STUB(r0, nullptr, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GENERIC_REGISTER_STUB(r1, nullptr, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GENERIC_REGISTER_STUB(r2, nullptr, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GENERIC_REGISTER_STUB(r3, nullptr, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GENERIC_REGISTER_STUB(r4, nullptr, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GENERIC_REGISTER_STUB(r5, nullptr, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GENERIC_REGISTER_STUB(r6, nullptr, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GENERIC_REGISTER_STUB(r7, nullptr, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_REGISTER_STUB(r8, nullptr), + DEFINE_REGISTER_STUB(r9, nullptr), + DEFINE_REGISTER_STUB(r10, nullptr), + DEFINE_REGISTER_STUB(r11, nullptr), + DEFINE_REGISTER_STUB(r12, nullptr), + DEFINE_REGISTER_STUB(r13, nullptr), + DEFINE_REGISTER_STUB(r14, nullptr), + DEFINE_REGISTER_STUB(r15, nullptr), + DEFINE_REGISTER_STUB(r16, nullptr), + DEFINE_REGISTER_STUB(r17, nullptr), + DEFINE_REGISTER_STUB(r18, nullptr), + DEFINE_REGISTER_STUB(r19, nullptr), + DEFINE_REGISTER_STUB(r20, nullptr), + DEFINE_REGISTER_STUB(r21, nullptr), + DEFINE_REGISTER_STUB(r22, nullptr), + DEFINE_REGISTER_STUB(r23, nullptr), + DEFINE_REGISTER_STUB(r24, nullptr), + DEFINE_REGISTER_STUB(r25, nullptr), + DEFINE_REGISTER_STUB(r26, "gp"), + DEFINE_GENERIC_REGISTER_STUB(r27, "fp", LLDB_REGNUM_GENERIC_FP), + DEFINE_GENERIC_REGISTER_STUB(r28, "sp", LLDB_REGNUM_GENERIC_SP), + DEFINE_REGISTER_STUB(r29, "ilink"), + DEFINE_REGISTER_STUB(r30, nullptr), + DEFINE_GENERIC_REGISTER_STUB(r31, "blink", LLDB_REGNUM_GENERIC_RA), + DEFINE_REGISTER_STUB(r32, nullptr), + DEFINE_REGISTER_STUB(r33, nullptr), + DEFINE_REGISTER_STUB(r34, nullptr), + DEFINE_REGISTER_STUB(r35, nullptr), + DEFINE_REGISTER_STUB(r36, nullptr), + DEFINE_REGISTER_STUB(r37, nullptr), + DEFINE_REGISTER_STUB(r38, nullptr), + DEFINE_REGISTER_STUB(r39, nullptr), + DEFINE_REGISTER_STUB(r40, nullptr), + DEFINE_REGISTER_STUB(r41, nullptr), + DEFINE_REGISTER_STUB(r42, nullptr), + DEFINE_REGISTER_STUB(r43, nullptr), + DEFINE_REGISTER_STUB(r44, nullptr), + DEFINE_REGISTER_STUB(r45, nullptr), + DEFINE_REGISTER_STUB(r46, nullptr), + DEFINE_REGISTER_STUB(r47, nullptr), + DEFINE_REGISTER_STUB(r48, nullptr), + DEFINE_REGISTER_STUB(r49, nullptr), + DEFINE_REGISTER_STUB(r50, nullptr), + DEFINE_REGISTER_STUB(r51, nullptr), + DEFINE_REGISTER_STUB(r52, nullptr), + DEFINE_REGISTER_STUB(r53, nullptr), + DEFINE_REGISTER_STUB(r54, nullptr), + DEFINE_REGISTER_STUB(r55, nullptr), + DEFINE_REGISTER_STUB(r56, nullptr), + DEFINE_REGISTER_STUB(r57, nullptr), + DEFINE_REGISTER_STUB(r58, "accl"), + DEFINE_REGISTER_STUB(r59, "acch"), + DEFINE_REGISTER_STUB(r60, "lp_count"), + DEFINE_REGISTER_STUB(r63, "pcl"), + DEFINE_GENERIC_REGISTER_STUB(pc, nullptr, LLDB_REGNUM_GENERIC_PC), + DEFINE_GENERIC_REGISTER_STUB(status32, nullptr, LLDB_REGNUM_GENERIC_FLAGS)} }; +} // namespace dwarf +} // namespace + +const RegisterInfo *ABISysV_arc::GetRegisterInfoArray(uint32_t &count) { + count = dwarf::g_register_infos.size(); + return dwarf::g_register_infos.data(); +} + +size_t ABISysV_arc::GetRedZoneSize() const { return 0; } + +bool ABISysV_arc::IsRegisterFileReduced(RegisterContext ®_ctx) const { + if (!m_is_reg_file_reduced) { + const auto *const rf_build_reg = reg_ctx.GetRegisterInfoByName("rf_build"); + + const auto reg_value = reg_ctx.ReadRegisterAsUnsigned(rf_build_reg, + /*fail_value*/ 0); + // RF_BUILD "Number of Entries" bit. + const uint32_t rf_entries_bit = 1U << 9U; + m_is_reg_file_reduced = (reg_value | rf_entries_bit) != 0; + } + + return m_is_reg_file_reduced.getValueOr(false); +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ + +ABISP ABISysV_arc::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) { + return llvm::Triple::arc == arch.GetTriple().getArch() ? + ABISP(new ABISysV_arc(std::move(process_sp), MakeMCRegisterInfo(arch))) : + ABISP(); +} + +namespace { +const size_t word_size = 4U; +const size_t reg_size = word_size; + +inline size_t AugmentArgSize(size_t size_in_bytes) { + return llvm::alignTo(size_in_bytes, word_size); +} + +size_t TotalArgsSizeInWords(const llvm::ArrayRef<ABI::CallArgument> &args) { + size_t total_size = 0; + for (const auto &arg : args) + total_size += + (ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(arg.size) + : reg_size) / + word_size; + + return total_size; +} +} // namespace + +bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp, + addr_t func_addr, addr_t return_addr, + llvm::ArrayRef<addr_t> args) const { + // We don't use the traditional trivial call specialized for jit. + return false; +} + +bool ABISysV_arc::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t pc, + addr_t ra, llvm::Type &prototype, + llvm::ArrayRef<ABI::CallArgument> args) const { + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return false; + + uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (pc_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + if (ra_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + if (sp_reg == LLDB_INVALID_REGNUM) + return false; + + Status error; + ProcessSP process = thread.GetProcess(); + if (!process) + return false; + + // Push host data onto target. + for (const auto &arg : args) { + // Skip over target values. + if (arg.type == ABI::CallArgument::TargetValue) + continue; + + // Create space on the stack for this data 4-byte aligned. + sp -= AugmentArgSize(arg.size); + + if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) < arg.size + || error.Fail()) + return false; + + // Update the argument with the target pointer. + *const_cast<addr_t *>(&arg.value) = sp; + } + + // Make sure number of parameters matches prototype. + assert(!prototype.isFunctionVarArg()); + assert(prototype.getFunctionNumParams() == args.size()); + + const size_t regs_for_args_count = IsRegisterFileReduced(*reg_ctx) ? 4U : 8U; + + // Number of arguments passed on stack. + auto args_size = TotalArgsSizeInWords(args); + auto on_stack = + args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count; + auto offset = on_stack * word_size; + + uint8_t reg_value[reg_size]; + size_t reg_index = LLDB_REGNUM_GENERIC_ARG1; + + for (const auto &arg : args) { + auto value = reinterpret_cast<const uint8_t *>(&arg.value); + auto size = + ABI::CallArgument::TargetValue == arg.type ? arg.size : reg_size; + + // Pass arguments via registers. + while (size > 0 && reg_index < regs_for_args_count) { + size_t byte_index = 0; + auto end = size < reg_size ? size : reg_size; + + while (byte_index < end) { + reg_value[byte_index++] = *(value++); + --size; + } + + while (byte_index < reg_size) { + reg_value[byte_index++] = 0; + } + + RegisterValue reg_val_obj(reg_value, reg_size, eByteOrderLittle); + if (!reg_ctx->WriteRegister( + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index), + reg_val_obj)) + return false; + + // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs. + ++reg_index; + } + + if (reg_index < regs_for_args_count || size == 0) + continue; + + // Remaining arguments are passed on the stack. + if (process->WriteMemory(sp - offset, value, size, error) < size || + !error.Success()) + return false; + + offset -= AugmentArgSize(size); + } + + // Set stack pointer immediately below arguments. + sp -= on_stack * word_size; + + // Update registers with current function call state. + reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc); + reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra); + reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp); + + return true; +} + +bool ABISysV_arc::GetArgumentValues(Thread &thread, ValueList &values) const { + return false; +} + +Status ABISysV_arc::SetReturnValueObject(StackFrameSP &frame_sp, + ValueObjectSP &new_value_sp) { + Status result; + if (!new_value_sp) { + result.SetErrorString("Empty value object for return value."); + return result; + } + + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { + result.SetErrorString("Null clang type for return value."); + return result; + } + + auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext(); + + bool is_signed = false; + if (!compiler_type.IsIntegerOrEnumerationType(is_signed) && + !compiler_type.IsPointerType()) { + result.SetErrorString("We don't support returning other types at present"); + return result; + } + + DataExtractor data; + size_t num_bytes = new_value_sp->GetData(data, result); + + if (result.Fail()) { + result.SetErrorStringWithFormat( + "Couldn't convert return value to raw data: %s", result.AsCString()); + return result; + } + + if (num_bytes <= 2 * reg_size) { + offset_t offset = 0; + uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); + + auto reg_info = + reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) { + result.SetErrorStringWithFormat("Couldn't write value to register %s", + reg_info->name); + return result; + } + + if (num_bytes <= reg_size) + return result; // Successfully written. + + raw_value >>= 32; + reg_info = + reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) { + result.SetErrorStringWithFormat("Couldn't write value to register %s", + reg_info->name); + } + + return result; + } + + result.SetErrorString( + "We don't support returning large integer values at present."); + return result; +} + +namespace { +template <typename T> +void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) { + raw_value &= std::numeric_limits<T>::max(); + if (is_signed) + scalar = static_cast<typename std::make_signed<T>::type>(raw_value); + else + scalar = static_cast<T>(raw_value); +} + +bool SetSizedInteger(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes, + bool is_signed) { + switch (size_in_bytes) { + default: + return false; + + case sizeof(uint64_t): + SetInteger<uint64_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint32_t): + SetInteger<uint32_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint16_t): + SetInteger<uint16_t>(scalar, raw_value, is_signed); + break; + + case sizeof(uint8_t): + SetInteger<uint8_t>(scalar, raw_value, is_signed); + break; + } + + return true; +} + +bool SetSizedFloat(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes) { + switch (size_in_bytes) { + default: + return false; + + case sizeof(uint64_t): + scalar = *reinterpret_cast<double *>(&raw_value); + break; + + case sizeof(uint32_t): + scalar = *reinterpret_cast<float *>(&raw_value); + break; + } + + return true; +} + +uint64_t ReadRawValue(const RegisterContextSP ®_ctx, uint8_t size_in_bytes) { + auto reg_info_r0 = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + + // Extract the register context so we can read arguments from registers. + uint64_t raw_value = + reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0) & UINT32_MAX; + + if (sizeof(uint64_t) == size_in_bytes) + raw_value |= (reg_ctx->ReadRegisterAsUnsigned( + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_ARG2), 0) & + UINT64_MAX) << 32U; + + return raw_value; +} +} // namespace + +ValueObjectSP +ABISysV_arc::GetReturnValueObjectSimple(Thread &thread, + CompilerType &compiler_type) const { + if (!compiler_type) + return ValueObjectSP(); + + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return ValueObjectSP(); + + Value value; + value.SetCompilerType(compiler_type); + + const uint32_t type_flags = compiler_type.GetTypeInfo(); + // Integer return type. + if (type_flags & eTypeIsInteger) { + const size_t byte_size = compiler_type.GetByteSize(nullptr).getValueOr(0); + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + const bool is_signed = (type_flags & eTypeIsSigned) != 0; + if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed)) + return ValueObjectSP(); + + value.SetValueType(Value::eValueTypeScalar); + } + // Pointer return type. + else if (type_flags & eTypeIsPointer) { + 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); + } + // Floating point return type. + else if (type_flags & eTypeIsFloat) { + uint32_t float_count = 0; + bool is_complex = false; + + if (compiler_type.IsFloatingPointType(float_count, is_complex) && + 1 == float_count && !is_complex) { + const size_t byte_size = compiler_type.GetByteSize(nullptr).getValueOr(0); + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size)) + return ValueObjectSP(); + } + } + // Unsupported return type. + else + return ValueObjectSP(); + + return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), + value, ConstString("")); +} + +ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl( + Thread &thread, CompilerType &return_compiler_type) const { + ValueObjectSP return_valobj_sp; + + if (!return_compiler_type) + return return_valobj_sp; + + ExecutionContext exe_ctx(thread.shared_from_this()); + return GetReturnValueObjectSimple(thread, return_compiler_type); +} + +ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(Thread &thread, + llvm::Type &retType) const { + auto reg_ctx = thread.GetRegisterContext(); + if (!reg_ctx) + return ValueObjectSP(); + + Value value; + // Void return type. + if (retType.isVoidTy()) { + value.GetScalar() = 0; + } + // Integer return type. + else if (retType.isIntegerTy()) { + size_t byte_size = retType.getPrimitiveSizeInBits(); + if (1 != byte_size) // For boolian type. + byte_size /= CHAR_BIT; + + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + const bool is_signed = false; // IR Type doesn't provide this info. + if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed)) + return ValueObjectSP(); + } + // Pointer return type. + else if (retType.isPointerTy()) { + 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); + } + // Floating point return type. + else if (retType.isFloatingPointTy()) { + const size_t byte_size = retType.getPrimitiveSizeInBits() / CHAR_BIT; + auto raw_value = ReadRawValue(reg_ctx, byte_size); + + if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size)) + return ValueObjectSP(); + } + // Unsupported return type. + else + return ValueObjectSP(); + + return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), + value, ConstString("")); +} + +bool ABISysV_arc::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Our Call Frame Address is the stack pointer value. + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf::sp, 0); + + // The previous PC is in the BLINK. + row->SetRegisterLocationToRegister(dwarf::pc, dwarf::blink, true); + unwind_plan.AppendRow(row); + + // All other registers are the same. + unwind_plan.SetSourceName("arc at-func-entry default"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + + return true; +} + +bool ABISysV_arc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { + return false; +} + +bool ABISysV_arc::RegisterIsVolatile(const RegisterInfo *reg_info) { + if (nullptr == reg_info) + return false; + + // Volatile registers are: r0..r12. + uint32_t regnum = reg_info->kinds[eRegisterKindDWARF]; + if (regnum <= 12) + return true; + + static const std::string ra_reg_name = "blink"; + return ra_reg_name == reg_info->name; +} + +void ABISysV_arc::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "System V ABI for ARC targets", CreateInstance); +} + +void ABISysV_arc::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ConstString ABISysV_arc::GetPluginNameStatic() { + static ConstString g_name("sysv-arc"); + return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ + +ConstString ABISysV_arc::GetPluginName() { + return GetPluginNameStatic(); +} + +uint32_t ABISysV_arc::GetPluginVersion() { return 1; } diff --git a/source/Plugins/ABI/SysV-arc/ABISysV_arc.h b/source/Plugins/ABI/SysV-arc/ABISysV_arc.h new file mode 100644 index 000000000000..c4b26a54158c --- /dev/null +++ b/source/Plugins/ABI/SysV-arc/ABISysV_arc.h @@ -0,0 +1,106 @@ +//===-- ArchitectureArc.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 liblldb_ABISysV_arc_h_ +#define liblldb_ABISysV_arc_h_ + +// Other libraries and framework includes +#include <llvm/ADT/Optional.h> + +// Project includes +#include "lldb/Target/ABI.h" +#include "lldb/lldb-private.h" + +class ABISysV_arc : public lldb_private::ABI { +public: + ~ABISysV_arc() override = default; + + size_t GetRedZoneSize() const override; + + bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef<lldb::addr_t> args) const override; + + // Special thread plan for GDB style non-jit function calls. + bool + PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, lldb::addr_t returnAddress, + llvm::Type &prototype, + llvm::ArrayRef<ABI::CallArgument> args) const override; + + bool GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; + + lldb_private::Status + SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value) override; + + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; + + // Specialized to work with llvm IR types. + lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, + llvm::Type &type) const override; + + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + + bool CallFrameAddressIsValid(lldb::addr_t cfa) override { + // Stack call frame address must be 4 byte aligned. + return (cfa & 0x3ull) == 0; + } + + bool CodeAddressIsValid(lldb::addr_t pc) override { + // Code addresse must be 2 byte aligned. + return (pc & 1ull) == 0; + } + + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + + static void Initialize(); + + static void Terminate(); + + static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, + const lldb_private::ArchSpec &arch); + + static lldb_private::ConstString GetPluginNameStatic(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + +private: + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + + bool IsRegisterFileReduced(lldb_private::RegisterContext ®_ctx) const; + + using lldb_private::ABI::ABI; // Call CreateInstance instead. + + using RegisterFileFlag = llvm::Optional<bool>; + mutable RegisterFileFlag m_is_reg_file_reduced; +}; + +#endif // liblldb_ABISysV_arc_h_ diff --git a/source/Plugins/ABI/SysV-arc/CMakeLists.txt b/source/Plugins/ABI/SysV-arc/CMakeLists.txt new file mode 100644 index 000000000000..3dc0d1c65b46 --- /dev/null +++ b/source/Plugins/ABI/SysV-arc/CMakeLists.txt @@ -0,0 +1,11 @@ +add_lldb_library(lldbPluginABISysV_arc PLUGIN + ABISysV_arc.cpp + + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + lldbPluginProcessUtility + LINK_COMPONENTS + Support + ) diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp index dd47ac7cbe3c..b6e8f8806829 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -1327,7 +1327,8 @@ ABISysV_arm::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (vendor_type != llvm::Triple::Apple) { if ((arch_type == llvm::Triple::arm) || (arch_type == llvm::Triple::thumb)) { - return ABISP(new ABISysV_arm(process_sp)); + return ABISP( + new ABISysV_arm(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1960,6 +1961,7 @@ bool ABISysV_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h index a0f00c8f227d..60fb14be5f7b 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h @@ -85,7 +85,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABISysV_arm(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_arm(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index 1d547121e231..89a1f2b3cf04 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -1668,8 +1668,10 @@ ABISysV_arm64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor(); if (vendor_type != llvm::Triple::Apple) { - if (arch_type == llvm::Triple::aarch64) { - return ABISP(new ABISysV_arm64(process_sp)); + if (arch_type == llvm::Triple::aarch64 || + arch_type == llvm::Triple::aarch64_32) { + return ABISP( + new ABISysV_arm64(std::move(process_sp), MakeMCRegisterInfo(arch))); } } @@ -1706,9 +1708,8 @@ bool ABISysV_arm64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%d (0x%" PRIx64 ") into %s", - static_cast<int>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%d (0x%" PRIx64 ") into %s", + static_cast<int>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } @@ -1958,6 +1959,7 @@ bool ABISysV_arm64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm64 at-func-entry default"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } @@ -1982,6 +1984,7 @@ bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("arm64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h index 1fbdc793ed6e..1bf5773e2db3 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h @@ -92,7 +92,9 @@ protected: lldb_private::CompilerType &ast_type) const override; private: - ABISysV_arm64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_arm64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp index 93647564fe25..34d9258ccb92 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp @@ -1014,7 +1014,8 @@ size_t ABISysV_hexagon::GetRedZoneSize() const { return 0; } ABISP ABISysV_hexagon::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::hexagon) { - return ABISP(new ABISysV_hexagon(process_sp)); + return ABISP( + new ABISysV_hexagon(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -1247,6 +1248,7 @@ bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("hexagon default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h index 459b6315dba2..bef64a22d95f 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h @@ -97,7 +97,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_hexagon(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_hexagon(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 05f5dba90687..69e4cff90ebf 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -198,7 +198,8 @@ ABISP ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getVendor() != llvm::Triple::Apple) { if (arch.GetTriple().getArch() == llvm::Triple::x86) { - return ABISP(new ABISysV_i386(process_sp)); + return ABISP( + new ABISysV_i386(std::move(process_sp), MakeMCRegisterInfo(arch))); } } return ABISP(); @@ -785,6 +786,7 @@ bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("i386 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h index 982bdd676b74..2362e9adda98 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h @@ -100,7 +100,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_i386(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_i386(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index 121c7300b968..416db9f5ae87 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -556,7 +556,8 @@ ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch(); if ((arch_type == llvm::Triple::mips) || (arch_type == llvm::Triple::mipsel)) { - return ABISP(new ABISysV_mips(process_sp)); + return ABISP( + new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -600,9 +601,8 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, - args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, + args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; @@ -630,9 +630,8 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, size_t i = 4; for (; ai != ae; ++ai) { reg_value.SetUInt32(*ai); - if (log) - log->Printf("About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "", - i + 1, args[i], arg_pos); + LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "", + i + 1, args[i], arg_pos); if (reg_ctx ->WriteRegisterValueToMemory(reg_info, arg_pos, @@ -654,8 +653,7 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0); - if (log) - log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0); + LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0); /* Write r0 with 0, in case we are stopped in syscall, * such setting prevents automatic decrement of the PC. @@ -664,29 +662,25 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0)) return false; - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); // Set "sp" to the requested value if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; - if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr); // Set "ra" to the return address if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) return false; - if (log) - log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr); // Set pc to the address of the called function. if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; - if (log) - log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr); // All callers of position independent functions must place the address of // the called function in t9 (r25) @@ -997,6 +991,7 @@ bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("mips default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h index 6cd9c19c22ac..8143f552fc4d 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h @@ -87,7 +87,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_mips(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index 18011cfb6b9e..72ec0715b6cd 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -554,7 +554,8 @@ size_t ABISysV_mips64::GetRedZoneSize() const { return 0; } ABISP ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().isMIPS64()) - return ABISP(new ABISysV_mips64(process_sp)); + return ABISP( + new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch))); return ABISP(); } @@ -589,18 +590,16 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, - args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, + args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -614,8 +613,7 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp, const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0); - if (log) - log->Printf("Writing R0: 0x%" PRIx64, (uint64_t)0); + LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0); /* Write r0 with 0, in case we are stopped in syscall, * such setting prevents automatic decrement of the PC. @@ -624,29 +622,25 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0)) return false; - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); // Set "sp" to the requested value if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; - if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr); // Set "ra" to the return address if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) return false; - if (log) - log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr); // Set pc to the address of the called function. if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; - if (log) - log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr); // All callers of position independent functions must place the address of // the called function in t9 (r25) @@ -1168,6 +1162,7 @@ bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("mips64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h index 7da71b36b4b7..76c3c5413b92 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h @@ -100,7 +100,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_mips64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index faa995033ac2..857b7fee10e3 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -218,7 +218,8 @@ size_t ABISysV_ppc::GetRedZoneSize() const { return 224; } ABISP ABISysV_ppc::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::ppc) { - return ABISP(new ABISysV_ppc(process_sp)); + return ABISP( + new ABISysV_ppc(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -255,18 +256,16 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -281,10 +280,10 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, RegisterValue reg_value; - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - ": 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + ": 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); // Save return address onto the stack if (!process_sp->WritePointerToMemory(sp, return_addr, error)) @@ -292,16 +291,14 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, // %r1 is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %pc is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; @@ -910,6 +907,7 @@ bool ABISysV_ppc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("ppc default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h index 3b199852c30d..59907c4648ba 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h @@ -96,7 +96,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_ppc(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index aa7907550f29..935353c38ca4 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -70,7 +70,8 @@ ABISP ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().isPPC64()) - return ABISP(new ABISysV_ppc64(process_sp)); + return ABISP( + new ABISysV_ppc64(std::move(process_sp), MakeMCRegisterInfo(arch))); return ABISP(); } @@ -106,18 +107,16 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -136,22 +135,20 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(12); // Save return address onto the stack. - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - "(+16): 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + "(+16): 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); if (!process_sp->WritePointerToMemory(sp + 16, return_addr, error)) return false; // Write the return address to link register. - if (log) - log->Printf("Writing LR: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing LR: 0x%" PRIx64, (uint64_t)return_addr); if (!reg_ctx->WriteRegisterFromUnsigned(lr_reg_info, return_addr)) return false; // Write target address to %r12 register. - if (log) - log->Printf("Writing R12: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing R12: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr)) return false; @@ -165,10 +162,9 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, else stack_offset = 40; - if (log) - log->Printf("Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64, - (uint64_t)(sp + stack_offset), (int)stack_offset, - (uint64_t)reg_value); + LLDB_LOGF(log, "Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64, + (uint64_t)(sp + stack_offset), (int)stack_offset, + (uint64_t)reg_value); if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error)) return false; @@ -176,23 +172,20 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0); // Save current SP onto the stack. - if (log) - log->Printf("Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp, - (uint64_t)reg_value); + LLDB_LOGF(log, "Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp, + (uint64_t)reg_value); if (!process_sp->WritePointerToMemory(sp, reg_value, error)) return false; // %r1 is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %pc is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; @@ -1017,6 +1010,7 @@ bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("ppc64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(pc_reg_num); return true; } diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h index d5fb09eec0d0..1b58975dd9d9 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h @@ -96,7 +96,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_ppc64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp index abe847b386a8..f4f803a8277d 100644 --- a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp +++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp @@ -200,7 +200,7 @@ size_t ABISysV_s390x::GetRedZoneSize() const { return 0; } ABISP ABISysV_s390x::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::systemz) { - return ABISP(new ABISysV_s390x(process_sp)); + return ABISP(new ABISysV_s390x(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -252,16 +252,14 @@ bool ABISysV_s390x::PrepareTrivialCall(Thread &thread, addr_t sp, if (i < 5) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } else { Status error; - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") onto stack", - static_cast<uint64_t>(i + 1), args[i]); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") onto stack", + static_cast<uint64_t>(i + 1), args[i]); if (!process_sp->WritePointerToMemory(arg_pos, args[i], error)) return false; arg_pos += 8; @@ -270,24 +268,21 @@ bool ABISysV_s390x::PrepareTrivialCall(Thread &thread, addr_t sp, // %r14 is set to the return address - if (log) - log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr); if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) return false; // %r15 is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %pc is set to the address of the called function. - if (log) - log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h index 13df477e84bc..671d6a18260e 100644 --- a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h +++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h @@ -88,7 +88,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_s390x(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_s390x(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 6c7b45f63399..bf1c48f778e1 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -222,17 +222,35 @@ ABISP ABISysV_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch(); const llvm::Triple::OSType os_type = arch.GetTriple().getOS(); + const llvm::Triple::EnvironmentType os_env = + arch.GetTriple().getEnvironment(); if (arch_type == llvm::Triple::x86_64) { switch(os_type) { - case llvm::Triple::OSType::MacOSX: - case llvm::Triple::OSType::Linux: - case llvm::Triple::OSType::FreeBSD: - case llvm::Triple::OSType::NetBSD: - case llvm::Triple::OSType::Solaris: - case llvm::Triple::OSType::UnknownOS: - return ABISP(new ABISysV_x86_64(process_sp)); - default: + case llvm::Triple::OSType::IOS: + case llvm::Triple::OSType::TvOS: + case llvm::Triple::OSType::WatchOS: + switch (os_env) { + case llvm::Triple::EnvironmentType::MacABI: + case llvm::Triple::EnvironmentType::Simulator: + case llvm::Triple::EnvironmentType::UnknownEnvironment: + // UnknownEnvironment is needed for older compilers that don't + // support the simulator environment. + return ABISP(new ABISysV_x86_64(std::move(process_sp), + MakeMCRegisterInfo(arch))); + default: return ABISP(); + } + case llvm::Triple::OSType::Darwin: + case llvm::Triple::OSType::FreeBSD: + case llvm::Triple::OSType::Linux: + case llvm::Triple::OSType::MacOSX: + case llvm::Triple::OSType::NetBSD: + case llvm::Triple::OSType::Solaris: + case llvm::Triple::OSType::UnknownOS: + return ABISP( + new ABISysV_x86_64(std::move(process_sp), MakeMCRegisterInfo(arch))); + default: + return ABISP(); } } return ABISP(); @@ -270,18 +288,16 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -295,10 +311,10 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, ProcessSP process_sp(thread.GetProcess()); RegisterValue reg_value; - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - ": 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + ": 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); // Save return address onto the stack if (!process_sp->WritePointerToMemory(sp, return_addr, error)) @@ -306,16 +322,14 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, // %rsp is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %rip is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; @@ -1034,6 +1048,7 @@ bool ABISysV_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("x86_64 default unwind plan"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index f6704aff348c..d445d8f4142a 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -98,7 +98,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABISysV_x86_64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABISysV_x86_64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp index 5dc7717d865d..ac24426914e1 100644 --- a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp +++ b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.cpp @@ -1092,7 +1092,8 @@ ABISP ABIWindows_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { if (arch.GetTriple().getArch() == llvm::Triple::x86_64 && arch.GetTriple().isOSWindows()) { - return ABISP(new ABIWindows_x86_64(process_sp)); + return ABISP( + new ABIWindows_x86_64(std::move(process_sp), MakeMCRegisterInfo(arch))); } return ABISP(); } @@ -1129,18 +1130,16 @@ bool ABIWindows_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); - if (log) - log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", - static_cast<uint64_t>(i + 1), args[i], reg_info->name); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast<uint64_t>(i + 1), args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP - if (log) - log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, - (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment @@ -1154,10 +1153,10 @@ bool ABIWindows_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, ProcessSP process_sp(thread.GetProcess()); RegisterValue reg_value; - if (log) - log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 - ": 0x%" PRIx64, - (uint64_t)sp, (uint64_t)return_addr); + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + ": 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); // Save return address onto the stack if (!process_sp->WritePointerToMemory(sp, return_addr, error)) @@ -1165,16 +1164,14 @@ bool ABIWindows_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, // %rsp is set to the actual stack value. - if (log) - log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) return false; // %rip is set to the address of the called function. - if (log) - log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) return false; diff --git a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h index 9f6b2ceef299..2366566d7809 100644 --- a/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h +++ b/source/Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h @@ -91,7 +91,9 @@ protected: bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); private: - ABIWindows_x86_64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) { + ABIWindows_x86_64(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up) + : lldb_private::ABI(std::move(process_sp), std::move(info_up)) { // Call CreateInstance instead. } }; diff --git a/source/Plugins/Architecture/Mips/ArchitectureMips.cpp b/source/Plugins/Architecture/Mips/ArchitectureMips.cpp index 60f1a2eb7572..5f2f6eeb8261 100644 --- a/source/Plugins/Architecture/Mips/ArchitectureMips.cpp +++ b/source/Plugins/Architecture/Mips/ArchitectureMips.cpp @@ -127,10 +127,10 @@ lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr, // Adjust the breakable address uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize(); - if (log) - log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64 - " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n", - __FUNCTION__, addr, breakable_addr); + LLDB_LOGF(log, + "Target::%s Breakpoint at 0x%8.8" PRIx64 + " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n", + __FUNCTION__, addr, breakable_addr); return breakable_addr; } diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 44c75fc953c8..28c9de2c1e96 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -381,11 +381,10 @@ public: static RegularExpression s_regex( llvm::StringRef("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?")); - RegularExpression::Match matches(3); - + llvm::SmallVector<llvm::StringRef, 4> matches; if (s_regex.Execute(out_string, &matches)) { - matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); - matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); + m_opcode_name = matches[1].str(); + m_mnemonics = matches[2].str(); } } } @@ -1190,10 +1189,12 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, // If any AArch64 variant, enable the ARMv8.5 ISA with SVE extensions so we // can disassemble newer instructions. - if (triple.getArch() == llvm::Triple::aarch64) + if (triple.getArch() == llvm::Triple::aarch64 || + triple.getArch() == llvm::Triple::aarch64_32) features_str += "+v8.5a,+sve2"; - if (triple.getArch() == llvm::Triple::aarch64 + if ((triple.getArch() == llvm::Triple::aarch64 || + triple.getArch() == llvm::Triple::aarch64_32) && triple.getVendor() == llvm::Triple::Apple) { cpu = "apple-latest"; } diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 23c8416f4986..5b19647a27ba 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -277,8 +277,7 @@ bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() { // Do not try to set the breakpoint if we don't know where to put it if (break_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Unable to locate _rtld_debug_state breakpoint address"); + LLDB_LOGF(log, "Unable to locate _rtld_debug_state breakpoint address"); return false; } @@ -301,7 +300,7 @@ bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() { .GetID() == m_dyld_bid); if (log && dyld_break == nullptr) - log->Printf("Failed to create _rtld_debug_state breakpoint"); + LLDB_LOGF(log, "Failed to create _rtld_debug_state breakpoint"); // check we have successfully set bp return (dyld_break != nullptr); @@ -316,8 +315,7 @@ bool DynamicLoaderHexagonDYLD::RendezvousBreakpointHit( user_id_t break_loc_id) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("Rendezvous breakpoint hit!"); + LLDB_LOGF(log, "Rendezvous breakpoint hit!"); DynamicLoaderHexagonDYLD *dyld_instance = nullptr; dyld_instance = static_cast<DynamicLoaderHexagonDYLD *>(baton); @@ -333,11 +331,9 @@ bool DynamicLoaderHexagonDYLD::RendezvousBreakpointHit( if (structAddr != LLDB_INVALID_ADDRESS) { dyld_instance->m_rendezvous.SetRendezvousAddress(structAddr); - if (log) - log->Printf("Found _rtld_debug structure @ 0x%08" PRIx64, structAddr); + LLDB_LOGF(log, "Found _rtld_debug structure @ 0x%08" PRIx64, structAddr); } else { - if (log) - log->Printf("Unable to resolve the _rtld_debug structure"); + LLDB_LOGF(log, "Unable to resolve the _rtld_debug structure"); } } @@ -375,11 +371,11 @@ void DynamicLoaderHexagonDYLD::RefreshModules() { } if (log) { - log->Printf("Target is loading '%s'", I->path.c_str()); + LLDB_LOGF(log, "Target is loading '%s'", I->path.c_str()); if (!module_sp.get()) - log->Printf("LLDB failed to load '%s'", I->path.c_str()); + LLDB_LOGF(log, "LLDB failed to load '%s'", I->path.c_str()); else - log->Printf("LLDB successfully loaded '%s'", I->path.c_str()); + LLDB_LOGF(log, "LLDB successfully loaded '%s'", I->path.c_str()); } } m_process->GetTarget().ModulesDidLoad(new_modules); @@ -400,8 +396,7 @@ void DynamicLoaderHexagonDYLD::RefreshModules() { UnloadSections(module_sp); } - if (log) - log->Printf("Target is unloading '%s'", I->path.c_str()); + LLDB_LOGF(log, "Target is unloading '%s'", I->path.c_str()); } loaded_modules.Remove(old_modules); m_process->GetTarget().ModulesDidUnload(old_modules, false); @@ -472,10 +467,10 @@ void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() { if (!m_rendezvous.Resolve()) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf( - "DynamicLoaderHexagonDYLD::%s unable to resolve rendezvous address", - __FUNCTION__); + LLDB_LOGF( + log, + "DynamicLoaderHexagonDYLD::%s unable to resolve rendezvous address", + __FUNCTION__); return; } @@ -493,10 +488,10 @@ void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() { module_list.Append(module_sp); } else { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderHexagonDYLD::%s failed loading module %s at " - "0x%" PRIx64, - __FUNCTION__, module_path, I->base_addr); + LLDB_LOGF(log, + "DynamicLoaderHexagonDYLD::%s failed loading module %s at " + "0x%" PRIx64, + __FUNCTION__, module_path, I->base_addr); } } @@ -604,12 +599,11 @@ DynamicLoaderHexagonDYLD::GetThreadLocalData(const lldb::ModuleSP module, Module *mod = module.get(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderHexagonDYLD::Performed TLS lookup: " - "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 - ", modid=%i, tls_block=0x%" PRIx64, - mod->GetObjectName().AsCString(""), link_map, tp, modid, - tls_block); + LLDB_LOGF(log, + "DynamicLoaderHexagonDYLD::Performed TLS lookup: " + "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 + ", modid=%i, tls_block=0x%" PRIx64, + mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block); if (tls_block == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp index 844a06c2b37d..f4788816d4ea 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp @@ -290,8 +290,9 @@ bool HexagonDYLDRendezvous::FindMetadata(const char *name, PThreadField field, Target &target = m_process->GetTarget(); SymbolContextList list; - if (!target.GetImages().FindSymbolsWithNameAndType(ConstString(name), - eSymbolTypeAny, list)) + target.GetImages().FindSymbolsWithNameAndType(ConstString(name), + eSymbolTypeAny, list); + if (list.IsEmpty()) return false; Address address = list[0].symbol->GetAddress(); @@ -339,16 +340,16 @@ void HexagonDYLDRendezvous::DumpToLog(Log *log) const { return; log->PutCString("HexagonDYLDRendezvous:"); - log->Printf(" Address: %" PRIx64, GetRendezvousAddress()); - log->Printf(" Version: %" PRIu64, GetVersion()); - log->Printf(" Link : %" PRIx64, GetLinkMapAddress()); - log->Printf(" Break : %" PRIx64, GetBreakAddress()); - log->Printf(" LDBase : %" PRIx64, GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) - ? "consistent" - : (state == eAdd) ? "add" : (state == eDelete) ? "delete" - : "unknown"); + LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress()); + LLDB_LOGF(log, " Version: %" PRIu64, GetVersion()); + LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress()); + LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress()); + LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase()); + LLDB_LOGF(log, " State : %s", + (state == eConsistent) + ? "consistent" + : (state == eAdd) ? "add" + : (state == eDelete) ? "delete" : "unknown"); iterator I = begin(); iterator E = end(); @@ -357,11 +358,11 @@ void HexagonDYLDRendezvous::DumpToLog(Log *log) const { log->PutCString("HexagonDYLDRendezvous SOEntries:"); for (int i = 1; I != E; ++I, ++i) { - log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); - log->Printf(" Base : %" PRIx64, I->base_addr); - log->Printf(" Path : %" PRIx64, I->path_addr); - log->Printf(" Dyn : %" PRIx64, I->dyn_addr); - log->Printf(" Next : %" PRIx64, I->next); - log->Printf(" Prev : %" PRIx64, I->prev); + LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->path.c_str()); + LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr); + LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr); + LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr); + LLDB_LOGF(log, " Next : %" PRIx64, I->next); + LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); } } diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 0d736738ebb5..737599303a60 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -33,16 +33,14 @@ static addr_t ResolveRendezvousAddress(Process *process) { Status error; if (!process) { - if (log) - log->Printf("%s null process provided", __FUNCTION__); + LLDB_LOGF(log, "%s null process provided", __FUNCTION__); return LLDB_INVALID_ADDRESS; } // Try to get it from our process. This might be a remote process and might // grab it via some remote-specific mechanism. info_location = process->GetImageInfoAddress(); - if (log) - log->Printf("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); + LLDB_LOGF(log, "%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); // If the process fails to return an address, fall back to seeing if the // local object file can help us find it. @@ -54,42 +52,38 @@ static addr_t ResolveRendezvousAddress(Process *process) { if (addr.IsValid()) { info_location = addr.GetLoadAddress(target); - if (log) - log->Printf( - "%s resolved via direct object file approach to 0x%" PRIx64, - __FUNCTION__, info_location); + LLDB_LOGF(log, + "%s resolved via direct object file approach to 0x%" PRIx64, + __FUNCTION__, info_location); } else { - if (log) - log->Printf("%s FAILED - direct object file approach did not yield a " - "valid address", - __FUNCTION__); + LLDB_LOGF(log, + "%s FAILED - direct object file approach did not yield a " + "valid address", + __FUNCTION__); } } } if (info_location == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("%s FAILED - invalid info address", __FUNCTION__); + LLDB_LOGF(log, "%s FAILED - invalid info address", __FUNCTION__); return LLDB_INVALID_ADDRESS; } - if (log) - log->Printf("%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, - __FUNCTION__, process->GetAddressByteSize(), info_location); + LLDB_LOGF(log, "%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, + __FUNCTION__, process->GetAddressByteSize(), info_location); info_addr = process->ReadPointerFromMemory(info_location, error); if (error.Fail()) { - if (log) - log->Printf("%s FAILED - could not read from the info location: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "%s FAILED - could not read from the info location: %s", + __FUNCTION__, error.AsCString()); return LLDB_INVALID_ADDRESS; } if (info_addr == 0) { - if (log) - log->Printf("%s FAILED - the rendezvous address contained at 0x%" PRIx64 - " returned a null value", - __FUNCTION__, info_location); + LLDB_LOGF(log, + "%s FAILED - the rendezvous address contained at 0x%" PRIx64 + " returned a null value", + __FUNCTION__, info_location); return LLDB_INVALID_ADDRESS; } @@ -109,14 +103,13 @@ DYLDRendezvous::DYLDRendezvous(Process *process) Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer(); if (exe_mod) { m_exe_file_spec = exe_mod->GetPlatformFileSpec(); - if (log) - log->Printf("DYLDRendezvous::%s exe module executable path set: '%s'", - __FUNCTION__, m_exe_file_spec.GetCString()); + LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'", + __FUNCTION__, m_exe_file_spec.GetCString()); } else { - if (log) - log->Printf("DYLDRendezvous::%s cannot cache exe module path: null " - "executable module pointer", - __FUNCTION__); + LLDB_LOGF(log, + "DYLDRendezvous::%s cannot cache exe module path: null " + "executable module pointer", + __FUNCTION__); } } } @@ -133,17 +126,16 @@ bool DYLDRendezvous::Resolve() { address_size = m_process->GetAddressByteSize(); padding = address_size - word_size; - if (log) - log->Printf("DYLDRendezvous::%s address size: %" PRIu64 - ", padding %" PRIu64, - __FUNCTION__, uint64_t(address_size), uint64_t(padding)); + LLDB_LOGF(log, + "DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64, + __FUNCTION__, uint64_t(address_size), uint64_t(padding)); if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) cursor = info_addr = ResolveRendezvousAddress(m_process); else cursor = info_addr = m_rendezvous_addr; - if (log) - log->Printf("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor); + LLDB_LOGF(log, "DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, + cursor); if (cursor == LLDB_INVALID_ADDRESS) return false; @@ -168,7 +160,10 @@ bool DYLDRendezvous::Resolve() { m_previous = m_current; m_current = info; - if (UpdateSOEntries(true)) + if (m_current.map_addr == 0) + return false; + + if (UpdateSOEntriesFromRemote()) return true; return UpdateSOEntries(); @@ -178,53 +173,91 @@ bool DYLDRendezvous::IsValid() { return m_rendezvous_addr != LLDB_INVALID_ADDRESS; } -bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) { - SOEntry entry; - LoadedModuleInfoList module_list; +DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { + switch (m_current.state) { + + case eConsistent: + switch (m_previous.state) { + // When the previous and current states are consistent this is the first + // time we have been asked to update. Just take a snapshot of the + // currently loaded modules. + case eConsistent: + return eTakeSnapshot; + // If we are about to add or remove a shared object clear out the current + // state and take a snapshot of the currently loaded images. + case eAdd: + return eAddModules; + case eDelete: + return eRemoveModules; + } + break; - // If we can't get the SO info from the remote, return failure. - if (fromRemote && m_process->LoadModules(module_list) == 0) - return false; + case eAdd: + case eDelete: + // Some versions of the android dynamic linker might send two + // notifications with state == eAdd back to back. Ignore them until we + // get an eConsistent notification. + if (!(m_previous.state == eConsistent || + (m_previous.state == eAdd && m_current.state == eDelete))) + return eNoAction; + + return eTakeSnapshot; + } + + return eNoAction; +} + +bool DYLDRendezvous::UpdateSOEntriesFromRemote() { + auto action = GetAction(); - if (!fromRemote && m_current.map_addr == 0) + if (action == eNoAction) return false; - // When the previous and current states are consistent this is the first time - // we have been asked to update. Just take a snapshot of the currently - // loaded modules. - if (m_previous.state == eConsistent && m_current.state == eConsistent) - return fromRemote ? SaveSOEntriesFromRemote(module_list) - : TakeSnapshot(m_soentries); - - // If we are about to add or remove a shared object clear out the current - // state and take a snapshot of the currently loaded images. - if (m_current.state == eAdd || m_current.state == eDelete) { - // Some versions of the android dynamic linker might send two notifications - // with state == eAdd back to back. Ignore them until we get an eConsistent - // notification. - if (!(m_previous.state == eConsistent || - (m_previous.state == eAdd && m_current.state == eDelete))) - return false; + if (action == eTakeSnapshot) { + m_added_soentries.clear(); + m_removed_soentries.clear(); + // We already have the loaded list from the previous update so no need to + // find all the modules again. + if (!m_loaded_modules.m_list.empty()) + return true; + } + + llvm::Expected<LoadedModuleInfoList> module_list = + m_process->GetLoadedModuleList(); + if (!module_list) { + llvm::consumeError(module_list.takeError()); + return false; + } + switch (action) { + case eTakeSnapshot: m_soentries.clear(); - if (fromRemote) - return SaveSOEntriesFromRemote(module_list); + return SaveSOEntriesFromRemote(*module_list); + case eAddModules: + return AddSOEntriesFromRemote(*module_list); + case eRemoveModules: + return RemoveSOEntriesFromRemote(*module_list); + case eNoAction: + return false; + } + llvm_unreachable("Fully covered switch above!"); +} +bool DYLDRendezvous::UpdateSOEntries() { + switch (GetAction()) { + case eTakeSnapshot: + m_soentries.clear(); m_added_soentries.clear(); m_removed_soentries.clear(); return TakeSnapshot(m_soentries); + case eAddModules: + return AddSOEntries(); + case eRemoveModules: + return RemoveSOEntries(); + case eNoAction: + return false; } - assert(m_current.state == eConsistent); - - // Otherwise check the previous state to determine what to expect and update - // accordingly. - if (m_previous.state == eAdd) - return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries(); - else if (m_previous.state == eDelete) - return fromRemote ? RemoveSOEntriesFromRemote(module_list) - : RemoveSOEntries(); - - return false; + llvm_unreachable("Fully covered switch above!"); } bool DYLDRendezvous::FillSOEntryFromModuleInfo( @@ -255,7 +288,7 @@ bool DYLDRendezvous::FillSOEntryFromModuleInfo( } bool DYLDRendezvous::SaveSOEntriesFromRemote( - LoadedModuleInfoList &module_list) { + const LoadedModuleInfoList &module_list) { for (auto const &modInfo : module_list.m_list) { SOEntry entry; if (!FillSOEntryFromModuleInfo(modInfo, entry)) @@ -270,7 +303,8 @@ bool DYLDRendezvous::SaveSOEntriesFromRemote( return true; } -bool DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list) { +bool DYLDRendezvous::AddSOEntriesFromRemote( + const LoadedModuleInfoList &module_list) { for (auto const &modInfo : module_list.m_list) { bool found = false; for (auto const &existing : m_loaded_modules.m_list) { @@ -288,8 +322,10 @@ bool DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list) { return false; // Only add shared libraries and not the executable. - if (!SOEntryIsMainExecutable(entry)) + if (!SOEntryIsMainExecutable(entry)) { m_soentries.push_back(entry); + m_added_soentries.push_back(entry); + } } m_loaded_modules = module_list; @@ -297,7 +333,7 @@ bool DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list) { } bool DYLDRendezvous::RemoveSOEntriesFromRemote( - LoadedModuleInfoList &module_list) { + const LoadedModuleInfoList &module_list) { for (auto const &existing : m_loaded_modules.m_list) { bool found = false; for (auto const &modInfo : module_list.m_list) { @@ -321,6 +357,7 @@ bool DYLDRendezvous::RemoveSOEntriesFromRemote( return false; m_soentries.erase(pos); + m_removed_soentries.push_back(entry); } } @@ -521,9 +558,10 @@ bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field, Target &target = m_process->GetTarget(); SymbolContextList list; - if (!target.GetImages().FindSymbolsWithNameAndType(ConstString(name), - eSymbolTypeAny, list)) - return false; + target.GetImages().FindSymbolsWithNameAndType(ConstString(name), + eSymbolTypeAny, list); + if (list.IsEmpty()) + return false; Address address = list[0].symbol->GetAddress(); addr_t addr = address.GetLoadAddress(&target); @@ -569,16 +607,16 @@ void DYLDRendezvous::DumpToLog(Log *log) const { return; log->PutCString("DYLDRendezvous:"); - log->Printf(" Address: %" PRIx64, GetRendezvousAddress()); - log->Printf(" Version: %" PRIu64, GetVersion()); - log->Printf(" Link : %" PRIx64, GetLinkMapAddress()); - log->Printf(" Break : %" PRIx64, GetBreakAddress()); - log->Printf(" LDBase : %" PRIx64, GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) - ? "consistent" - : (state == eAdd) ? "add" : (state == eDelete) ? "delete" - : "unknown"); + LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress()); + LLDB_LOGF(log, " Version: %" PRIu64, GetVersion()); + LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress()); + LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress()); + LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase()); + LLDB_LOGF(log, " State : %s", + (state == eConsistent) + ? "consistent" + : (state == eAdd) ? "add" + : (state == eDelete) ? "delete" : "unknown"); iterator I = begin(); iterator E = end(); @@ -587,11 +625,11 @@ void DYLDRendezvous::DumpToLog(Log *log) const { log->PutCString("DYLDRendezvous SOEntries:"); for (int i = 1; I != E; ++I, ++i) { - log->Printf("\n SOEntry [%d] %s", i, I->file_spec.GetCString()); - log->Printf(" Base : %" PRIx64, I->base_addr); - log->Printf(" Path : %" PRIx64, I->path_addr); - log->Printf(" Dyn : %" PRIx64, I->dyn_addr); - log->Printf(" Next : %" PRIx64, I->next); - log->Printf(" Prev : %" PRIx64, I->prev); + LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetCString()); + LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr); + LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr); + LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr); + LLDB_LOGF(log, " Next : %" PRIx64, I->next); + LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); } } diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index 993e62f5e9f9..536eeeaaf334 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -222,16 +222,20 @@ protected: /// Updates the current set of SOEntries, the set of added entries, and the /// set of removed entries. - bool UpdateSOEntries(bool fromRemote = false); + bool UpdateSOEntries(); + + /// Same as UpdateSOEntries but it gets the list of loaded modules from the + /// remote debug server (faster when supported). + bool UpdateSOEntriesFromRemote(); bool FillSOEntryFromModuleInfo( LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry); - bool SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool SaveSOEntriesFromRemote(const LoadedModuleInfoList &module_list); - bool AddSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool AddSOEntriesFromRemote(const LoadedModuleInfoList &module_list); - bool RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list); + bool RemoveSOEntriesFromRemote(const LoadedModuleInfoList &module_list); bool AddSOEntries(); @@ -248,6 +252,17 @@ protected: enum PThreadField { eSize, eNElem, eOffset }; bool FindMetadata(const char *name, PThreadField field, uint32_t &value); + + enum RendezvousAction { + eNoAction, + eTakeSnapshot, + eAddModules, + eRemoveModules + }; + + /// Returns the current action to be taken given the current and previous + /// state + RendezvousAction GetAction() const; }; #endif diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index b55660899d0d..9d61c8feb923 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -85,32 +85,31 @@ DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() { void DynamicLoaderPOSIXDYLD::DidAttach() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); - m_auxv = llvm::make_unique<AuxVector>(m_process->GetAuxvData()); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData()); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF( + log, "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", + __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); // ask the process if it can load any of its own modules - m_process->LoadModules(); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "Couldn't load modules: {0}"); ModuleSP executable_sp = GetTargetExecutable(); ResolveExecutableModule(executable_sp); // find the main process load offset addr_t load_offset = ComputeLoadOffset(); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " executable '%s', load_offset 0x%" PRIx64, - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - executable_sp ? executable_sp->GetFileSpec().GetPath().c_str() - : "<null executable>", - load_offset); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " executable '%s', load_offset 0x%" PRIx64, + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + executable_sp ? executable_sp->GetFileSpec().GetPath().c_str() + : "<null executable>", + load_offset); EvalSpecialModulesStatus(); @@ -137,12 +136,12 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { ModuleList module_list; module_list.Append(executable_sp); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " added executable '%s' to module load list", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - executable_sp->GetFileSpec().GetPath().c_str()); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " added executable '%s' to module load list", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + executable_sp->GetFileSpec().GetPath().c_str()); UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true); @@ -151,14 +150,15 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { m_process->GetTarget().ModulesDidLoad(module_list); if (log) { - log->Printf("DynamicLoaderPOSIXDYLD::%s told the target about the " - "modules that loaded:", - __FUNCTION__); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s told the target about the " + "modules that loaded:", + __FUNCTION__); for (auto module_sp : module_list.Modules()) { - log->Printf("-- [module] %s (pid %" PRIu64 ")", - module_sp ? module_sp->GetFileSpec().GetPath().c_str() - : "<null>", - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF(log, "-- [module] %s (pid %" PRIu64 ")", + module_sp ? module_sp->GetFileSpec().GetPath().c_str() + : "<null>", + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); } } } @@ -174,13 +174,12 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { void DynamicLoaderPOSIXDYLD::DidLaunch() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); ModuleSP executable; addr_t load_offset; - m_auxv = llvm::make_unique<AuxVector>(m_process->GetAuxvData()); + m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData()); executable = GetTargetExecutable(); load_offset = ComputeLoadOffset(); @@ -191,9 +190,8 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() { module_list.Append(executable); UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", - __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", + __FUNCTION__); if (!SetRendezvousBreakpoint()) { // If we cannot establish rendezvous breakpoint right now we'll try again @@ -227,22 +225,20 @@ void DynamicLoaderPOSIXDYLD::ProbeEntry() { const addr_t entry = GetEntryPoint(); if (entry == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf( - "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " GetEntryPoint() returned no address, not setting entry breakpoint", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF( + log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " GetEntryPoint() returned no address, not setting entry breakpoint", + __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); return; } - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " GetEntryPoint() returned address 0x%" PRIx64 - ", setting entry breakpoint", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - entry); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " GetEntryPoint() returned address 0x%" PRIx64 + ", setting entry breakpoint", + __FUNCTION__, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, entry); if (m_process) { Breakpoint *const entry_break = @@ -271,11 +267,10 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD *>(baton); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, - __FUNCTION__, - dyld_instance->m_process ? dyld_instance->m_process->GetID() - : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID); // Disable the breakpoint --- if a stop happens right after this, which we've // seen on occasion, we don't want the breakpoint stepping thread-plan logic @@ -287,22 +282,22 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( BreakpointSP breakpoint_sp = dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id); if (breakpoint_sp) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " disabling breakpoint id %" PRIu64, - __FUNCTION__, dyld_instance->m_process->GetID(), break_id); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " disabling breakpoint id %" PRIu64, + __FUNCTION__, dyld_instance->m_process->GetID(), break_id); breakpoint_sp->SetEnabled(false); } else { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " failed to find breakpoint for breakpoint id %" PRIu64, - __FUNCTION__, dyld_instance->m_process->GetID(), break_id); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " failed to find breakpoint for breakpoint id %" PRIu64, + __FUNCTION__, dyld_instance->m_process->GetID(), break_id); } } else { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 - " no Process instance! Cannot disable breakpoint", - __FUNCTION__, break_id); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 + " no Process instance! Cannot disable breakpoint", + __FUNCTION__, break_id); } dyld_instance->LoadAllCurrentModules(); @@ -393,23 +388,22 @@ bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast<DynamicLoaderPOSIXDYLD *>(baton); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, - __FUNCTION__, - dyld_instance->m_process ? dyld_instance->m_process->GetID() - : LLDB_INVALID_PROCESS_ID); + LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID); dyld_instance->RefreshModules(); // Return true to stop the target, false to just let the target run. const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange(); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " stop_when_images_change=%s", - __FUNCTION__, - dyld_instance->m_process ? dyld_instance->m_process->GetID() - : LLDB_INVALID_PROCESS_ID, - stop_when_images_change ? "true" : "false"); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 + " stop_when_images_change=%s", + __FUNCTION__, + dyld_instance->m_process ? dyld_instance->m_process->GetID() + : LLDB_INVALID_PROCESS_ID, + stop_when_images_change ? "true" : "false"); return stop_when_images_change; } @@ -562,10 +556,10 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { LoadVDSO(); if (!m_rendezvous.Resolve()) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD " - "rendezvous address", - __FUNCTION__); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD " + "rendezvous address", + __FUNCTION__); return; } @@ -589,10 +583,10 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { module_list.Append(module_sp); } else { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf( - "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, - __FUNCTION__, I->file_spec.GetCString(), I->base_addr); + LLDB_LOGF( + log, + "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, + __FUNCTION__, I->file_spec.GetCString(), I->base_addr); } } @@ -697,12 +691,12 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: " - "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 - ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", - module_sp->GetObjectName().AsCString(""), link_map, tp, - (int64_t)modid, tls_block); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::Performed TLS lookup: " + "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 + ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", + module_sp->GetObjectName().AsCString(""), link_map, tp, + (int64_t)modid, tls_block); if (tls_block == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; @@ -722,18 +716,17 @@ void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( ProcessInstanceInfo process_info; if (!m_process->GetProcessInfo(process_info)) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to get process info for " - "pid %" PRIu64, - __FUNCTION__, m_process->GetID()); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s - failed to get process info for " + "pid %" PRIu64, + __FUNCTION__, m_process->GetID()); return; } - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 - ": %s", - __FUNCTION__, m_process->GetID(), - process_info.GetExecutableFile().GetPath().c_str()); + LLDB_LOGF( + log, "DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s", + __FUNCTION__, m_process->GetID(), + process_info.GetExecutableFile().GetPath().c_str()); ModuleSpec module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); @@ -748,10 +741,10 @@ void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( StreamString stream; module_spec.Dump(stream); - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to resolve executable " - "with module spec \"%s\": %s", - __FUNCTION__, stream.GetData(), error.AsCString()); + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s - failed to resolve executable " + "with module spec \"%s\": %s", + __FUNCTION__, stream.GetData(), error.AsCString()); return; } diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index fa3fbe0d9fa6..25ab30e9db9c 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -122,38 +122,37 @@ lldb::addr_t DynamicLoaderWindowsDYLD::GetLoadAddress(ModuleSP executable) { void DynamicLoaderWindowsDYLD::DidAttach() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); - ModuleSP executable = GetTargetExecutable(); + ModuleSP executable = GetTargetExecutable(); - if (!executable.get()) - return; + if (!executable.get()) + return; - // Try to fetch the load address of the file from the process, since there - // could be randomization of the load address. - lldb::addr_t load_addr = GetLoadAddress(executable); - if (load_addr == LLDB_INVALID_ADDRESS) - return; + // Try to fetch the load address of the file from the process, since there + // could be randomization of the load address. + lldb::addr_t load_addr = GetLoadAddress(executable); + if (load_addr == LLDB_INVALID_ADDRESS) + return; - // Request the process base address. - lldb::addr_t image_base = m_process->GetImageInfoAddress(); - if (image_base == load_addr) - return; + // Request the process base address. + lldb::addr_t image_base = m_process->GetImageInfoAddress(); + if (image_base == load_addr) + return; - // Rebase the process's modules if there is a mismatch. - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); + // Rebase the process's modules if there is a mismatch. + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); - ModuleList module_list; - module_list.Append(executable); - m_process->GetTarget().ModulesDidLoad(module_list); - m_process->LoadModules(); + ModuleList module_list; + module_list.Append(executable); + m_process->GetTarget().ModulesDidLoad(module_list); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); } void DynamicLoaderWindowsDYLD::DidLaunch() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); + LLDB_LOGF(log, "DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); ModuleSP executable = GetTargetExecutable(); if (!executable.get()) @@ -167,7 +166,8 @@ void DynamicLoaderWindowsDYLD::DidLaunch() { ModuleList module_list; module_list.Append(executable); m_process->GetTarget().ModulesDidLoad(module_list); - m_process->LoadModules(); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); } } diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp index 369f88327dd9..f33a713cc0b2 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -75,8 +75,6 @@ ASTDumper::ASTDumper(const CompilerType &compiler_type) { const char *ASTDumper::GetCString() { return m_dump.c_str(); } -void ASTDumper::ToSTDERR() { fprintf(stderr, "%s\n", m_dump.c_str()); } - void ASTDumper::ToLog(Log *log, const char *prefix) { size_t len = m_dump.length() + 1; @@ -92,7 +90,7 @@ void ASTDumper::ToLog(Log *log, const char *prefix) { while (end) { *end = '\0'; - log->Printf("%s%s", prefix, str); + LLDB_LOGF(log, "%s%s", prefix, str); *end = '\n'; @@ -100,9 +98,7 @@ void ASTDumper::ToLog(Log *log, const char *prefix) { end = strchr(str, '\n'); } - log->Printf("%s%s", prefix, str); + LLDB_LOGF(log, "%s%s", prefix, str); free(alloc); } - -void ASTDumper::ToStream(lldb::StreamSP &stream) { stream->PutCString(m_dump); } diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 526ef90782ef..68eaad33f51c 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -58,13 +58,13 @@ void ASTResultSynthesizer::TransformTopLevelDecl(Decl *D) { if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D)) { if (log && log->GetVerbose()) { if (named_decl->getIdentifier()) - log->Printf("TransformTopLevelDecl(%s)", - named_decl->getIdentifier()->getNameStart()); + LLDB_LOGF(log, "TransformTopLevelDecl(%s)", + named_decl->getIdentifier()->getNameStart()); else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) - log->Printf("TransformTopLevelDecl(%s)", - method_decl->getSelector().getAsString().c_str()); + LLDB_LOGF(log, "TransformTopLevelDecl(%s)", + method_decl->getSelector().getAsString().c_str()); else - log->Printf("TransformTopLevelDecl(<complex>)"); + LLDB_LOGF(log, "TransformTopLevelDecl(<complex>)"); } if (m_top_level) { @@ -130,7 +130,7 @@ bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl *FunDecl) { os.flush(); - log->Printf("Untransformed function AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Untransformed function AST:\n%s", s.c_str()); } Stmt *function_body = function_decl->getBody(); @@ -146,7 +146,7 @@ bool ASTResultSynthesizer::SynthesizeFunctionResult(FunctionDecl *FunDecl) { os.flush(); - log->Printf("Transformed function AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Transformed function AST:\n%s", s.c_str()); } return ret; @@ -170,7 +170,7 @@ bool ASTResultSynthesizer::SynthesizeObjCMethodResult( os.flush(); - log->Printf("Untransformed method AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Untransformed method AST:\n%s", s.c_str()); } Stmt *method_body = MethodDecl->getBody(); @@ -190,7 +190,7 @@ bool ASTResultSynthesizer::SynthesizeObjCMethodResult( os.flush(); - log->Printf("Transformed method AST:\n%s", s.c_str()); + LLDB_LOGF(log, "Transformed method AST:\n%s", s.c_str()); } return ret; @@ -308,8 +308,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, if (log) { std::string s = expr_qual_type.getAsString(); - log->Printf("Last statement is an %s with type: %s", - (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); + LLDB_LOGF(log, "Last statement is an %s with type: %s", + (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); } clang::VarDecl *result_decl = nullptr; @@ -422,8 +422,7 @@ void ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) { ConstString name_cs(name.str().c_str()); - if (log) - log->Printf("Recording persistent type %s\n", name_cs.GetCString()); + LLDB_LOGF(log, "Recording persistent type %s\n", name_cs.GetCString()); m_decls.push_back(D); } @@ -443,8 +442,7 @@ void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) { ConstString name_cs(name.str().c_str()); - if (log) - log->Printf("Recording persistent decl %s\n", name_cs.GetCString()); + LLDB_LOGF(log, "Recording persistent decl %s\n", name_cs.GetCString()); m_decls.push_back(D); } @@ -467,7 +465,7 @@ void ASTResultSynthesizer::CommitPersistentDecls() { decl->dump(ss); ss.flush(); - log->Printf("Couldn't commit persistent decl: %s\n", s.c_str()); + LLDB_LOGF(log, "Couldn't commit persistent decl: %s\n", s.c_str()); } continue; diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index c5778f86bb62..372c2439ebf0 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -9,6 +9,7 @@ #include "ClangASTSource.h" #include "ASTDumper.h" +#include "ClangDeclVendor.h" #include "ClangModulesDeclVendor.h" #include "lldb/Core/Module.h" @@ -18,7 +19,6 @@ #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TaggedASTType.h" #include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" @@ -74,14 +74,19 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, file_manager}; std::vector<clang::ExternalASTMerger::ImporterSource> sources; for (lldb::ModuleSP module_sp : m_target->GetImages().Modules()) { - if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>( - module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC))) { + auto type_system_or_err = + module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS), + std::move(err), "Failed to get ClangASTContext"); + } else if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>( + &type_system_or_err.get())) { lldbassert(module_ast_ctx->getASTContext()); lldbassert(module_ast_ctx->getFileManager()); - sources.push_back({*module_ast_ctx->getASTContext(), - *module_ast_ctx->getFileManager(), - module_ast_ctx->GetOriginMap() - }); + sources.emplace_back(*module_ast_ctx->getASTContext(), + *module_ast_ctx->getFileManager(), + module_ast_ctx->GetOriginMap()); } } @@ -96,17 +101,14 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, if (!language_runtime) break; - DeclVendor *runtime_decl_vendor = language_runtime->GetDeclVendor(); - - if (!runtime_decl_vendor) - break; - - sources.push_back(runtime_decl_vendor->GetImporterSource()); + if (auto *runtime_decl_vendor = llvm::dyn_cast_or_null<ClangDeclVendor>( + language_runtime->GetDeclVendor())) { + sources.push_back(runtime_decl_vendor->GetImporterSource()); + } } while (false); do { - DeclVendor *modules_decl_vendor = - m_target->GetClangModulesDeclVendor(); + auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); if (!modules_decl_vendor) break; @@ -127,11 +129,9 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, *scratch_ast_context->getFileManager(), scratch_ast_context->GetOriginMap()}); } - while (false) - ; m_merger_up = - llvm::make_unique<clang::ExternalASTMerger>(target, sources); + std::make_unique<clang::ExternalASTMerger>(target, sources); } else { m_ast_importer_sp->InstallMapCompleter(&ast_context, *this); } @@ -273,13 +273,13 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { unsigned int current_id = invocation_id++; if (log) { - log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing " - "(TagDecl*)%p named %s", - current_id, static_cast<void *>(m_ast_context), - static_cast<void *>(tag_decl), - tag_decl->getName().str().c_str()); + LLDB_LOGF(log, + " CompleteTagDecl[%u] on (ASTContext*)%p Completing " + "(TagDecl*)%p named %s", + current_id, static_cast<void *>(m_ast_context), + static_cast<void *>(tag_decl), tag_decl->getName().str().c_str()); - log->Printf(" CTD[%u] Before:", current_id); + LLDB_LOGF(log, " CTD[%u] Before:", current_id); ASTDumper dumper((Decl *)tag_decl); dumper.ToLog(log, " [CTD] "); } @@ -301,10 +301,10 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { // We couldn't complete the type. Maybe there's a definition somewhere // else that can be completed. - if (log) - log->Printf(" CTD[%u] Type could not be completed in the module in " - "which it was first found.", - current_id); + LLDB_LOGF(log, + " CTD[%u] Type could not be completed in the module in " + "which it was first found.", + current_id); bool found = false; @@ -316,9 +316,9 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { m_ast_importer_sp->GetNamespaceMap(namespace_context); if (log && log->GetVerbose()) - log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast<void *>(namespace_map.get()), - static_cast<int>(namespace_map->size())); + LLDB_LOGF(log, " CTD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast<void *>(namespace_map.get()), + static_cast<int>(namespace_map->size())); if (!namespace_map) return; @@ -326,10 +326,9 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e && !found; ++i) { - if (log) - log->Printf(" CTD[%u] Searching namespace %s in module %s", - current_id, i->second.GetName().AsCString(), - i->first->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CTD[%u] Searching namespace %s in module %s", + current_id, i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); TypeList types; @@ -409,7 +408,7 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { } if (log) { - log->Printf(" [CTD] After:"); + LLDB_LOGF(log, " [CTD] After:"); ASTDumper dumper((Decl *)tag_decl); dumper.ToLog(log, " [CTD] "); } @@ -419,11 +418,12 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (log) { - log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing " - "an ObjCInterfaceDecl named %s", - static_cast<void *>(m_ast_context), - interface_decl->getName().str().c_str()); - log->Printf(" [COID] Before:"); + LLDB_LOGF(log, + " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing " + "an ObjCInterfaceDecl named %s", + static_cast<void *>(m_ast_context), + interface_decl->getName().str().c_str()); + LLDB_LOGF(log, " [COID] Before:"); ASTDumper dumper((Decl *)interface_decl); dumper.ToLog(log, " [COID] "); } @@ -467,7 +467,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { CompleteType(interface_decl->getSuperClass()); if (log) { - log->Printf(" [COID] After:"); + LLDB_LOGF(log, " [COID] After:"); ASTDumper dumper((Decl *)interface_decl); dumper.ToLog(log, " [COID] "); } @@ -554,20 +554,22 @@ void ClangASTSource::FindExternalLexicalDecls( if (log) { if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) - log->Printf( + LLDB_LOGF( + log, "FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p", current_id, static_cast<void *>(m_ast_context), context_named_decl->getNameAsString().c_str(), context_decl->getDeclKindName(), static_cast<const void *>(context_decl)); else if (context_decl) - log->Printf( - "FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", + LLDB_LOGF( + log, "FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", current_id, static_cast<void *>(m_ast_context), context_decl->getDeclKindName(), static_cast<const void *>(context_decl)); else - log->Printf( + LLDB_LOGF( + log, "FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context", current_id, static_cast<const void *>(m_ast_context)); } @@ -580,9 +582,9 @@ void ClangASTSource::FindExternalLexicalDecls( return; if (log) { - log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", - current_id, static_cast<void *>(original_ctx), - static_cast<void *>(original_decl)); + LLDB_LOGF( + log, " FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", current_id, + static_cast<void *>(original_ctx), static_cast<void *>(original_decl)); ASTDumper(original_decl).ToLog(log, " "); } @@ -626,13 +628,13 @@ void ClangASTSource::FindExternalLexicalDecls( ASTDumper ast_dumper(decl); if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) - log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", - current_id, context_named_decl->getDeclKindName(), - context_named_decl->getNameAsString().c_str(), - decl->getDeclKindName(), ast_dumper.GetCString()); + LLDB_LOGF(log, " FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", + current_id, context_named_decl->getDeclKindName(), + context_named_decl->getNameAsString().c_str(), + decl->getDeclKindName(), ast_dumper.GetCString()); else - log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, - decl->getDeclKindName(), ast_dumper.GetCString()); + LLDB_LOGF(log, " FELD[%d] Adding lexical %sDecl %s", current_id, + decl->getDeclKindName(), ast_dumper.GetCString()); } Decl *copied_decl = CopyDecl(decl); @@ -645,6 +647,20 @@ void ClangASTSource::FindExternalLexicalDecls( m_ast_importer_sp->RequireCompleteType(copied_field_type); } + auto decl_context_non_const = const_cast<DeclContext *>(decl_context); + + // The decl ended up in the wrong DeclContext. Let's fix that so + // the decl we copied will actually be found. + // FIXME: This is a horrible hack that shouldn't be necessary. However + // it seems our current setup sometimes fails to copy decls to the right + // place. See rdar://55129537. + if (copied_decl->getDeclContext() != decl_context) { + assert(copied_decl->getDeclContext()->containsDecl(copied_decl)); + copied_decl->getDeclContext()->removeDecl(copied_decl); + copied_decl->setDeclContext(decl_context_non_const); + assert(!decl_context_non_const->containsDecl(copied_decl)); + decl_context_non_const->addDeclInternal(copied_decl); + } } else { SkippedDecls = true; } @@ -678,22 +694,25 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { if (log) { if (!context.m_decl_context) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " - "(ASTContext*)%p for '%s' in a NULL DeclContext", - current_id, static_cast<void *>(m_ast_context), - name.GetCString()); + LLDB_LOGF(log, + "ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in a NULL DeclContext", + current_id, static_cast<void *>(m_ast_context), + name.GetCString()); else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " - "(ASTContext*)%p for '%s' in '%s'", - current_id, static_cast<void *>(m_ast_context), - name.GetCString(), - context_named_decl->getNameAsString().c_str()); + LLDB_LOGF(log, + "ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in '%s'", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), + context_named_decl->getNameAsString().c_str()); else - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on " - "(ASTContext*)%p for '%s' in a '%s'", - current_id, static_cast<void *>(m_ast_context), - name.GetCString(), context.m_decl_context->getDeclKindName()); + LLDB_LOGF(log, + "ClangASTSource::FindExternalVisibleDecls[%u] on " + "(ASTContext*)%p for '%s' in a '%s'", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), context.m_decl_context->getDeclKindName()); } if (HasMerger() && !isa<TranslationUnitDecl>(context.m_decl_context) @@ -723,9 +742,9 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { m_ast_importer_sp->GetNamespaceMap(namespace_context) : nullptr; if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast<void *>(namespace_map.get()), - static_cast<int>(namespace_map->size())); + LLDB_LOGF(log, " CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast<void *>(namespace_map.get()), + static_cast<int>(namespace_map->size())); if (!namespace_map) return; @@ -733,10 +752,9 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e; ++i) { - if (log) - log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s", - current_id, i->second.GetName().AsCString(), - i->first->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CAS::FEVD[%u] Searching namespace %s in module %s", + current_id, i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); FindExternalVisibleDecls(context, i->first, i->second, current_id); } @@ -748,8 +766,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { } else { CompilerDeclContext namespace_decl; - if (log) - log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id); + LLDB_LOGF(log, " CAS::FEVD[%u] Searching the root namespace", current_id); FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl, current_id); @@ -757,10 +774,10 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { if (!context.m_namespace_map->empty()) { if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", - current_id, - static_cast<void *>(context.m_namespace_map.get()), - static_cast<int>(context.m_namespace_map->size())); + LLDB_LOGF(log, + " CAS::FEVD[%u] Registering namespace map %p (%d entries)", + current_id, static_cast<void *>(context.m_namespace_map.get()), + static_cast<int>(context.m_namespace_map->size())); NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map); @@ -807,21 +824,17 @@ void ClangASTSource::FindExternalVisibleDecls( if (module_sp && namespace_decl) { CompilerDeclContext found_namespace_decl; - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - - if (symbol_vendor) { - found_namespace_decl = - symbol_vendor->FindNamespace(name, &namespace_decl); + if (SymbolFile *symbol_file = module_sp->GetSymbolFile()) { + found_namespace_decl = symbol_file->FindNamespace(name, &namespace_decl); if (found_namespace_decl) { context.m_namespace_map->push_back( std::pair<lldb::ModuleSP, CompilerDeclContext>( module_sp, found_namespace_decl)); - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CAS::FEVD[%u] Found namespace %s in module %s", + current_id, name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); } } } else if (!HasMerger()) { @@ -836,23 +849,21 @@ void ClangASTSource::FindExternalVisibleDecls( CompilerDeclContext found_namespace_decl; - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + SymbolFile *symbol_file = image->GetSymbolFile(); - if (!symbol_vendor) + if (!symbol_file) continue; - found_namespace_decl = - symbol_vendor->FindNamespace(name, &namespace_decl); + found_namespace_decl = symbol_file->FindNamespace(name, &namespace_decl); if (found_namespace_decl) { context.m_namespace_map->push_back( std::pair<lldb::ModuleSP, CompilerDeclContext>( image, found_namespace_decl)); - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CAS::FEVD[%u] Found namespace %s in module %s", + current_id, name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); } } } @@ -878,9 +889,9 @@ void ClangASTSource::FindExternalVisibleDecls( if (log) { const char *name_string = type_sp->GetName().GetCString(); - log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s", - current_id, name.GetCString(), - (name_string ? name_string : "<anonymous>")); + LLDB_LOGF(log, " CAS::FEVD[%u] Matching type found for \"%s\": %s", + current_id, name.GetCString(), + (name_string ? name_string : "<anonymous>")); } CompilerType full_type = type_sp->GetFullCompilerType(); @@ -888,8 +899,8 @@ void ClangASTSource::FindExternalVisibleDecls( CompilerType copied_clang_type(GuardedCopyType(full_type)); if (!copied_clang_type) { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type", current_id); + LLDB_LOGF(log, " CAS::FEVD[%u] - Couldn't export a type", + current_id); continue; } @@ -915,9 +926,10 @@ void ClangASTSource::FindExternalVisibleDecls( break; if (log) { - log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in " - "the modules", - current_id, name.GetCString()); + LLDB_LOGF(log, + " CAS::FEVD[%u] Matching entity found for \"%s\" in " + "the modules", + current_id, name.GetCString()); } clang::NamedDecl *const decl_from_modules = decls[0]; @@ -930,10 +942,10 @@ void ClangASTSource::FindExternalVisibleDecls( copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; if (!copied_named_decl) { - if (log) - log->Printf( - " CAS::FEVD[%u] - Couldn't export a type from the modules", - current_id); + LLDB_LOGF( + log, + " CAS::FEVD[%u] - Couldn't export a type from the modules", + current_id); break; } @@ -971,11 +983,13 @@ void ClangASTSource::FindExternalVisibleDecls( uint32_t max_matches = 1; std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(name, append, max_matches, decls)) + auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + if (!clang_decl_vendor->FindDecls(name, append, max_matches, decls)) break; if (log) { - log->Printf( + LLDB_LOGF( + log, " CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", current_id, name.GetCString()); } @@ -985,10 +999,9 @@ void ClangASTSource::FindExternalVisibleDecls( copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; if (!copied_named_decl) { - if (log) - log->Printf( - " CAS::FEVD[%u] - Couldn't export a type from the runtime", - current_id); + LLDB_LOGF(log, + " CAS::FEVD[%u] - Couldn't export a type from the runtime", + current_id); break; } @@ -1126,8 +1139,8 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin( if (log) { ASTDumper dumper((Decl *)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOMD[%d] found (%s) %s", current_id, log_info, + dumper.GetCString()); } context.AddNamedDecl(copied_method_decl); @@ -1205,17 +1218,16 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ConstString selector_name(ss.GetString()); - if (log) - log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p " - "for selector [%s %s]", - current_id, static_cast<void *>(m_ast_context), - interface_decl->getNameAsString().c_str(), - selector_name.AsCString()); + LLDB_LOGF(log, + "ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p " + "for selector [%s %s]", + current_id, static_cast<void *>(m_ast_context), + interface_decl->getNameAsString().c_str(), + selector_name.AsCString()); SymbolContextList sc_list; const bool include_symbols = false; const bool include_inlines = false; - const bool append = false; std::string interface_name = interface_decl->getNameAsString(); @@ -1225,9 +1237,10 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ms.Flush(); ConstString instance_method_name(ms.GetString()); + sc_list.Clear(); m_target->GetImages().FindFunctions( instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); if (sc_list.GetSize()) break; @@ -1237,9 +1250,10 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { ms.Flush(); ConstString class_method_name(ms.GetString()); + sc_list.Clear(); m_target->GetImages().FindFunctions( class_method_name, lldb::eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); if (sc_list.GetSize()) break; @@ -1252,7 +1266,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { m_target->GetImages().FindFunctions( selector_name, lldb::eFunctionNameTypeSelector, include_symbols, - include_inlines, append, candidate_sc_list); + include_inlines, candidate_sc_list); for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); ci != ce; ++ci) { SymbolContext candidate_sc; @@ -1331,8 +1345,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { if (log) { ASTDumper dumper((Decl *)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOMD[%d] found (in symbols) %s", current_id, + dumper.GetCString()); } context.AddNamedDecl(copied_method_decl); @@ -1360,11 +1374,11 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { if (complete_interface_decl == interface_decl) break; // already checked this one - if (log) - log->Printf("CAS::FOPD[%d] trying origin " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, static_cast<void *>(complete_interface_decl), - static_cast<void *>(&complete_iface_decl->getASTContext())); + LLDB_LOGF(log, + "CAS::FOPD[%d] trying origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<void *>(complete_interface_decl), + static_cast<void *>(&complete_iface_decl->getASTContext())); FindObjCMethodDeclsWithOrigin(current_id, context, complete_interface_decl, "in debug info"); @@ -1423,7 +1437,9 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { uint32_t max_matches = 1; std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(interface_name, append, max_matches, decls)) + auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + if (!clang_decl_vendor->FindDecls(interface_name, append, max_matches, + decls)) break; ObjCInterfaceDecl *runtime_interface_decl = @@ -1462,8 +1478,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (parser_property_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_property_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id, + dumper.GetCString()); } context.AddNamedDecl(parser_property_decl.decl); @@ -1480,8 +1496,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (parser_ivar_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_ivar_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, - dumper.GetCString()); + LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id, + dumper.GetCString()); } context.AddNamedDecl(parser_ivar_decl.decl); @@ -1505,23 +1521,23 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { ConstString class_name(parser_iface_decl->getNameAsString().c_str()); - if (log) - log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on " - "(ASTContext*)%p for '%s.%s'", - current_id, static_cast<void *>(m_ast_context), - parser_iface_decl->getNameAsString().c_str(), - context.m_decl_name.getAsString().c_str()); + LLDB_LOGF(log, + "ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on " + "(ASTContext*)%p for '%s.%s'", + current_id, static_cast<void *>(m_ast_context), + parser_iface_decl->getNameAsString().c_str(), + context.m_decl_name.getAsString().c_str()); if (FindObjCPropertyAndIvarDeclsWithOrigin( current_id, context, *this, origin_iface_decl)) return; - if (log) - log->Printf("CAS::FOPD[%d] couldn't find the property on origin " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching " - "elsewhere...", - current_id, static_cast<const void *>(origin_iface_decl.decl), - static_cast<void *>(&origin_iface_decl->getASTContext())); + LLDB_LOGF(log, + "CAS::FOPD[%d] couldn't find the property on origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching " + "elsewhere...", + current_id, static_cast<const void *>(origin_iface_decl.decl), + static_cast<void *>(&origin_iface_decl->getASTContext())); SymbolContext null_sc; TypeList type_list; @@ -1542,12 +1558,11 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (complete_iface_decl.decl == origin_iface_decl.decl) break; // already checked this one - if (log) - log->Printf("CAS::FOPD[%d] trying origin " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void *>(complete_iface_decl.decl), - static_cast<void *>(&complete_iface_decl->getASTContext())); + LLDB_LOGF(log, + "CAS::FOPD[%d] trying origin " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<const void *>(complete_iface_decl.decl), + static_cast<void *>(&complete_iface_decl->getASTContext())); FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, complete_iface_decl); @@ -1578,13 +1593,12 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (!interface_decl_from_modules.IsValid()) break; - if (log) - log->Printf( - "CAS::FOPD[%d] trying module " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void *>(interface_decl_from_modules.decl), - static_cast<void *>(&interface_decl_from_modules->getASTContext())); + LLDB_LOGF( + log, + "CAS::FOPD[%d] trying module " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<const void *>(interface_decl_from_modules.decl), + static_cast<void *>(&interface_decl_from_modules->getASTContext())); if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, interface_decl_from_modules)) @@ -1614,7 +1628,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { uint32_t max_matches = 1; std::vector<clang::NamedDecl *> decls; - if (!decl_vendor->FindDecls(class_name, append, max_matches, decls)) + auto *clang_decl_vendor = llvm::cast<ClangDeclVendor>(decl_vendor); + if (!clang_decl_vendor->FindDecls(class_name, append, max_matches, decls)) break; DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime( @@ -1623,13 +1638,12 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (!interface_decl_from_runtime.IsValid()) break; - if (log) - log->Printf( - "CAS::FOPD[%d] trying runtime " - "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast<const void *>(interface_decl_from_runtime.decl), - static_cast<void *>(&interface_decl_from_runtime->getASTContext())); + LLDB_LOGF( + log, + "CAS::FOPD[%d] trying runtime " + "(ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast<const void *>(interface_decl_from_runtime.decl), + static_cast<void *>(&interface_decl_from_runtime->getASTContext())); if (FindObjCPropertyAndIvarDeclsWithOrigin( current_id, context, *this, interface_decl_from_runtime)) @@ -1729,12 +1743,12 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p " - "[name = '%s']", - current_id, static_cast<void *>(m_ast_context), - static_cast<const void *>(record), - record->getNameAsString().c_str()); + LLDB_LOGF(log, + "LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p " + "[name = '%s']", + current_id, static_cast<void *>(m_ast_context), + static_cast<const void *>(record), + record->getNameAsString().c_str()); DeclFromParser<const RecordDecl> parser_record(record); DeclFromUser<const RecordDecl> origin_record( @@ -1798,24 +1812,25 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, m_ast_context->getCharWidth(); if (log) { - log->Printf("LRT[%u] returned:", current_id); - log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, - static_cast<const void *>(origin_record.decl)); - log->Printf("LRT[%u] Size = %" PRId64, current_id, size); - log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment); - log->Printf("LRT[%u] Fields:", current_id); + LLDB_LOGF(log, "LRT[%u] returned:", current_id); + LLDB_LOGF(log, "LRT[%u] Original = (RecordDecl*)%p", current_id, + static_cast<const void *>(origin_record.decl)); + LLDB_LOGF(log, "LRT[%u] Size = %" PRId64, current_id, size); + LLDB_LOGF(log, "LRT[%u] Alignment = %" PRId64, current_id, alignment); + LLDB_LOGF(log, "LRT[%u] Fields:", current_id); for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); fi != fe; ++fi) { - log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 - " bits", - current_id, static_cast<void *>(*fi), - fi->getNameAsString().c_str(), field_offsets[*fi]); + LLDB_LOGF(log, + "LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 + " bits", + current_id, static_cast<void *>(*fi), + fi->getNameAsString().c_str(), field_offsets[*fi]); } DeclFromParser<const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record); if (parser_cxx_record.IsValid()) { - log->Printf("LRT[%u] Bases:", current_id); + LLDB_LOGF(log, "LRT[%u] Bases:", current_id); for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); @@ -1828,7 +1843,8 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, DeclFromParser<CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record); - log->Printf( + LLDB_LOGF( + log, "LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, (is_virtual ? "Virtual " : ""), @@ -1839,7 +1855,7 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, : base_offsets[base_cxx_record.decl].getQuantity())); } } else { - log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); + LLDB_LOGF(log, "LRD[%u] Not a CXXRecord, so no bases", current_id); } } @@ -1856,16 +1872,18 @@ void ClangASTSource::CompleteNamespaceMap( if (log) { if (parent_map && parent_map->size()) - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " - "namespace %s in namespace %s", - current_id, static_cast<void *>(m_ast_context), - name.GetCString(), - parent_map->begin()->second.GetName().AsCString()); + LLDB_LOGF(log, + "CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " + "namespace %s in namespace %s", + current_id, static_cast<void *>(m_ast_context), + name.GetCString(), + parent_map->begin()->second.GetName().AsCString()); else - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " - "namespace %s", - current_id, static_cast<void *>(m_ast_context), - name.GetCString()); + LLDB_LOGF(log, + "CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for " + "namespace %s", + current_id, static_cast<void *>(m_ast_context), + name.GetCString()); } if (parent_map) { @@ -1877,13 +1895,13 @@ void ClangASTSource::CompleteNamespaceMap( lldb::ModuleSP module_sp = i->first; CompilerDeclContext module_parent_namespace_decl = i->second; - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + SymbolFile *symbol_file = module_sp->GetSymbolFile(); - if (!symbol_vendor) + if (!symbol_file) continue; found_namespace_decl = - symbol_vendor->FindNamespace(name, &module_parent_namespace_decl); + symbol_file->FindNamespace(name, &module_parent_namespace_decl); if (!found_namespace_decl) continue; @@ -1891,10 +1909,9 @@ void ClangASTSource::CompleteNamespaceMap( namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>( module_sp, found_namespace_decl)); - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", current_id, - name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CMN[%u] Found namespace %s in module %s", current_id, + name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); } } else { const ModuleList &target_images = m_target->GetImages(); @@ -1910,13 +1927,13 @@ void ClangASTSource::CompleteNamespaceMap( CompilerDeclContext found_namespace_decl; - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + SymbolFile *symbol_file = image->GetSymbolFile(); - if (!symbol_vendor) + if (!symbol_file) continue; found_namespace_decl = - symbol_vendor->FindNamespace(name, &null_namespace_decl); + symbol_file->FindNamespace(name, &null_namespace_decl); if (!found_namespace_decl) continue; @@ -1924,10 +1941,9 @@ void ClangASTSource::CompleteNamespaceMap( namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>( image, found_namespace_decl)); - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", current_id, - name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); + LLDB_LOGF(log, " CMN[%u] Found namespace %s in module %s", current_id, + name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); } } } @@ -2065,7 +2081,8 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { // seems to be generating bad types on occasion. return CompilerType(); - return CompilerType(m_ast_context, copied_qual_type); + return CompilerType(ClangASTContext::GetASTContext(m_ast_context), + copied_qual_type.getAsOpaquePtr()); } clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { @@ -2162,8 +2179,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, } else { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("Function type wasn't a FunctionProtoType"); + LLDB_LOGF(log, "Function type wasn't a FunctionProtoType"); } // If this is an operator (e.g. operator new or operator==), only insert the @@ -2194,7 +2210,9 @@ clang::NamedDecl *NameSearchContext::AddGenericFunDecl() { proto_info)); return AddFunDecl( - CompilerType(m_ast_source.m_ast_context, generic_function_type), true); + CompilerType(ClangASTContext::GetASTContext(m_ast_source.m_ast_context), + generic_function_type.getAsOpaquePtr()), + true); } clang::NamedDecl * diff --git a/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp new file mode 100644 index 000000000000..c59722b7b4f8 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp @@ -0,0 +1,30 @@ +//===-- ClangDeclVendor.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 "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" + +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Utility/ConstString.h" + +using namespace lldb_private; + +uint32_t ClangDeclVendor::FindDecls(ConstString name, bool append, + uint32_t max_matches, + std::vector<CompilerDecl> &decls) { + if (!append) + decls.clear(); + + std::vector<clang::NamedDecl *> named_decls; + uint32_t ret = FindDecls(name, /*append*/ false, max_matches, named_decls); + for (auto *named_decl : named_decls) { + decls.push_back(CompilerDecl( + ClangASTContext::GetASTContext(&named_decl->getASTContext()), + named_decl)); + } + return ret; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h new file mode 100644 index 000000000000..90b715f37cba --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h @@ -0,0 +1,50 @@ +//===-- ClangDeclVendor.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 liblldb_ClangDeclVendor_h_ +#define liblldb_ClangDeclVendor_h_ + +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/DeclVendor.h" + +#include "clang/AST/ExternalASTMerger.h" + +namespace lldb_private { + +// A clang specialized extension to DeclVendor. +class ClangDeclVendor : public DeclVendor { +public: + ClangDeclVendor(DeclVendorKind kind) : DeclVendor(kind) {} + + virtual ~ClangDeclVendor() {} + + /// Interface for ExternalASTMerger. Returns an ImporterSource allowing type + /// completion. + /// + /// \return + /// An ImporterSource for this ClangDeclVendor. + virtual clang::ExternalASTMerger::ImporterSource GetImporterSource() = 0; + + uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, + std::vector<CompilerDecl> &decls) override; + + virtual uint32_t FindDecls(ConstString name, bool append, + uint32_t max_matches, + std::vector<clang::NamedDecl *> &decls) = 0; + + static bool classof(const DeclVendor *vendor) { + return vendor->GetKind() >= eClangDeclVendor && + vendor->GetKind() < eLastClangDeclVendor; + } + +private: + DISALLOW_COPY_AND_ASSIGN(ClangDeclVendor); +}; +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h b/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h index db50c2aa3e90..48cd1c4b99fa 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h +++ b/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h @@ -29,7 +29,7 @@ public: return diag->getKind() == eDiagnosticOriginClang; } - ClangDiagnostic(const char *message, DiagnosticSeverity severity, + ClangDiagnostic(llvm::StringRef message, DiagnosticSeverity severity, uint32_t compiler_id) : Diagnostic(message, severity, eDiagnosticOriginClang, compiler_id) {} @@ -42,6 +42,7 @@ public: } const FixItList &FixIts() const { return m_fixit_vec; } +private: FixItList m_fixit_vec; }; diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index a49a7029e0d2..f4457fc1b740 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -180,98 +180,20 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { return ret; } -namespace { -/// This class walks an AST and ensures that all DeclContexts defined inside the -/// current source file are properly complete. -/// -/// This is used to ensure that persistent types defined in the current source -/// file migrate completely to the persistent AST context before they are -/// reused. If that didn't happen, it would be impoossible to complete them -/// because their origin would be gone. -/// -/// The stragtegy used by this class is to check the SourceLocation (to be -/// specific, the FileID) and see if it's the FileID for the current expression. -/// Alternate strategies could include checking whether an ExternalASTMerger, -/// set up to not have the current context as a source, can find an original for -/// the type. -class Completer : public clang::RecursiveASTVisitor<Completer> { -private: - clang::ASTImporter &m_exporter; /// Used to import Decl contents - clang::FileID m_file; /// The file that's going away - llvm::DenseSet<clang::Decl *> m_completed; /// Visited Decls, to avoid cycles - - bool ImportAndCheckCompletable(clang::Decl *decl) { - (void)m_exporter.Import(decl); - if (m_completed.count(decl)) - return false; - if (!llvm::isa<DeclContext>(decl)) - return false; - const clang::SourceLocation loc = decl->getLocation(); - if (!loc.isValid()) - return false; - const clang::FileID file = - m_exporter.getFromContext().getSourceManager().getFileID(loc); - if (file != m_file) - return false; - // We are assuming the Decl was parsed in this very expression, so it - // should not have external storage. - lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage()); - return true; - } - - void Complete(clang::Decl *decl) { - m_completed.insert(decl); - auto *decl_context = llvm::cast<DeclContext>(decl); - (void)m_exporter.Import(decl); - m_exporter.CompleteDecl(decl); - for (Decl *child : decl_context->decls()) - if (ImportAndCheckCompletable(child)) - Complete(child); - } - - void MaybeComplete(clang::Decl *decl) { - if (ImportAndCheckCompletable(decl)) - Complete(decl); - } - -public: - Completer(clang::ASTImporter &exporter, clang::FileID file) - : m_exporter(exporter), m_file(file) {} - - // Implements the RecursiveASTVisitor's core API. It is called on each Decl - // that the RecursiveASTVisitor encounters, and returns true if the traversal - // should continue. - bool VisitDecl(clang::Decl *decl) { - MaybeComplete(decl); - return true; - } -}; -} - -static void CompleteAllDeclContexts(clang::ASTImporter &exporter, - clang::FileID file, - clang::QualType root) { - clang::QualType canonical_type = root.getCanonicalType(); - if (clang::TagDecl *tag_decl = canonical_type->getAsTagDecl()) { - Completer(exporter, file).TraverseDecl(tag_decl); - } else if (auto interface_type = llvm::dyn_cast<ObjCInterfaceType>( - canonical_type.getTypePtr())) { - Completer(exporter, file).TraverseDecl(interface_type->getDecl()); - } else { - Completer(exporter, file).TraverseType(canonical_type); - } -} - static clang::QualType ExportAllDeclaredTypes( - clang::ExternalASTMerger &merger, + clang::ExternalASTMerger &parent_merger, clang::ExternalASTMerger &merger, clang::ASTContext &source, clang::FileManager &source_file_manager, const clang::ExternalASTMerger::OriginMap &source_origin_map, clang::FileID file, clang::QualType root) { - clang::ExternalASTMerger::ImporterSource importer_source = - { source, source_file_manager, source_origin_map }; + // Mark the source as temporary to make sure all declarations from the + // AST are exported. Also add the parent_merger as the merger into the + // source AST so that the merger can track back any declarations from + // the persistent ASTs we used as sources. + clang::ExternalASTMerger::ImporterSource importer_source( + source, source_file_manager, source_origin_map, /*Temporary*/ true, + &parent_merger); merger.AddSources(importer_source); clang::ASTImporter &exporter = merger.ImporterForOrigin(source); - CompleteAllDeclContexts(exporter, file, root); llvm::Expected<clang::QualType> ret_or_error = exporter.Import(root); merger.RemoveSources(importer_source); if (ret_or_error) { @@ -286,10 +208,10 @@ static clang::QualType ExportAllDeclaredTypes( TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target, ClangASTContext &source, TypeFromParser parser_type) { - assert (&target == m_target->GetScratchClangASTContext()); - assert ((TypeSystem*)&source == parser_type.GetTypeSystem()); - assert (source.getASTContext() == m_ast_context); - + assert(&target == m_target->GetScratchClangASTContext()); + assert((TypeSystem *)&source == parser_type.GetTypeSystem()); + assert(source.getASTContext() == m_ast_context); + if (m_ast_importer_sp) { return TypeFromUser(m_ast_importer_sp->DeportType( target.getASTContext(), source.getASTContext(), @@ -299,13 +221,12 @@ TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target, clang::FileID source_file = source.getASTContext()->getSourceManager().getFileID( source.getASTContext()->getTranslationUnitDecl()->getLocation()); - auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>( + auto scratch_ast_context = static_cast<ClangASTContextForExpressions *>( m_target->GetScratchClangASTContext()); clang::QualType exported_type = ExportAllDeclaredTypes( - scratch_ast_context->GetMergerUnchecked(), + *m_merger_up.get(), scratch_ast_context->GetMergerUnchecked(), *source.getASTContext(), *source.getFileManager(), - m_merger_up->GetOrigins(), - source_file, + m_merger_up->GetOrigins(), source_file, clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType())); return TypeFromUser(exported_type.getAsOpaquePtr(), &target); } else { @@ -375,8 +296,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, TypeFromUser user_type = DeportType(*context, *ast, parser_type); if (!user_type.GetOpaqueQualType()) { - if (log) - log->Printf("Persistent variable's type wasn't copied successfully"); + LLDB_LOGF(log, "Persistent variable's type wasn't copied successfully"); return false; } @@ -415,8 +335,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, var->m_flags |= ClangExpressionVariable::EVKeepInTarget; } - if (log) - log->Printf("Created persistent variable with flags 0x%hx", var->m_flags); + LLDB_LOGF(log, "Created persistent variable with flags 0x%hx", var->m_flags); var->EnableParserVars(GetParserID()); @@ -458,10 +377,9 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, if (!var) return false; - if (log) - log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", - static_cast<const void *>(decl), name.GetCString(), - var->GetName().GetCString()); + LLDB_LOGF(log, "Adding value for (NamedDecl*)%p [%s - %s] to the structure", + static_cast<const void *>(decl), name.GetCString(), + var->GetName().GetCString()); // We know entity->m_parser_vars is valid because we used a parser variable // to find it @@ -475,9 +393,8 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID())) { // We already laid this out; do not touch - if (log) - log->Printf("Already placed at 0x%llx", - (unsigned long long)jit_vars->m_offset); + LLDB_LOGF(log, "Already placed at 0x%llx", + (unsigned long long)jit_vars->m_offset); } llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID()); @@ -512,8 +429,7 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, if (!err.Success()) return false; - if (log) - log->Printf("Placed at 0x%llx", (unsigned long long)offset); + LLDB_LOGF(log, "Placed at 0x%llx", (unsigned long long)offset); jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this. @@ -779,7 +695,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (GetImportInProgress()) { if (log && log->GetVerbose()) - log->Printf("Ignoring a query during an import"); + LLDB_LOGF(log, "Ignoring a query during an import"); return; } @@ -788,20 +704,23 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { if (!context.m_decl_context) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " - "'%s' in a NULL DeclContext", - current_id, name.GetCString()); + LLDB_LOGF(log, + "ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in a NULL DeclContext", + current_id, name.GetCString()); else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " - "'%s' in '%s'", - current_id, name.GetCString(), - context_named_decl->getNameAsString().c_str()); + LLDB_LOGF(log, + "ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in '%s'", + current_id, name.GetCString(), + context_named_decl->getNameAsString().c_str()); else - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " - "'%s' in a '%s'", - current_id, name.GetCString(), - context.m_decl_context->getDeclKindName()); + LLDB_LOGF(log, + "ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for " + "'%s' in a '%s'", + current_id, name.GetCString(), + context.m_decl_context->getDeclKindName()); } if (const NamespaceDecl *namespace_context = @@ -828,7 +747,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", current_id, static_cast<void *>(namespace_map.get()), (int)namespace_map->size()); - + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e; ++i) { @@ -848,7 +767,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl, current_id); } - + ClangASTSource::FindExternalVisibleDecls(context); } @@ -922,9 +841,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( MaybeRegisterFunctionBody(parser_function_decl); } - if (log) - log->Printf(" CEDM::FEVD[%u] Found persistent decl %s", current_id, - name.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id, + name.GetCString()); context.AddNamedDecl(parser_named_decl); } while (false); @@ -979,8 +897,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { ASTDumper ast_dumper(class_qual_type); - log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Adding type for $__lldb_class: %s", + current_id, ast_dumper.GetCString()); } AddThisType(context, class_user_type, current_id); @@ -1024,8 +942,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (pointee_type.IsValid()) { if (log) { ASTDumper ast_dumper(pointee_type); - log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_class: %s", + current_id, ast_dumper.GetCString()); } AddThisType(context, pointee_type, current_id); @@ -1048,7 +966,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( return; AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), - current_id); + current_id); m_struct_vars->m_object_pointer_type = TypeFromUser(ctx_obj_ptr->GetCompilerType()); @@ -1096,8 +1014,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { ASTDumper ast_dumper(interface_type); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); } AddOneType(context, class_user_type, current_id); @@ -1157,8 +1075,9 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (log) { ASTDumper ast_dumper(self_type->GetFullCompilerType()); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); + LLDB_LOGF(log, + " FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); } TypeFromUser class_user_type(self_clang_type); @@ -1222,9 +1141,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( reg_name)); if (reg_info) { - if (log) - log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, - reg_info->name); + LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id, + reg_info->name); AddOneRegister(context, reg_info, current_id); } @@ -1298,14 +1216,12 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } const bool include_inlines = false; - const bool append = false; - + sc_list.Clear(); if (namespace_decl && module_sp) { const bool include_symbols = false; module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase, - include_symbols, include_inlines, append, - sc_list); + include_symbols, include_inlines, sc_list); } else if (target && !namespace_decl) { const bool include_symbols = true; @@ -1314,7 +1230,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( target->GetImages().FindFunctions(name, eFunctionNameTypeFull, include_symbols, include_inlines, - append, sc_list); + sc_list); } // If we found more than one function, see if we can use the frame's decl @@ -1511,9 +1427,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) { if (log) { - log->Printf(" CAS::FEVD[%u] Matching function found for " - "\"%s\" in the modules", - current_id, name.GetCString()); + LLDB_LOGF(log, + " CAS::FEVD[%u] Matching function found for " + "\"%s\" in the modules", + current_id, name.GetCString()); } clang::Decl *copied_decl = CopyDecl(decl_from_modules); @@ -1522,10 +1439,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( : nullptr; if (!copied_function_decl) { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a function " - "declaration from the modules", - current_id); + LLDB_LOGF(log, + " CAS::FEVD[%u] - Couldn't export a function " + "declaration from the modules", + current_id); break; } @@ -1538,9 +1455,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( context.m_found.function = true; } else if (llvm::isa<clang::VarDecl>(decl_from_modules)) { if (log) { - log->Printf(" CAS::FEVD[%u] Matching variable found for " - "\"%s\" in the modules", - current_id, name.GetCString()); + LLDB_LOGF(log, + " CAS::FEVD[%u] Matching variable found for " + "\"%s\" in the modules", + current_id, name.GetCString()); } clang::Decl *copied_decl = CopyDecl(decl_from_modules); @@ -1549,10 +1467,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( : nullptr; if (!copied_var_decl) { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a variable " - "declaration from the modules", - current_id); + LLDB_LOGF(log, + " CAS::FEVD[%u] - Couldn't export a variable " + "declaration from the modules", + current_id); break; } @@ -1647,8 +1565,7 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, const_value_extractor.GetByteSize()); var_location.SetValueType(Value::eValueTypeHostAddress); } else { - if (log) - log->Printf("Error evaluating constant variable: %s", err.AsCString()); + LLDB_LOGF(log, "Error evaluating constant variable: %s", err.AsCString()); return false; } } @@ -1656,9 +1573,8 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, CompilerType type_to_use = GuardedCopyType(var_clang_type); if (!type_to_use) { - if (log) - log->Printf( - "Couldn't copy a variable's type into the parser's AST context"); + LLDB_LOGF(log, + "Couldn't copy a variable's type into the parser's AST context"); return false; } @@ -1751,9 +1667,10 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (log) { ASTDumper orig_dumper(ut.GetOpaqueQualType()); ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", - current_id, decl_name.c_str(), ast_dumper.GetCString(), - orig_dumper.GetCString()); + LLDB_LOGF(log, + " CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", + current_id, decl_name.c_str(), ast_dumper.GetCString(), + orig_dumper.GetCString()); } } @@ -1768,9 +1685,8 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, TypeFromParser parser_type(GuardedCopyType(user_type)); if (!parser_type.GetOpaqueQualType()) { - if (log) - log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", - current_id, pvar_sp->GetName().GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Couldn't import type for pvar %s", + current_id, pvar_sp->GetName().GetCString()); return; } @@ -1789,8 +1705,8 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, if (log) { ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, - pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, + pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); } } @@ -1848,8 +1764,8 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, if (log) { ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, - decl_name.c_str(), ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%u] Found variable %s, returned %s", + current_id, decl_name.c_str(), ast_dumper.GetCString()); } } @@ -1858,7 +1774,7 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); ClangASTContextForExpressions *scratch_ast_context = - static_cast<ClangASTContextForExpressions*>( + static_cast<ClangASTContextForExpressions *>( target->GetScratchClangASTContext()); for (size_t index = 0, num_entities = m_found_entities.GetSize(); @@ -1874,15 +1790,14 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl); if (!var_decl) { - if (log) - log->Printf("Entity of unknown type does not have a VarDecl"); + LLDB_LOGF(log, "Entity of unknown type does not have a VarDecl"); return false; } if (log) { ASTDumper ast_dumper(const_cast<VarDecl *>(var_decl)); - log->Printf("Variable of unknown type now has Decl %s", - ast_dumper.GetCString()); + LLDB_LOGF(log, "Variable of unknown type now has Decl %s", + ast_dumper.GetCString()); } QualType var_type = var_decl->getType(); @@ -1897,18 +1812,17 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { var_type.getAsOpaquePtr()); } else if (HasMerger()) { copied_type = CopyTypeWithMerger( - var_decl->getASTContext(), - scratch_ast_context->GetMergerUnchecked(), - var_type).getAsOpaquePtr(); + var_decl->getASTContext(), + scratch_ast_context->GetMergerUnchecked(), var_type) + .getAsOpaquePtr(); } else { lldbassert(0 && "No mechanism to copy a resolved unknown type!"); return false; } if (!copied_type) { - if (log) - log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't " - "import the type for a variable"); + LLDB_LOGF(log, "ClangExpressionDeclMap::ResolveUnknownType - Couldn't " + "import the type for a variable"); return (bool)lldb::ExpressionVariableSP(); } @@ -1939,9 +1853,8 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, m_ast_context, reg_info->encoding, reg_info->byte_size * 8); if (!clang_type) { - if (log) - log->Printf(" Tried to add a type for %s, but couldn't get one", - context.m_decl_name.getAsString().c_str()); + LLDB_LOGF(log, " Tried to add a type for %s, but couldn't get one", + context.m_decl_name.getAsString().c_str()); return; } @@ -1969,9 +1882,9 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, if (log) { ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, - context.m_decl_name.getAsString().c_str(), - ast_dumper.GetCString()); + LLDB_LOGF(log, " CEDM::FEVD[%d] Added register %s, returned %s", + current_id, context.m_decl_name.getAsString().c_str(), + ast_dumper.GetCString()); } } @@ -2016,24 +1929,24 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (copied_function_template) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_template); - + StreamString ss; - + function->DumpSymbolContext(&ss); - + log->Printf(" CEDM::FEVD[%u] Imported decl for function template" " %s (description %s), returned %s", current_id, copied_function_template->getNameAsString().c_str(), ss.GetData(), ast_dumper.GetCString()); } - + context.AddNamedDecl(copied_function_template); } } else if (src_function_decl) { if (clang::FunctionDecl *copied_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( - CopyDecl(src_function_decl))) { + CopyDecl(src_function_decl))) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_decl); @@ -2041,19 +1954,20 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, function->DumpSymbolContext(&ss); - log->Printf(" CEDM::FEVD[%u] Imported decl for function %s " - "(description %s), returned %s", - current_id, - copied_function_decl->getNameAsString().c_str(), - ss.GetData(), ast_dumper.GetCString()); + LLDB_LOGF(log, + " CEDM::FEVD[%u] Imported decl for function %s " + "(description %s), returned %s", + current_id, + copied_function_decl->getNameAsString().c_str(), + ss.GetData(), ast_dumper.GetCString()); } context.AddNamedDecl(copied_function_decl); return; } else { if (log) { - log->Printf(" Failed to import the function decl for '%s'", - src_function_decl->getName().str().c_str()); + LLDB_LOGF(log, " Failed to import the function decl for '%s'", + src_function_decl->getName().str().c_str()); } } } @@ -2082,7 +1996,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (!function_decl) { if (log) { - log->Printf( + LLDB_LOGF( + log, " Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", function_type->GetName().GetCString(), function_type->GetID()); } @@ -2092,10 +2007,11 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, } else { // We failed to copy the type we found if (log) { - log->Printf(" Failed to import the function type '%s' {0x%8.8" PRIx64 - "} into the expression parser AST contenxt", - function_type->GetName().GetCString(), - function_type->GetID()); + LLDB_LOGF(log, + " Failed to import the function type '%s' {0x%8.8" PRIx64 + "} into the expression parser AST contenxt", + function_type->GetName().GetCString(), + function_type->GetID()); } return; @@ -2154,7 +2070,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); - log->Printf( + LLDB_LOGF( + log, " CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", current_id, (function ? "specific" : "generic"), decl_name.c_str(), ss.GetData(), function_str.c_str()); @@ -2170,7 +2087,8 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, if (!copied_clang_type) { if (log) - log->Printf( + LLDB_LOGF( + log, "ClangExpressionDeclMap::AddThisType - Couldn't import the type"); return; @@ -2203,9 +2121,10 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, ASTDumper method_ast_dumper((clang::Decl *)method_decl); ASTDumper type_ast_dumper(copied_clang_type); - log->Printf(" CEDM::AddThisType Added function $__lldb_expr " - "(description %s) for this type %s", - method_ast_dumper.GetCString(), type_ast_dumper.GetCString()); + LLDB_LOGF(log, + " CEDM::AddThisType Added function $__lldb_expr " + "(description %s) for this type %s", + method_ast_dumper.GetCString(), type_ast_dumper.GetCString()); } } @@ -2244,8 +2163,8 @@ void ClangExpressionDeclMap::AddOneType(NameSearchContext &context, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (log) - log->Printf( - "ClangExpressionDeclMap::AddOneType - Couldn't import the type"); + LLDB_LOGF( + log, "ClangExpressionDeclMap::AddOneType - Couldn't import the type"); return; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index 03b73e6be391..2711e90726e7 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -356,7 +356,7 @@ private: /// Activate parser-specific variables void EnableParserVars() { if (!m_parser_vars.get()) - m_parser_vars = llvm::make_unique<ParserVars>(); + m_parser_vars = std::make_unique<ParserVars>(); } /// Deallocate parser-specific variables diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 7d13891ded8d..1422911d6546 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -105,16 +105,26 @@ using namespace lldb_private; class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks { ClangModulesDeclVendor &m_decl_vendor; ClangPersistentVariables &m_persistent_vars; + clang::SourceManager &m_source_mgr; StreamString m_error_stream; bool m_has_errors = false; public: LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, - ClangPersistentVariables &persistent_vars) - : m_decl_vendor(decl_vendor), m_persistent_vars(persistent_vars) {} + ClangPersistentVariables &persistent_vars, + clang::SourceManager &source_mgr) + : m_decl_vendor(decl_vendor), m_persistent_vars(persistent_vars), + m_source_mgr(source_mgr) {} void moduleImport(SourceLocation import_location, clang::ModuleIdPath path, const clang::Module * /*null*/) override { + // Ignore modules that are imported in the wrapper code as these are not + // loaded by the user. + llvm::StringRef filename = + m_source_mgr.getPresumedLoc(import_location).getFilename(); + if (filename == ClangExpressionSourceCode::g_prefix_file_name) + return; + SourceModule module; for (const std::pair<IdentifierInfo *, SourceLocation> &component : path) @@ -137,12 +147,14 @@ public: class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer { public: - ClangDiagnosticManagerAdapter() - : m_passthrough(new clang::TextDiagnosticBuffer) {} - - ClangDiagnosticManagerAdapter( - const std::shared_ptr<clang::TextDiagnosticBuffer> &passthrough) - : m_passthrough(passthrough) {} + ClangDiagnosticManagerAdapter(DiagnosticOptions &opts) { + DiagnosticOptions *m_options = new DiagnosticOptions(opts); + m_options->ShowPresumedLoc = true; + m_options->ShowLevel = false; + m_os.reset(new llvm::raw_string_ostream(m_output)); + m_passthrough.reset( + new clang::TextDiagnosticPrinter(*m_os, m_options, false)); + } void ResetManager(DiagnosticManager *manager = nullptr) { m_manager = manager; @@ -150,79 +162,92 @@ public: void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) override { - if (m_manager) { - llvm::SmallVector<char, 32> diag_str; - Info.FormatDiagnostic(diag_str); - diag_str.push_back('\0'); - const char *data = diag_str.data(); - - lldb_private::DiagnosticSeverity severity; - bool make_new_diagnostic = true; - - switch (DiagLevel) { - case DiagnosticsEngine::Level::Fatal: - case DiagnosticsEngine::Level::Error: - severity = eDiagnosticSeverityError; - break; - case DiagnosticsEngine::Level::Warning: - severity = eDiagnosticSeverityWarning; - break; - case DiagnosticsEngine::Level::Remark: - case DiagnosticsEngine::Level::Ignored: - severity = eDiagnosticSeverityRemark; - break; - case DiagnosticsEngine::Level::Note: - m_manager->AppendMessageToDiagnostic(data); - make_new_diagnostic = false; - } - if (make_new_diagnostic) { - ClangDiagnostic *new_diagnostic = - new ClangDiagnostic(data, severity, Info.getID()); - m_manager->AddDiagnostic(new_diagnostic); - - // Don't store away warning fixits, since the compiler doesn't have - // enough context in an expression for the warning to be useful. - // FIXME: Should we try to filter out FixIts that apply to our generated - // code, and not the user's expression? - if (severity == eDiagnosticSeverityError) { - size_t num_fixit_hints = Info.getNumFixItHints(); - for (size_t i = 0; i < num_fixit_hints; i++) { - const clang::FixItHint &fixit = Info.getFixItHint(i); - if (!fixit.isNull()) - new_diagnostic->AddFixitHint(fixit); - } - } + if (!m_manager) { + // We have no DiagnosticManager before/after parsing but we still could + // receive diagnostics (e.g., by the ASTImporter failing to copy decls + // when we move the expression result ot the ScratchASTContext). Let's at + // least log these diagnostics until we find a way to properly render + // them and display them to the user. + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + if (log) { + llvm::SmallVector<char, 32> diag_str; + Info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + const char *plain_diag = diag_str.data(); + LLDB_LOG(log, "Received diagnostic outside parsing: {0}", plain_diag); } + return; } + // Render diagnostic message to m_output. + m_output.clear(); m_passthrough->HandleDiagnostic(DiagLevel, Info); - } + m_os->flush(); - void FlushDiagnostics(DiagnosticsEngine &Diags) { - m_passthrough->FlushDiagnostics(Diags); - } + lldb_private::DiagnosticSeverity severity; + bool make_new_diagnostic = true; + + switch (DiagLevel) { + case DiagnosticsEngine::Level::Fatal: + case DiagnosticsEngine::Level::Error: + severity = eDiagnosticSeverityError; + break; + case DiagnosticsEngine::Level::Warning: + severity = eDiagnosticSeverityWarning; + break; + case DiagnosticsEngine::Level::Remark: + case DiagnosticsEngine::Level::Ignored: + severity = eDiagnosticSeverityRemark; + break; + case DiagnosticsEngine::Level::Note: + m_manager->AppendMessageToDiagnostic(m_output); + make_new_diagnostic = false; + } + if (make_new_diagnostic) { + // ClangDiagnostic messages are expected to have no whitespace/newlines + // around them. + std::string stripped_output = llvm::StringRef(m_output).trim(); + + auto new_diagnostic = std::make_unique<ClangDiagnostic>( + stripped_output, severity, Info.getID()); + + // Don't store away warning fixits, since the compiler doesn't have + // enough context in an expression for the warning to be useful. + // FIXME: Should we try to filter out FixIts that apply to our generated + // code, and not the user's expression? + if (severity == eDiagnosticSeverityError) { + size_t num_fixit_hints = Info.getNumFixItHints(); + for (size_t i = 0; i < num_fixit_hints; i++) { + const clang::FixItHint &fixit = Info.getFixItHint(i); + if (!fixit.isNull()) + new_diagnostic->AddFixitHint(fixit); + } + } - DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { - return new ClangDiagnosticManagerAdapter(m_passthrough); + m_manager->AddDiagnostic(std::move(new_diagnostic)); + } } - clang::TextDiagnosticBuffer *GetPassthrough() { return m_passthrough.get(); } + clang::TextDiagnosticPrinter *GetPassthrough() { return m_passthrough.get(); } private: DiagnosticManager *m_manager = nullptr; - std::shared_ptr<clang::TextDiagnosticBuffer> m_passthrough; + std::shared_ptr<clang::TextDiagnosticPrinter> m_passthrough; + /// Output stream of m_passthrough. + std::shared_ptr<llvm::raw_string_ostream> m_os; + /// Output string filled by m_os. + std::string m_output; }; -static void -SetupModuleHeaderPaths(CompilerInstance *compiler, - std::vector<ConstString> include_directories, - lldb::TargetSP target_sp) { +static void SetupModuleHeaderPaths(CompilerInstance *compiler, + std::vector<std::string> include_directories, + lldb::TargetSP target_sp) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts(); - for (ConstString dir : include_directories) { - search_opts.AddPath(dir.AsCString(), frontend::System, false, true); + for (const std::string &dir : include_directories) { + search_opts.AddPath(dir, frontend::System, false, true); LLDB_LOG(log, "Added user include dir: {0}", dir); } @@ -232,27 +257,9 @@ SetupModuleHeaderPaths(CompilerInstance *compiler, search_opts.ModuleCachePath = module_cache.str(); LLDB_LOG(log, "Using module cache path: {0}", module_cache.c_str()); - FileSpec clang_resource_dir = GetClangResourceDir(); - std::string resource_dir = clang_resource_dir.GetPath(); - if (FileSystem::Instance().IsDirectory(resource_dir)) { - search_opts.ResourceDir = resource_dir; - std::string resource_include = resource_dir + "/include"; - search_opts.AddPath(resource_include, frontend::System, false, true); - - LLDB_LOG(log, "Added resource include dir: {0}", resource_include); - } + search_opts.ResourceDir = GetClangResourceDir().GetPath(); search_opts.ImplicitModuleMaps = true; - - std::vector<std::string> system_include_directories = - target_sp->GetPlatform()->GetSystemIncludeDirectories( - lldb::eLanguageTypeC_plus_plus); - - for (const std::string &include_dir : system_include_directories) { - search_opts.AddPath(include_dir, frontend::System, false, true); - - LLDB_LOG(log, "Added system include dir: {0}", include_dir); - } } //===----------------------------------------------------------------------===// @@ -261,10 +268,12 @@ SetupModuleHeaderPaths(CompilerInstance *compiler, ClangExpressionParser::ClangExpressionParser( ExecutionContextScope *exe_scope, Expression &expr, - bool generate_debug_info, std::vector<ConstString> include_directories) + bool generate_debug_info, std::vector<std::string> include_directories, + std::string filename) : ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(), m_pp_callbacks(nullptr), - m_include_directories(std::move(include_directories)) { + m_include_directories(std::move(include_directories)), + m_filename(std::move(filename)) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // We can't compile expressions without a target. So if the exe_scope is @@ -331,9 +340,8 @@ ClangExpressionParser::ClangExpressionParser( if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) { lang_rt = process_sp->GetLanguageRuntime(frame_lang); - if (log) - log->Printf("Frame has language of type %s", - Language::GetNameForLanguageType(frame_lang)); + LLDB_LOGF(log, "Frame has language of type %s", + Language::GetNameForLanguageType(frame_lang)); } // 2. Configure the compiler with a set of default options that are @@ -341,9 +349,8 @@ ClangExpressionParser::ClangExpressionParser( if (target_arch.IsValid()) { std::string triple = target_arch.GetTriple().str(); m_compiler->getTargetOpts().Triple = triple; - if (log) - log->Printf("Using %s as the target triple", - m_compiler->getTargetOpts().Triple.c_str()); + LLDB_LOGF(log, "Using %s as the target triple", + m_compiler->getTargetOpts().Triple.c_str()); } else { // If we get here we don't have a valid target and just have to guess. // Sometimes this will be ok to just use the host target triple (when we @@ -352,9 +359,8 @@ ClangExpressionParser::ClangExpressionParser( // the host triple. In such a case the language runtime should expose an // overridden options set (3), below. m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); - if (log) - log->Printf("Using default target triple of %s", - m_compiler->getTargetOpts().Triple.c_str()); + LLDB_LOGF(log, "Using default target triple of %s", + m_compiler->getTargetOpts().Triple.c_str()); } // Now add some special fixes for known architectures: Any arm32 iOS // environment, but not on arm64 @@ -408,12 +414,13 @@ ClangExpressionParser::ClangExpressionParser( auto target_info = TargetInfo::CreateTargetInfo( m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts); if (log) { - log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign()); - log->Printf("Target datalayout string: '%s'", - target_info->getDataLayout().getStringRepresentation().c_str()); - log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str()); - log->Printf("Target vector alignment: %d", - target_info->getMaxVectorAlign()); + LLDB_LOGF(log, "Using SIMD alignment: %d", + target_info->getSimdDefaultAlign()); + LLDB_LOGF(log, "Target datalayout string: '%s'", + target_info->getDataLayout().getStringRepresentation().c_str()); + LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str()); + LLDB_LOGF(log, "Target vector alignment: %d", + target_info->getMaxVectorAlign()); } m_compiler->setTarget(target_info); @@ -508,6 +515,9 @@ ClangExpressionParser::ClangExpressionParser( lang_opts.DoubleSquareBracketAttributes = true; lang_opts.CPlusPlus11 = true; + // The Darwin libc expects this macro to be set. + lang_opts.GNUCVersion = 40201; + SetupModuleHeaderPaths(m_compiler.get(), m_include_directories, target_sp); } @@ -537,8 +547,8 @@ ClangExpressionParser::ClangExpressionParser( // Set CodeGen options m_compiler->getCodeGenOpts().EmitDeclMetadata = true; m_compiler->getCodeGenOpts().InstrumentFunctions = false; - m_compiler->getCodeGenOpts().DisableFPElim = true; - m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; + m_compiler->getCodeGenOpts().setFramePointer( + CodeGenOptions::FramePointerKind::All); if (generate_debug_info) m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); else @@ -560,7 +570,9 @@ ClangExpressionParser::ClangExpressionParser( // 6. Set up the diagnostic buffer for reporting errors - m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); + auto diag_mgr = new ClangDiagnosticManagerAdapter( + m_compiler->getDiagnostics().getDiagnosticOptions()); + m_compiler->getDiagnostics().setClient(diag_mgr); // 7. Set up the source management objects inside the compiler m_compiler->createFileManager(); @@ -574,8 +586,8 @@ ClangExpressionParser::ClangExpressionParser( llvm::cast<ClangPersistentVariables>( target_sp->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)); - std::unique_ptr<PPCallbacks> pp_callbacks( - new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); + std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks( + *decl_vendor, *clang_persistent_vars, m_compiler->getSourceManager())); m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get()); m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); @@ -592,9 +604,7 @@ ClangExpressionParser::ClangExpressionParser( m_compiler->createASTContext(); clang::ASTContext &ast_context = m_compiler->getASTContext(); - m_ast_context.reset( - new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); - m_ast_context->setASTContext(&ast_context); + m_ast_context.reset(new ClangASTContext(ast_context)); std::string module_name("$__lldb_module"); @@ -872,8 +882,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, ClangDiagnosticManagerAdapter *adapter = static_cast<ClangDiagnosticManagerAdapter *>( m_compiler->getDiagnostics().getClient()); - clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); - diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); + auto diag_buf = adapter->GetPassthrough(); adapter->ResetManager(&diagnostic_manager); @@ -904,16 +913,19 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, } if (temp_fd != -1) { - lldb_private::File file(temp_fd, true); + lldb_private::NativeFile file(temp_fd, File::eOpenOptionWrite, true); const size_t expr_text_len = strlen(expr_text); size_t bytes_written = expr_text_len; if (file.Write(expr_text, bytes_written).Success()) { if (bytes_written == expr_text_len) { file.Close(); - source_mgr.setMainFileID(source_mgr.createFileID( - m_compiler->getFileManager().getFile(result_path), - SourceLocation(), SrcMgr::C_User)); - created_main_file = true; + if (auto fileEntry = + m_compiler->getFileManager().getFile(result_path)) { + source_mgr.setMainFileID(source_mgr.createFileID( + *fileEntry, + SourceLocation(), SrcMgr::C_User)); + created_main_file = true; + } } } } @@ -921,7 +933,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, if (!created_main_file) { std::unique_ptr<MemoryBuffer> memory_buffer = - MemoryBuffer::getMemBufferCopy(expr_text, "<lldb-expr>"); + MemoryBuffer::getMemBufferCopy(expr_text, m_filename); source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); } @@ -1092,8 +1104,8 @@ bool ClangExpressionParser::RewriteExpression( if (num_diags == 0) return false; - for (const Diagnostic *diag : diagnostic_manager.Diagnostics()) { - const ClangDiagnostic *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag); + for (const auto &diag : diagnostic_manager.Diagnostics()) { + const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get()); if (diagnostic && diagnostic->HasFixIts()) { for (const FixItHint &fixit : diagnostic->FixIts()) { // This is cobbed from clang::Rewrite::FixItRewriter. @@ -1181,9 +1193,8 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( m_expr.FunctionName()); return err; } else { - if (log) - log->Printf("Found function %s for %s", function_name.AsCString(), - m_expr.FunctionName()); + LLDB_LOGF(log, "Found function %s for %s", function_name.AsCString(), + m_expr.FunctionName()); } } @@ -1198,9 +1209,8 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( LLVMUserExpression::IRPasses custom_passes; { auto lang = m_expr.Language(); - if (log) - log->Printf("%s - Current expression language is %s\n", __FUNCTION__, - Language::GetNameForLanguageType(lang)); + LLDB_LOGF(log, "%s - Current expression language is %s\n", __FUNCTION__, + Language::GetNameForLanguageType(lang)); lldb::ProcessSP process_sp = exe_ctx.GetProcessSP(); if (process_sp && lang != lldb::eLanguageTypeUnknown) { auto runtime = process_sp->GetLanguageRuntime(lang); @@ -1210,10 +1220,10 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( } if (custom_passes.EarlyPasses) { - if (log) - log->Printf("%s - Running Early IR Passes from LanguageRuntime on " - "expression module '%s'", - __FUNCTION__, m_expr.FunctionName()); + LLDB_LOGF(log, + "%s - Running Early IR Passes from LanguageRuntime on " + "expression module '%s'", + __FUNCTION__, m_expr.FunctionName()); custom_passes.EarlyPasses->run(*llvm_module_up); } @@ -1230,12 +1240,10 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( type_system_helper->DeclMap(); // result can be NULL if (decl_map) { - Stream *error_stream = nullptr; Target *target = exe_ctx.GetTargetPtr(); - error_stream = target->GetDebugger().GetErrorFile().get(); - + auto &error_stream = target->GetDebugger().GetErrorStream(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), - *execution_unit_sp, *error_stream, + *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = @@ -1298,9 +1306,8 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( process->SetDynamicCheckers(dynamic_checkers); - if (log) - log->Printf("== [ClangExpressionParser::PrepareForExecution] " - "Finished installing dynamic checkers =="); + LLDB_LOGF(log, "== [ClangExpressionParser::PrepareForExecution] " + "Finished installing dynamic checkers =="); } if (auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>( @@ -1316,10 +1323,10 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( } if (custom_passes.LatePasses) { - if (log) - log->Printf("%s - Running Late IR Passes from LanguageRuntime on " - "expression module '%s'", - __FUNCTION__, m_expr.FunctionName()); + LLDB_LOGF(log, + "%s - Running Late IR Passes from LanguageRuntime on " + "expression module '%s'", + __FUNCTION__, m_expr.FunctionName()); custom_passes.LatePasses->run(*module); } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index a42c2190ffb8..79ad5728bf74 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -53,9 +53,14 @@ public: /// @param[in] include_directories /// List of include directories that should be used when parsing the /// expression. + /// + /// @param[in] filename + /// Name of the source file that should be used when rendering + /// diagnostics (i.e. errors, warnings or notes from Clang). ClangExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info, - std::vector<ConstString> include_directories = {}); + std::vector<std::string> include_directories = {}, + std::string filename = "<clang expression>"); /// Destructor ~ClangExpressionParser() override; @@ -177,7 +182,9 @@ private: ///encounters module imports std::unique_ptr<ClangASTContext> m_ast_context; - std::vector<ConstString> m_include_directories; + std::vector<std::string> m_include_directories; + /// File name used for the user expression. + std::string m_filename; }; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index f513b1eea360..21cb33402e7f 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -29,7 +29,15 @@ using namespace lldb_private; -const char *ClangExpressionSourceCode::g_expression_prefix = R"( +#define PREFIX_NAME "<lldb wrapper prefix>" + +const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME; + +const char *ClangExpressionSourceCode::g_expression_prefix = +"#line 1 \"" PREFIX_NAME R"(" +#ifndef offsetof +#define offsetof(t, d) __builtin_offsetof(t, d) +#endif #ifndef NULL #define NULL (__null) #endif @@ -64,9 +72,6 @@ extern "C" } )"; -static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; -static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; - namespace { class AddMacroState { @@ -166,6 +171,17 @@ static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, } } +lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode( + llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, + llvm::StringRef body, Wrapping wrap) + : ExpressionSourceCode(name, prefix, body, wrap) { + // Use #line markers to pretend that we have a single-line source file + // 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"; +} + namespace { /// Allows checking if a token is contained in a given expression. class TokenVerifier { @@ -286,7 +302,8 @@ bool ClangExpressionSourceCode::GetText( Target *target = exe_ctx.GetTargetPtr(); if (target) { - if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) { + if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64 || + target->GetArchitecture().GetMachine() == llvm::Triple::aarch64_32) { target_specific_defines = "typedef bool BOOL;\n"; } if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) { @@ -398,9 +415,9 @@ bool ClangExpressionSourceCode::GetText( case lldb::eLanguageTypeC: case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeObjC: - tagged_body.append(c_start_marker); + tagged_body.append(m_start_marker); tagged_body.append(m_body); - tagged_body.append(c_end_marker); + tagged_body.append(m_end_marker); break; } switch (wrapping_language) { @@ -474,24 +491,19 @@ bool ClangExpressionSourceCode::GetText( bool ClangExpressionSourceCode::GetOriginalBodyBounds( std::string transformed_text, lldb::LanguageType wrapping_language, size_t &start_loc, size_t &end_loc) { - const char *start_marker; - const char *end_marker; - switch (wrapping_language) { default: return false; case lldb::eLanguageTypeC: case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeObjC: - start_marker = c_start_marker; - end_marker = c_end_marker; break; } - start_loc = transformed_text.find(start_marker); + start_loc = transformed_text.find(m_start_marker); if (start_loc == std::string::npos) return false; - start_loc += strlen(start_marker); - end_loc = transformed_text.find(end_marker); + start_loc += m_start_marker.size(); + end_loc = transformed_text.find(m_end_marker); return end_loc != std::string::npos; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h index 894290295837..1d159670b962 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -23,15 +23,18 @@ class ExecutionContext; class ClangExpressionSourceCode : public ExpressionSourceCode { public: + /// The file name we use for the wrapper code that we inject before + /// the user expression. + static const llvm::StringRef g_prefix_file_name; static const char *g_expression_prefix; - static ClangExpressionSourceCode *CreateWrapped(const char *prefix, - const char *body) { - return new ClangExpressionSourceCode("$__lldb_expr", prefix, body, true); + static ClangExpressionSourceCode *CreateWrapped(llvm::StringRef filename, + llvm::StringRef prefix, + llvm::StringRef body) { + return new ClangExpressionSourceCode(filename, "$__lldb_expr", prefix, body, + Wrap); } - uint32_t GetNumBodyLines(); - /// Generates the source code that will evaluate the expression. /// /// \param text output parameter containing the source code string. @@ -56,14 +59,20 @@ public: // Given a string returned by GetText, find the beginning and end of the body // passed to CreateWrapped. Return true if the bounds could be found. This // will also work on text with FixItHints applied. - static bool GetOriginalBodyBounds(std::string transformed_text, - lldb::LanguageType wrapping_language, - size_t &start_loc, size_t &end_loc); + bool GetOriginalBodyBounds(std::string transformed_text, + lldb::LanguageType wrapping_language, + size_t &start_loc, size_t &end_loc); protected: - ClangExpressionSourceCode(const char *name, const char *prefix, const char *body, - bool wrap) : - ExpressionSourceCode(name, prefix, body, wrap) {} + ClangExpressionSourceCode(llvm::StringRef filename, llvm::StringRef name, + llvm::StringRef prefix, llvm::StringRef body, + Wrapping wrap); + +private: + /// String marking the start of the user expression. + std::string m_start_marker; + /// String marking the end of the user expression. + std::string m_end_marker; }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index eabc96aa8e51..8fbfa6e47578 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -179,8 +179,7 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp, m_wrapper_function_text.append(");\n}\n"); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); + LLDB_LOGF(log, "Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); // Okay, now compile this expression diff --git a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp index 65c547391831..42d3f22014dd 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp @@ -30,10 +30,10 @@ static bool VerifyClangPath(const llvm::Twine &clang_path) { if (FileSystem::Instance().IsDirectory(clang_path)) return true; Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("VerifyClangPath(): " - "failed to stat clang resource directory at \"%s\"", - clang_path.str().c_str()); + LLDB_LOGF(log, + "VerifyClangPath(): " + "failed to stat clang resource directory at \"%s\"", + clang_path.str().c_str()); return false; } @@ -67,10 +67,10 @@ static bool DefaultComputeClangResourceDirectory(FileSpec &lldb_shlib_spec, llvm::sys::path::native(relative_path); llvm::sys::path::append(clang_dir, relative_path); if (!verify || VerifyClangPath(clang_dir)) { - if (log) - log->Printf("DefaultComputeClangResourceDir: Setting ClangResourceDir " - "to \"%s\", verify = %s", - clang_dir.str().str().c_str(), verify ? "true" : "false"); + LLDB_LOGF(log, + "DefaultComputeClangResourceDir: Setting ClangResourceDir " + "to \"%s\", verify = %s", + clang_dir.str().str().c_str(), verify ? "true" : "false"); file_spec.GetDirectory().SetString(clang_dir); FileSystem::Instance().Resolve(file_spec); return true; @@ -160,9 +160,8 @@ FileSpec lldb_private::GetClangResourceDir() { ComputeClangResourceDirectory(lldb_file_spec, g_cached_resource_dir, true); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) - log->Printf("GetClangResourceDir() => '%s'", - g_cached_resource_dir.GetPath().c_str()); + LLDB_LOGF(log, "GetClangResourceDir() => '%s'", + g_cached_resource_dir.GetPath().c_str()); }); return g_cached_resource_dir; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 4a220790e50d..f3df589d7311 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -27,6 +27,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SourceModule.h" #include "lldb/Target/Target.h" @@ -110,6 +111,9 @@ private: ImportedModuleMap m_imported_modules; ImportedModuleSet m_user_imported_modules; const clang::ExternalASTMerger::OriginMap m_origin_map; + // We assume that every ASTContext has an ClangASTContext, so we also store + // a custom ClangASTContext for our internal ASTContext. + std::unique_ptr<ClangASTContext> m_ast_context; }; } // anonymous namespace @@ -143,7 +147,8 @@ void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) { } } -ClangModulesDeclVendor::ClangModulesDeclVendor() {} +ClangModulesDeclVendor::ClangModulesDeclVendor() + : ClangDeclVendor(eClangModuleDeclVendor) {} ClangModulesDeclVendor::~ClangModulesDeclVendor() {} @@ -155,7 +160,11 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( : m_diagnostics_engine(std::move(diagnostics_engine)), m_compiler_invocation(std::move(compiler_invocation)), m_compiler_instance(std::move(compiler_instance)), - m_parser(std::move(parser)), m_origin_map() {} + m_parser(std::move(parser)), m_origin_map() { + + // Initialize our ClangASTContext. + m_ast_context.reset(new ClangASTContext(m_compiler_instance->getASTContext())); +} void ClangModulesDeclVendorImpl::ReportModuleExportsHelper( std::set<ClangModulesDeclVendor::ModuleID> &exports, @@ -237,11 +246,11 @@ bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module, bool is_system = true; bool is_framework = false; - auto *dir = + auto dir = HS.getFileMgr().getDirectory(module.search_path.GetStringRef()); if (!dir) return error(); - auto *file = HS.lookupModuleMapFile(dir, is_framework); + auto *file = HS.lookupModuleMapFile(*dir, is_framework); if (!file) return error(); if (!HS.loadModuleMapFile(file, is_system)) @@ -562,8 +571,9 @@ ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, clang::ExternalASTMerger::ImporterSource ClangModulesDeclVendorImpl::GetImporterSource() { - return {m_compiler_instance->getASTContext(), - m_compiler_instance->getFileManager(), m_origin_map}; + return clang::ExternalASTMerger::ImporterSource( + m_compiler_instance->getASTContext(), + m_compiler_instance->getFileManager(), m_origin_map); } static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h index d5c8757bdcd0..e099b59041d8 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -10,22 +10,27 @@ #define liblldb_ClangModulesDeclVendor_h #include "lldb/Core/ClangForward.h" -#include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/SourceModule.h" #include "lldb/Target/Platform.h" +#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" + #include <set> #include <vector> namespace lldb_private { -class ClangModulesDeclVendor : public DeclVendor { +class ClangModulesDeclVendor : public ClangDeclVendor { public: // Constructors and Destructors ClangModulesDeclVendor(); ~ClangModulesDeclVendor() override; + static bool classof(const DeclVendor *vendor) { + return vendor->GetKind() == eClangModuleDeclVendor; + } + static ClangModulesDeclVendor *Create(Target &target); typedef std::vector<ConstString> ModulePath; diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 742a14992dc9..24dd705e37b1 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -23,8 +23,7 @@ using namespace lldb; using namespace lldb_private; ClangPersistentVariables::ClangPersistentVariables() - : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), - m_next_persistent_variable_id(0) {} + : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang) {} ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable( const lldb::ValueObjectSP &valobj_sp) { @@ -43,13 +42,25 @@ void ClangPersistentVariables::RemovePersistentVariable( lldb::ExpressionVariableSP variable) { RemoveVariable(variable); - const char *name = variable->GetName().AsCString(); + // Check if the removed variable was the last one that was created. If yes, + // reuse the variable id for the next variable. - if (*name != '$') + // Nothing to do if we have not assigned a variable id so far. + if (m_next_persistent_variable_id == 0) return; - name++; - if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1) + llvm::StringRef name = variable->GetName().GetStringRef(); + // Remove the prefix from the variable that only the indes is left. + if (!name.consume_front(GetPersistentVariablePrefix(false))) + return; + + // Check if the variable contained a variable id. + uint32_t variable_id; + if (name.getAsInteger(10, variable_id)) + return; + // If it's the most recent variable id that was assigned, make sure that this + // variable id will be used for the next persistent variable. + if (variable_id == m_next_persistent_variable_id - 1) m_next_persistent_variable_id--; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index b39f89ad7eef..95e6c3ac963d 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -45,11 +45,20 @@ public: uint32_t addr_byte_size) override; void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override; - llvm::StringRef - GetPersistentVariablePrefix(bool is_error) const override { + + llvm::StringRef GetPersistentVariablePrefix(bool is_error) const override { return "$"; } + /// Returns the next file name that should be used for user expressions. + std::string GetNextExprFileName() { + std::string name; + name.append("<user expression "); + name.append(std::to_string(m_next_user_file_id++)); + name.append(">"); + return name; + } + llvm::Optional<CompilerType> GetCompilerTypeFromPersistentDecl(ConstString type_name) override; @@ -66,8 +75,10 @@ public: } private: - uint32_t m_next_persistent_variable_id; ///< The counter used by - ///GetNextResultName(). + /// The counter used by GetNextExprFileName. + uint32_t m_next_user_file_id = 0; + // The counter used by GetNextPersistentVariableName + uint32_t m_next_persistent_variable_id = 0; typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap; PersistentDeclMap diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 2dae5b7022f3..da1ca785635c 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Config.h" + #include <stdio.h> #if HAVE_SYS_TYPES_H #include <sys/types.h> @@ -21,9 +23,9 @@ #include "ClangDiagnostic.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" -#include "ClangExpressionSourceCode.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" +#include "CppModuleConfiguration.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" @@ -90,21 +92,18 @@ ClangUserExpression::~ClangUserExpression() {} void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("ClangUserExpression::ScanContext()"); + LLDB_LOGF(log, "ClangUserExpression::ScanContext()"); m_target = exe_ctx.GetTargetPtr(); if (!(m_allow_cxx || m_allow_objc)) { - if (log) - log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); + LLDB_LOGF(log, " [CUE::SC] Settings inhibit C++ and Objective-C"); return; } StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == nullptr) { - if (log) - log->Printf(" [CUE::SC] Null stack frame"); + LLDB_LOGF(log, " [CUE::SC] Null stack frame"); return; } @@ -112,8 +111,7 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { lldb::eSymbolContextBlock); if (!sym_ctx.function) { - if (log) - log->Printf(" [CUE::SC] Null function"); + LLDB_LOGF(log, " [CUE::SC] Null function"); return; } @@ -121,16 +119,14 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { Block *function_block = sym_ctx.GetFunctionBlock(); if (!function_block) { - if (log) - log->Printf(" [CUE::SC] Null function block"); + LLDB_LOGF(log, " [CUE::SC] Null function block"); return; } CompilerDeclContext decl_context = function_block->GetDeclContext(); if (!decl_context) { - if (log) - log->Printf(" [CUE::SC] Null decl context"); + LLDB_LOGF(log, " [CUE::SC] Null decl context"); return; } @@ -317,17 +313,13 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { // count is not available, [myArray count] returns id, which can't be directly // cast to int without causing a clang error. static void ApplyObjcCastHack(std::string &expr) { -#define OBJC_CAST_HACK_FROM "(int)[" -#define OBJC_CAST_HACK_TO "(int)(long long)[" - - size_t from_offset; + const std::string from = "(int)["; + const std::string to = "(int)(long long)["; - while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) - expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, - OBJC_CAST_HACK_TO); + size_t offset; -#undef OBJC_CAST_HACK_TO -#undef OBJC_CAST_HACK_FROM + while ((offset = expr.find(from)) != expr.npos) + expr.replace(offset, from.size(), to); } bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager, @@ -336,6 +328,7 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)) { + m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state); m_result_delegate.RegisterPersistentState(persistent_state); } else { diagnostic_manager.PutString( @@ -384,30 +377,34 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) { } } -void ClangUserExpression::UpdateLanguageForExpr( +void ClangUserExpression::UpdateLanguageForExpr() { + m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown; + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) + return; + if (m_in_cplusplus_method) + m_expr_lang = lldb::eLanguageTypeC_plus_plus; + else if (m_in_objectivec_method) + m_expr_lang = lldb::eLanguageTypeObjC; + else + m_expr_lang = lldb::eLanguageTypeC; +} + +void ClangUserExpression::CreateSourceCode( DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, std::vector<std::string> modules_to_import, bool for_completion) { - m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown; + m_filename = m_clang_state->GetNextExprFileName(); std::string prefix = m_expr_prefix; if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { m_transformed_text = m_expr_text; } else { - std::unique_ptr<ClangExpressionSourceCode> source_code( - ClangExpressionSourceCode::CreateWrapped(prefix.c_str(), - m_expr_text.c_str())); - - if (m_in_cplusplus_method) - m_expr_lang = lldb::eLanguageTypeC_plus_plus; - else if (m_in_objectivec_method) - m_expr_lang = lldb::eLanguageTypeObjC; - else - m_expr_lang = lldb::eLanguageTypeC; - - if (!source_code->GetText(m_transformed_text, m_expr_lang, - m_in_static_method, exe_ctx, !m_ctx_obj, - for_completion, modules_to_import)) { + m_source_code.reset(ClangExpressionSourceCode::CreateWrapped( + m_filename, prefix.c_str(), m_expr_text.c_str())); + + if (!m_source_code->GetText(m_transformed_text, m_expr_lang, + m_in_static_method, exe_ctx, !m_ctx_obj, + for_completion, modules_to_import)) { diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't construct expression body"); return; @@ -417,7 +414,7 @@ void ClangUserExpression::UpdateLanguageForExpr( // transformed code. We need this later for the code completion. std::size_t original_start; std::size_t original_end; - bool found_bounds = source_code->GetOriginalBodyBounds( + bool found_bounds = m_source_code->GetOriginalBodyBounds( m_transformed_text, m_expr_lang, original_start, original_end); if (found_bounds) m_user_expression_start_pos = original_start; @@ -437,48 +434,70 @@ static bool SupportsCxxModuleImport(lldb::LanguageType language) { } } -std::vector<std::string> -ClangUserExpression::GetModulesToImport(ExecutionContext &exe_ctx) { +/// Utility method that puts a message into the expression log and +/// returns an invalid module configuration. +static CppModuleConfiguration LogConfigError(const std::string &msg) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + LLDB_LOG(log, "[C++ module config] {0}", msg); + return CppModuleConfiguration(); +} - if (!SupportsCxxModuleImport(Language())) - return {}; +CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, + ExecutionContext &exe_ctx) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + // Don't do anything if this is not a C++ module configuration. + if (!SupportsCxxModuleImport(language)) + return LogConfigError("Language doesn't support C++ modules"); Target *target = exe_ctx.GetTargetPtr(); - if (!target || !target->GetEnableImportStdModule()) - return {}; + if (!target) + return LogConfigError("No target"); + + if (!target->GetEnableImportStdModule()) + return LogConfigError("Importing std module not enabled in settings"); StackFrame *frame = exe_ctx.GetFramePtr(); if (!frame) - return {}; + return LogConfigError("No frame"); Block *block = frame->GetFrameBlock(); if (!block) - return {}; + return LogConfigError("No block"); SymbolContext sc; block->CalculateSymbolContext(&sc); if (!sc.comp_unit) - return {}; - - if (log) { - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) { - LLDB_LOG(log, "Found module in compile unit: {0:$[.]} - include dir: {1}", - llvm::make_range(m.path.begin(), m.path.end()), m.search_path); + return LogConfigError("Couldn't calculate symbol context"); + + // Build a list of files we need to analyze to build the configuration. + FileSpecList files; + for (const FileSpec &f : sc.comp_unit->GetSupportFiles()) + files.AppendIfUnique(f); + // We also need to look at external modules in the case of -gmodules as they + // contain the support files for libc++ and the C library. + sc.comp_unit->ForEachExternalModule([&files](lldb::ModuleSP module) { + for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) { + const FileSpecList &support_files = + module->GetCompileUnitAtIndex(i)->GetSupportFiles(); + for (const FileSpec &f : support_files) { + files.AppendIfUnique(f); + } } + }); + + LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze", + files.GetSize()); + if (log && log->GetVerbose()) { + for (const FileSpec &f : files) + LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}", + f.GetPath()); } - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) - m_include_directories.push_back(m.search_path); - - // Check if we imported 'std' or any of its submodules. - // We currently don't support importing any other modules in the expression - // parser. - for (const SourceModule &m : sc.comp_unit->GetImportedModules()) - if (!m.path.empty() && m.path.front() == "std") - return {"std"}; - - return {}; + // Try to create a configuration from the files. If there is no valid + // configuration possible with the files, this just returns an invalid + // configuration. + return CppModuleConfiguration(files); } bool ClangUserExpression::PrepareForParsing( @@ -506,14 +525,21 @@ bool ClangUserExpression::PrepareForParsing( SetupDeclVendor(exe_ctx, m_target); - std::vector<std::string> used_modules = GetModulesToImport(exe_ctx); - m_imported_cpp_modules = !used_modules.empty(); + CppModuleConfiguration module_config = GetModuleConfig(m_language, exe_ctx); + llvm::ArrayRef<std::string> imported_modules = + module_config.GetImportedModules(); + m_imported_cpp_modules = !imported_modules.empty(); + m_include_directories = module_config.GetIncludeDirs(); LLDB_LOG(log, "List of imported modules in expression: {0}", - llvm::make_range(used_modules.begin(), used_modules.end())); - - UpdateLanguageForExpr(diagnostic_manager, exe_ctx, used_modules, - for_completion); + llvm::make_range(imported_modules.begin(), imported_modules.end())); + LLDB_LOG(log, "List of include directories gathered for modules: {0}", + llvm::make_range(m_include_directories.begin(), + m_include_directories.end())); + + UpdateLanguageForExpr(); + CreateSourceCode(diagnostic_manager, exe_ctx, imported_modules, + for_completion); return true; } @@ -527,8 +553,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false)) return false; - if (log) - log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str()); //////////////////////////////////// // Set up the target and compiler @@ -573,7 +598,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, // parser_sp will never be empty. ClangExpressionParser parser(exe_scope, *this, generate_debug_info, - m_include_directories); + m_include_directories, m_filename); unsigned num_errors = parser.Parse(diagnostic_manager); @@ -586,8 +611,11 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, size_t fixed_end; const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); - if (ClangExpressionSourceCode::GetOriginalBodyBounds( - fixed_expression, m_expr_lang, fixed_start, fixed_end)) + // Retrieve the original expression in case we don't have a top level + // expression (which has no surrounding source code). + if (m_source_code && + m_source_code->GetOriginalBodyBounds(fixed_expression, m_expr_lang, + fixed_start, fixed_end)) m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); } @@ -648,12 +676,10 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, register_execution_unit = true; } - if (register_execution_unit) { - llvm::cast<PersistentExpressionState>( - exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage( - m_language)) + if (register_execution_unit) + exe_ctx.GetTargetPtr() + ->GetPersistentExpressionStateForLanguage(m_language) ->RegisterExecutionUnit(m_execution_unit_sp); - } } if (generate_debug_info) { @@ -726,8 +752,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx, if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true)) return false; - if (log) - log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str()); ////////////////////////// // Parse the expression diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 24c152bdb45d..d94f9cc5e066 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -15,6 +15,7 @@ #include "ASTStructExtractor.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionHelper.h" +#include "ClangExpressionSourceCode.h" #include "ClangExpressionVariable.h" #include "IRForTarget.h" @@ -105,6 +106,9 @@ public: /// If not eResultTypeAny, the type to use for the expression /// result. /// + /// \param[in] options + /// Additional options for the expression. + /// /// \param[in] ctx_obj /// The object (if any) in which context the expression /// must be evaluated. For details see the comment to @@ -175,11 +179,11 @@ private: lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) override; - std::vector<std::string> GetModulesToImport(ExecutionContext &exe_ctx); - void UpdateLanguageForExpr(DiagnosticManager &diagnostic_manager, - ExecutionContext &exe_ctx, - std::vector<std::string> modules_to_import, - bool for_completion); + void CreateSourceCode(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx, + std::vector<std::string> modules_to_import, + bool for_completion); + void UpdateLanguageForExpr(); bool SetupPersistentState(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx); bool PrepareForParsing(DiagnosticManager &diagnostic_manager, @@ -205,13 +209,17 @@ private: /// The language type of the current expression. lldb::LanguageType m_expr_lang = lldb::eLanguageTypeUnknown; /// The include directories that should be used when parsing the expression. - std::vector<ConstString> m_include_directories; + std::vector<std::string> m_include_directories; /// The absolute character position in the transformed source code where the /// user code (as typed by the user) starts. If the variable is empty, then we /// were not able to calculate this position. llvm::Optional<size_t> m_user_expression_start_pos; ResultDelegate m_result_delegate; + ClangPersistentVariables *m_clang_state; + std::unique_ptr<ClangExpressionSourceCode> m_source_code; + /// File name used for the expression. + std::string m_filename; /// The object (if any) in which context the expression is evaluated. /// See the comment to `UserExpression::Evaluate` for details. @@ -219,6 +227,23 @@ private: /// True iff this expression explicitly imported C++ modules. bool m_imported_cpp_modules = false; + + /// True if the expression parser should enforce the presence of a valid class + /// pointer in order to generate the expression as a method. + bool m_enforce_valid_object = true; + /// True if the expression is compiled as a C++ member function (true if it + /// was parsed when exe_ctx was in a C++ method). + bool m_in_cplusplus_method = false; + /// True if the expression is compiled as an Objective-C method (true if it + /// was parsed when exe_ctx was in an Objective-C method). + bool m_in_objectivec_method = false; + /// True if the expression is compiled as a static (or class) method + /// (currently true if it was parsed when exe_ctx was in an Objective-C class + /// method). + bool m_in_static_method = false; + /// True if "this" or "self" must be looked up and passed in. False if the + /// expression doesn't really use them and they can be NULL. + bool m_needs_object_ptr = false; }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 5eec224477fc..564c62c6a2c6 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/Config.h" + #include "ClangUtilityFunction.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" diff --git a/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp new file mode 100644 index 000000000000..51ae73285b53 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -0,0 +1,82 @@ +//===-- CppModuleConfiguration.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 "CppModuleConfiguration.h" + +#include "ClangHost.h" +#include "lldb/Host/FileSystem.h" + +using namespace lldb_private; + +bool CppModuleConfiguration::SetOncePath::TrySet(llvm::StringRef path) { + // Setting for the first time always works. + if (m_first) { + m_path = path.str(); + m_valid = true; + m_first = false; + return true; + } + // Changing the path to the same value is fine. + if (m_path == path) + return true; + + // Changing the path after it was already set is not allowed. + m_valid = false; + return false; +} + +bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { + using namespace llvm::sys::path; + // Convert to slashes to make following operations simpler. + std::string dir_buffer = convert_to_slash(f.GetDirectory().GetStringRef()); + llvm::StringRef posix_dir(dir_buffer); + + // Check for /c++/vX/ that is used by libc++. + static llvm::Regex libcpp_regex(R"regex(/c[+][+]/v[0-9]/)regex"); + if (libcpp_regex.match(f.GetPath())) { + // Strip away libc++'s /experimental directory if there is one. + posix_dir.consume_back("/experimental"); + return m_std_inc.TrySet(posix_dir); + } + + // Check for /usr/include. On Linux this might be /usr/include/bits, so + // we should remove that '/bits' suffix to get the actual include directory. + if (posix_dir.endswith("/usr/include/bits")) + posix_dir.consume_back("/bits"); + if (posix_dir.endswith("/usr/include")) + return m_c_inc.TrySet(posix_dir); + + // File wasn't interesting, continue analyzing. + return true; +} + +bool CppModuleConfiguration::hasValidConfig() { + // We all these include directories to have a valid usable configuration. + return m_c_inc.Valid() && m_std_inc.Valid(); +} + +CppModuleConfiguration::CppModuleConfiguration( + const FileSpecList &support_files) { + // Analyze all files we were given to build the configuration. + bool error = !llvm::all_of(support_files, + std::bind(&CppModuleConfiguration::analyzeFile, + this, std::placeholders::_1)); + // If we have a valid configuration at this point, set the + // include directories and module list that should be used. + if (!error && hasValidConfig()) { + // Calculate the resource directory for LLDB. + llvm::SmallString<256> resource_dir; + llvm::sys::path::append(resource_dir, GetClangResourceDir().GetPath(), + "include"); + m_resource_inc = resource_dir.str(); + + // This order matches the way Clang orders these directories. + m_include_dirs = {m_std_inc.Get(), m_resource_inc, m_c_inc.Get()}; + m_imported_modules = {"std"}; + } +} diff --git a/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h new file mode 100644 index 000000000000..8e892e37d0de --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -0,0 +1,84 @@ +//===-- CppModuleConfiguration.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 liblldb_CppModuleConfiguration_h_ +#define liblldb_CppModuleConfiguration_h_ + +#include <lldb/Core/FileSpecList.h> +#include <llvm/Support/Regex.h> + +namespace lldb_private { + +/// A Clang configuration when importing C++ modules. +/// +/// Includes a list of include paths that should be used when importing +/// and a list of modules that can be imported. Currently only used when +/// importing the 'std' module and its dependencies. +class CppModuleConfiguration { + /// Utility class for a path that can only be set once. + class SetOncePath { + std::string m_path; + bool m_valid = false; + /// True iff this path hasn't been set yet. + bool m_first = true; + + public: + /// Try setting the path. Returns true if the path was set and false if + /// the path was already set. + LLVM_NODISCARD bool TrySet(llvm::StringRef path); + /// Return the path if there is one. + std::string Get() const { + assert(m_valid && "Called Get() on an invalid SetOncePath?"); + return m_path; + } + /// Returns true iff this path was set exactly once so far. + bool Valid() const { return m_valid; } + }; + + /// If valid, the include path used for the std module. + SetOncePath m_std_inc; + /// If valid, the include path to the C library (e.g. /usr/include). + SetOncePath m_c_inc; + /// The Clang resource include path for this configuration. + std::string m_resource_inc; + + std::vector<std::string> m_include_dirs; + std::vector<std::string> m_imported_modules; + + /// Analyze a given source file to build the current configuration. + /// Returns false iff there was a fatal error that makes analyzing any + /// further files pointless as the configuration is now invalid. + bool analyzeFile(const FileSpec &f); + +public: + /// Creates a configuraiton by analyzing the given list of used source files. + /// + /// Currently only looks at the used paths and doesn't actually access the + /// files on the disk. + explicit CppModuleConfiguration(const FileSpecList &support_files); + /// Creates an empty and invalid configuration. + CppModuleConfiguration() {} + + /// Returns true iff this is a valid configuration that can be used to + /// load and compile modules. + bool hasValidConfig(); + + /// Returns a list of include directories that should be used when using this + /// configuration (e.g. {"/usr/include", "/usr/include/c++/v1"}). + llvm::ArrayRef<std::string> GetIncludeDirs() const { return m_include_dirs; } + + /// Returns a list of (top level) modules that should be imported when using + /// this configuration (e.g. {"std"}). + llvm::ArrayRef<std::string> GetImportedModules() const { + return m_imported_modules; + } +}; + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp b/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp index f8e004fe7d4a..d5ffb9529f36 100644 --- a/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp +++ b/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp @@ -320,9 +320,8 @@ protected: bool InstrumentInstruction(llvm::Instruction *inst) override { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("Instrumenting load/store instruction: %s\n", - PrintValue(inst).c_str()); + LLDB_LOGF(log, "Instrumenting load/store instruction: %s\n", + PrintValue(inst).c_str()); if (!m_valid_pointer_check_func) m_valid_pointer_check_func = @@ -483,9 +482,8 @@ protected: std::string name_str = called_function->getName().str(); const char *name_cstr = name_str.c_str(); - if (log) - log->Printf("Found call to %s: %s\n", name_cstr, - PrintValue(call_inst).c_str()); + LLDB_LOGF(log, "Found call to %s: %s\n", name_cstr, + PrintValue(call_inst).c_str()); if (name_str.find("objc_msgSend") == std::string::npos) return true; @@ -520,10 +518,9 @@ protected: return true; } - if (log) - log->Printf( - "Function name '%s' contains 'objc_msgSend' but is not handled", - name_str.c_str()); + LLDB_LOGF(log, + "Function name '%s' contains 'objc_msgSend' but is not handled", + name_str.c_str()); return true; } @@ -548,8 +545,7 @@ bool IRDynamicChecks::runOnModule(llvm::Module &M) { llvm::Function *function = M.getFunction(StringRef(m_func_name)); if (!function) { - if (log) - log->Printf("Couldn't find %s() in the module", m_func_name.c_str()); + LLDB_LOGF(log, "Couldn't find %s() in the module", m_func_name.c_str()); return false; } @@ -582,7 +578,7 @@ bool IRDynamicChecks::runOnModule(llvm::Module &M) { oss.flush(); - log->Printf("Module after dynamic checks: \n%s", s.c_str()); + LLDB_LOGF(log, "Module after dynamic checks: \n%s", s.c_str()); } return true; diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 07acb2e1030f..4e871f7d6a44 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -43,6 +43,8 @@ using namespace llvm; static char ID; +typedef SmallVector<Instruction *, 2> InstrList; + IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : m_maker(maker), m_values() {} @@ -153,6 +155,15 @@ clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) { return DeclForGlobal(global_val, m_module); } +/// Returns true iff the mangled symbol is for a static guard variable. +static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol, + bool check_ms_abi = true) { + bool result = mangled_symbol.startswith("_ZGV"); // Itanium ABI guard variable + if (check_ms_abi) + result |= mangled_symbol.endswith("@4IA"); // Microsoft ABI + return result; +} + bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -164,64 +175,58 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); - std::string result_name_str; - const char *result_name = nullptr; + llvm::StringRef result_name; + bool found_result = false; - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), - ve = value_symbol_table.end(); - vi != ve; ++vi) { - result_name_str = vi->first().str(); - const char *value_name = result_name_str.c_str(); + for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { + result_name = value_symbol.first(); - if (strstr(value_name, "$__lldb_expr_result_ptr") && - strncmp(value_name, "_ZGV", 4)) { - result_name = value_name; + // Check if this is a guard variable. It seems this causes some hiccups + // on Windows, so let's only check for Itanium guard variables. + bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false); + + if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var) { + found_result = true; m_result_is_pointer = true; break; } - if (strstr(value_name, "$__lldb_expr_result") && - strncmp(value_name, "_ZGV", 4)) { - result_name = value_name; + if (result_name.contains("$__lldb_expr_result") && !is_guard_var) { + found_result = true; m_result_is_pointer = false; break; } } - if (!result_name) { - if (log) - log->PutCString("Couldn't find result variable"); + if (!found_result) { + LLDB_LOG(log, "Couldn't find result variable"); return true; } - if (log) - log->Printf("Result name: \"%s\"", result_name); + LLDB_LOG(log, "Result name: \"{0}\"", result_name); Value *result_value = m_module->getNamedValue(result_name); if (!result_value) { - if (log) - log->PutCString("Result variable had no data"); + LLDB_LOG(log, "Result variable had no data"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable's " - "name (%s) exists, but not its definition\n", + m_error_stream.Format("Internal error [IRForTarget]: Result variable's " + "name ({0}) exists, but not its definition\n", result_name); return false; } - if (log) - log->Printf("Found result in the IR: \"%s\"", - PrintValue(result_value, false).c_str()); + LLDB_LOG(log, "Found result in the IR: \"{0}\"", + PrintValue(result_value, false)); GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); if (!result_global) { - if (log) - log->PutCString("Result variable isn't a GlobalVariable"); + LLDB_LOG(log, "Result variable isn't a GlobalVariable"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) " + m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " "is defined, but is not a global variable\n", result_name); @@ -230,10 +235,9 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { clang::NamedDecl *result_decl = DeclForGlobal(result_global); if (!result_decl) { - if (log) - log->PutCString("Result variable doesn't have a corresponding Decl"); + LLDB_LOG(log, "Result variable doesn't have a corresponding Decl"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable (%s) " + m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " "does not have a corresponding Clang entity\n", result_name); @@ -246,16 +250,15 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { result_decl->print(decl_desc_stream); decl_desc_stream.flush(); - log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); + LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str); } clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); if (!result_var) { - if (log) - log->PutCString("Result variable Decl isn't a VarDecl"); + LLDB_LOG(log, "Result variable Decl isn't a VarDecl"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable " - "(%s)'s corresponding Clang entity isn't a " + m_error_stream.Format("Internal error [IRForTarget]: Result variable " + "({0})'s corresponding Clang entity isn't a " "variable\n", result_name); @@ -292,10 +295,9 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::ClangASTContext::GetASTContext( &result_decl->getASTContext())); } else { - if (log) - log->PutCString("Expected result to have pointer type, but it did not"); + LLDB_LOG(log, "Expected result to have pointer type, but it did not"); - m_error_stream.Printf("Internal error [IRForTarget]: Lvalue result (%s) " + m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) " "is not a pointer variable\n", result_name); @@ -316,8 +318,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::StreamString type_desc_stream; m_result_type.DumpTypeDescription(&type_desc_stream); - if (log) - log->Printf("Result type has unknown size"); + LLDB_LOG(log, "Result type has unknown size"); m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' " "couldn't be determined\n", @@ -329,15 +330,13 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { lldb_private::StreamString type_desc_stream; m_result_type.DumpTypeDescription(&type_desc_stream); - log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); + LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData()); } m_result_name = lldb_private::ConstString("$RESULT_NAME"); - if (log) - log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, - m_result_name.GetCString(), - m_result_type.GetByteSize(nullptr).getValueOr(0)); + LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}", + m_result_name, m_result_type.GetByteSize(nullptr).getValueOr(0)); // Construct a new result global and set up its metadata @@ -369,10 +368,8 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { m_module->getNamedMetadata("clang.global.decl.ptrs"); named_metadata->addOperand(persistent_global_md); - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(result_global).c_str(), - PrintValue(new_result_global).c_str()); + LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global), + PrintValue(new_result_global)); if (result_global->use_empty()) { // We need to synthesize a store for this variable, because otherwise @@ -385,11 +382,10 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { return false; if (!result_global->hasInitializer()) { - if (log) - log->Printf("Couldn't find initializer for unused variable"); + LLDB_LOG(log, "Couldn't find initializer for unused variable"); - m_error_stream.Printf("Internal error [IRForTarget]: Result variable " - "(%s) has no writes and no initializer\n", + m_error_stream.Format("Internal error [IRForTarget]: Result variable " + "({0}) has no writes and no initializer\n", result_name); return false; @@ -400,9 +396,8 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { StoreInst *synthesized_store = new StoreInst(initializer, new_result_global, first_entry_instruction); - if (log) - log->Printf("Synthesized result store \"%s\"\n", - PrintValue(synthesized_store).c_str()); + LLDB_LOG(log, "Synthesized result store \"{0}\"\n", + PrintValue(synthesized_store)); } else { result_global->replaceAllUsesWith(new_result_global); } @@ -438,7 +433,6 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str, missing_weak); if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak) { - if (log) log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C " @@ -448,9 +442,8 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, return false; } - if (log) - log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, - CFStringCreateWithBytes_addr); + LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}", + CFStringCreateWithBytes_addr); // Build the function type: // @@ -543,9 +536,7 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder, m_error_stream)) { - if (log) - log->PutCString( - "Couldn't replace the NSString with the result of the call"); + LLDB_LOG(log, "Couldn't replace the NSString with the result of the call"); m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an " "Objective-C constant string with a dynamic " @@ -565,21 +556,17 @@ bool IRForTarget::RewriteObjCConstStrings() { ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), - ve = value_symbol_table.end(); - vi != ve; ++vi) { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); + for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { + llvm::StringRef value_name = value_symbol.first(); - if (strstr(value_name_cstr, "_unnamed_cfstring_")) { - Value *nsstring_value = vi->second; + if (value_name.contains("_unnamed_cfstring_")) { + Value *nsstring_value = value_symbol.second; GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value); if (!nsstring_global) { - if (log) - log->PutCString("NSString variable is not a GlobalVariable"); + LLDB_LOG(log, "NSString variable is not a GlobalVariable"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string is not a global variable\n"); @@ -588,8 +575,7 @@ bool IRForTarget::RewriteObjCConstStrings() { } if (!nsstring_global->hasInitializer()) { - if (log) - log->PutCString("NSString variable does not have an initializer"); + LLDB_LOG(log, "NSString variable does not have an initializer"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string does not have an initializer\n"); @@ -601,9 +587,8 @@ bool IRForTarget::RewriteObjCConstStrings() { dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); if (!nsstring_struct) { - if (log) - log->PutCString( - "NSString variable's initializer is not a ConstantStruct"); + LLDB_LOG(log, + "NSString variable's initializer is not a ConstantStruct"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string is not a structure constant\n"); @@ -621,10 +606,11 @@ bool IRForTarget::RewriteObjCConstStrings() { // }; if (nsstring_struct->getNumOperands() != 4) { - if (log) - log->Printf("NSString variable's initializer structure has an " - "unexpected number of members. Should be 4, is %d", - nsstring_struct->getNumOperands()); + + LLDB_LOG(log, + "NSString variable's initializer structure has an " + "unexpected number of members. Should be 4, is {0}", + nsstring_struct->getNumOperands()); m_error_stream.Printf("Internal error [IRForTarget]: The struct for an " "Objective-C constant string is not as " @@ -636,8 +622,7 @@ bool IRForTarget::RewriteObjCConstStrings() { Constant *nsstring_member = nsstring_struct->getOperand(2); if (!nsstring_member) { - if (log) - log->PutCString("NSString initializer's str element was empty"); + LLDB_LOG(log, "NSString initializer's str element was empty"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string does not have a string " @@ -649,9 +634,8 @@ bool IRForTarget::RewriteObjCConstStrings() { ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member); if (!nsstring_expr) { - if (log) - log->PutCString( - "NSString initializer's str element is not a ConstantExpr"); + LLDB_LOG(log, + "NSString initializer's str element is not a ConstantExpr"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string's string initializer is not " @@ -671,9 +655,8 @@ bool IRForTarget::RewriteObjCConstStrings() { } if (!cstr_global) { - if (log) - log->PutCString( - "NSString initializer's str element is not a GlobalVariable"); + LLDB_LOG(log, + "NSString initializer's str element is not a GlobalVariable"); m_error_stream.Printf("Internal error [IRForTarget]: Unhandled" "constant string initializer\n"); @@ -682,9 +665,8 @@ bool IRForTarget::RewriteObjCConstStrings() { } if (!cstr_global->hasInitializer()) { - if (log) - log->PutCString("NSString initializer's str element does not have an " - "initializer"); + LLDB_LOG(log, "NSString initializer's str element does not have an " + "initializer"); m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " "constant string's string initializer doesn't " @@ -726,21 +708,18 @@ bool IRForTarget::RewriteObjCConstStrings() { ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); - if (log) { - if (cstr_array) - log->Printf("Found NSString constant %s, which contains \"%s\"", - value_name_cstr, cstr_array->getAsString().str().c_str()); - else - log->Printf("Found NSString constant %s, which contains \"\"", - value_name_cstr); - } + if (cstr_array) + LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"", + value_name, cstr_array->getAsString()); + else + LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"", + value_name); if (!cstr_array) cstr_global = nullptr; if (!RewriteObjCConstString(nsstring_global, cstr_global)) { - if (log) - log->PutCString("Error rewriting the constant string"); + LLDB_LOG(log, "Error rewriting the constant string"); // We don't print an error message here because RewriteObjCConstString // has done so for us. @@ -750,19 +729,15 @@ bool IRForTarget::RewriteObjCConstStrings() { } } - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), - ve = value_symbol_table.end(); - vi != ve; ++vi) { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); + for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { + llvm::StringRef value_name = value_symbol.first(); - if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) { - GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second); + if (value_name == "__CFConstantStringClassReference") { + GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second); if (!gv) { - if (log) - log->PutCString( - "__CFConstantStringClassReference is not a global variable"); + LLDB_LOG(log, + "__CFConstantStringClassReference is not a global variable"); m_error_stream.Printf("Internal error [IRForTarget]: Found a " "CFConstantStringClassReference, but it is not a " @@ -850,9 +825,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { std::string omvn_initializer_string = omvn_initializer_array->getAsString(); - if (log) - log->Printf("Found Objective-C selector reference \"%s\"", - omvn_initializer_string.c_str()); + LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"", + omvn_initializer_string); // Construct a call to sel_registerName @@ -866,9 +840,7 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak) return false; - if (log) - log->Printf("Found sel_registerName at 0x%" PRIx64, - sel_registerName_addr); + LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr); // Build the function type: struct objc_selector // *sel_registerName(uint8_t*) @@ -921,32 +893,21 @@ bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; - InstrList selector_loads; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; - + for (Instruction &inst : basic_block) { if (LoadInst *load = dyn_cast<LoadInst>(&inst)) if (IsObjCSelectorRef(load->getPointerOperand())) selector_loads.push_back(&inst); } - InstrIterator iter; - - for (iter = selector_loads.begin(); iter != selector_loads.end(); ++iter) { - if (!RewriteObjCSelector(*iter)) { + for (Instruction *inst : selector_loads) { + if (!RewriteObjCSelector(inst)) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a " "static reference to an Objective-C selector to a " "dynamic reference\n"); - if (log) - log->PutCString( - "Couldn't rewrite a reference to an Objective-C selector"); + LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector"); return false; } @@ -1022,9 +983,8 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) { std::string ocn_initializer_string = ocn_initializer_array->getAsString(); - if (log) - log->Printf("Found Objective-C class reference \"%s\"", - ocn_initializer_string.c_str()); + LLDB_LOG(log, "Found Objective-C class reference \"{0}\"", + ocn_initializer_string); // Construct a call to objc_getClass @@ -1038,9 +998,7 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) { if (objc_getClass_addr == LLDB_INVALID_ADDRESS || missing_weak) return false; - if (log) - log->Printf("Found objc_getClass at 0x%" PRIx64, - objc_getClass_addr); + LLDB_LOG(log, "Found objc_getClass at {0}", objc_getClass_addr); // Build the function type: %struct._objc_class *objc_getClass(i8*) @@ -1086,32 +1044,21 @@ bool IRForTarget::RewriteObjCClassReferences(BasicBlock &basic_block) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; - InstrList class_loads; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; - + for (Instruction &inst : basic_block) { if (LoadInst *load = dyn_cast<LoadInst>(&inst)) if (IsObjCClassReference(load->getPointerOperand())) class_loads.push_back(&inst); } - InstrIterator iter; - - for (iter = class_loads.begin(); iter != class_loads.end(); ++iter) { - if (!RewriteObjCClassReference(*iter)) { + for (Instruction *inst : class_loads) { + if (!RewriteObjCClassReference(inst)) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a " "static reference to an Objective-C class to a " "dynamic reference\n"); - if (log) - log->PutCString( - "Couldn't rewrite a reference to an Objective-C class"); + LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C class"); return false; } @@ -1180,9 +1127,8 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { LoadInst *persistent_load = new LoadInst(persistent_global, "", alloc); - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", PrintValue(alloc).c_str(), - PrintValue(persistent_load).c_str()); + LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc), + PrintValue(persistent_load)); alloc->replaceAllUsesWith(persistent_load); alloc->eraseFromParent(); @@ -1197,23 +1143,16 @@ bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; - InstrList pvar_allocs; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; + for (Instruction &inst : basic_block) { if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) { llvm::StringRef alloc_name = alloc->getName(); if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")) { if (alloc_name.find_first_of("0123456789") == 1) { - if (log) - log->Printf("Rejecting a numeric persistent variable."); + LLDB_LOG(log, "Rejecting a numeric persistent variable."); m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, " "$1, ... are reserved for use as result " @@ -1227,16 +1166,12 @@ bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { } } - InstrIterator iter; - - for (iter = pvar_allocs.begin(); iter != pvar_allocs.end(); ++iter) { - if (!RewritePersistentAlloc(*iter)) { + for (Instruction *inst : pvar_allocs) { + if (!RewritePersistentAlloc(inst)) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " "the creation of a persistent variable\n"); - if (log) - log->PutCString( - "Couldn't rewrite the creation of a persistent variable"); + LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable"); return false; } @@ -1245,79 +1180,12 @@ bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { return true; } -bool IRForTarget::MaterializeInitializer(uint8_t *data, Constant *initializer) { - if (!initializer) - return true; - - lldb_private::Log *log( - lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - if (log && log->GetVerbose()) - log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, - PrintValue(initializer).c_str()); - - Type *initializer_type = initializer->getType(); - - if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer)) { - size_t constant_size = m_target_data->getTypeStoreSize(initializer_type); - lldb_private::Scalar scalar = int_initializer->getValue().zextOrTrunc( - llvm::NextPowerOf2(constant_size) * 8); - - lldb_private::Status get_data_error; - return scalar.GetAsMemoryData(data, constant_size, - lldb_private::endian::InlHostByteOrder(), - get_data_error) != 0; - } else if (ConstantDataArray *array_initializer = - dyn_cast<ConstantDataArray>(initializer)) { - if (array_initializer->isString()) { - std::string array_initializer_string = array_initializer->getAsString(); - memcpy(data, array_initializer_string.c_str(), - m_target_data->getTypeStoreSize(initializer_type)); - } else { - ArrayType *array_initializer_type = array_initializer->getType(); - Type *array_element_type = array_initializer_type->getElementType(); - - size_t element_size = m_target_data->getTypeAllocSize(array_element_type); - - for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) { - Value *operand_value = array_initializer->getOperand(i); - Constant *operand_constant = dyn_cast<Constant>(operand_value); - - if (!operand_constant) - return false; - - if (!MaterializeInitializer(data + (i * element_size), - operand_constant)) - return false; - } - } - return true; - } else if (ConstantStruct *struct_initializer = - dyn_cast<ConstantStruct>(initializer)) { - StructType *struct_initializer_type = struct_initializer->getType(); - const StructLayout *struct_layout = - m_target_data->getStructLayout(struct_initializer_type); - - for (unsigned i = 0; i < struct_initializer->getNumOperands(); ++i) { - if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), - struct_initializer->getOperand(i))) - return false; - } - return true; - } else if (isa<ConstantAggregateZero>(initializer)) { - memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); - return true; - } - return false; -} - // This function does not report errors; its callers are responsible. bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); + LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr)); if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) { switch (constant_expr->getOpcode()) { @@ -1343,25 +1211,26 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { if (!global_variable->hasExternalLinkage()) return true; - if (log) - log->Printf("Found global variable \"%s\" without metadata", - global_variable->getName().str().c_str()); + LLDB_LOG(log, "Found global variable \"{0}\" without metadata", + global_variable->getName()); return false; } - std::string name(named_decl->getName().str()); + llvm::StringRef name(named_decl->getName()); clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); if (value_decl == nullptr) return false; - lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), - value_decl->getType()); + lldb_private::CompilerType compiler_type( + lldb_private::ClangASTContext::GetASTContext( + &value_decl->getASTContext()), + value_decl->getType().getAsOpaquePtr()); const Type *value_type = nullptr; - if (name[0] == '$') { + if (name.startswith("$")) { // The $__lldb_expr_result name indicates the return value has allocated // as a static variable. Per the comment at // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static @@ -1381,31 +1250,24 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { llvm::Optional<uint64_t> value_size = compiler_type.GetByteSize(nullptr); if (!value_size) return false; - lldb::offset_t value_alignment = - (compiler_type.GetTypeBitAlign() + 7ull) / 8ull; - - if (log) { - log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 - ", align %" PRIu64 "]", - name.c_str(), - lldb_private::ClangUtil::GetQualType(compiler_type) - .getAsString() - .c_str(), - PrintType(value_type).c_str(), *value_size, value_alignment); - } - - if (named_decl && - !m_decl_map->AddValueToStruct( - named_decl, lldb_private::ConstString(name.c_str()), llvm_value_ptr, - *value_size, value_alignment)) { - if (!global_variable->hasExternalLinkage()) - return true; - else - return true; - } + llvm::Optional<size_t> opt_alignment = compiler_type.GetTypeBitAlign(nullptr); + if (!opt_alignment) + return false; + lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull; + + LLDB_LOG(log, + "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, " + "align {4}]", + name, + lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(), + PrintType(value_type), *value_size, value_alignment); + + if (named_decl) + m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name), + llvm_value_ptr, *value_size, + value_alignment); } else if (dyn_cast<llvm::Function>(llvm_value_ptr)) { - if (log) - log->Printf("Function pointers aren't handled right now"); + LLDB_LOG(log, "Function pointers aren't handled right now"); return false; } @@ -1424,14 +1286,12 @@ bool IRForTarget::HandleSymbol(Value *symbol) { m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny); if (symbol_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Symbol \"%s\" had no address", name.GetCString()); + LLDB_LOG(log, "Symbol \"{0}\" had no address", name); return false; } - if (log) - log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); + LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr); Type *symbol_type = symbol->getType(); @@ -1440,9 +1300,8 @@ bool IRForTarget::HandleSymbol(Value *symbol) { Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); - if (log) - log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), - PrintValue(symbol_addr_ptr).c_str()); + LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol), + PrintValue(symbol_addr_ptr)); symbol->replaceAllUsesWith(symbol_addr_ptr); @@ -1453,14 +1312,12 @@ bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); + LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old)); for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); op_index < num_ops; ++op_index) - if (!MaybeHandleVariable(Old->getArgOperand( - op_index))) // conservatively believe that this is a store - { + // conservatively believe that this is a store + if (!MaybeHandleVariable(Old->getArgOperand(op_index))) { m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " "one of the arguments of a function call.\n"); @@ -1493,9 +1350,8 @@ bool IRForTarget::HandleObjCClass(Value *classlist_reference) { lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); - if (log) - log->Printf("Found reference to Objective-C class %s (0x%llx)", - name_cstr.AsCString(), (unsigned long long)class_ptr); + LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name, + (unsigned long long)class_ptr); if (class_ptr == LLDB_INVALID_ADDRESS) return false; @@ -1528,13 +1384,9 @@ bool IRForTarget::HandleObjCClass(Value *classlist_reference) { } bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) { - BasicBlock::iterator ii; - std::vector<CallInst *> calls_to_remove; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; - + for (Instruction &inst : basic_block) { CallInst *call = dyn_cast<CallInst>(&inst); // MaybeHandleCallArguments handles error reporting; we are silent here @@ -1557,25 +1409,16 @@ bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) { calls_to_remove.push_back(call); } - for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), - ce = calls_to_remove.end(); - ci != ce; ++ci) { - (*ci)->eraseFromParent(); - } + for (CallInst *ci : calls_to_remove) + ci->eraseFromParent(); return true; } bool IRForTarget::ResolveCalls(BasicBlock &basic_block) { - ///////////////////////////////////////////////////////////////////////// // Prepare the current basic block for execution in the remote process - // - - BasicBlock::iterator ii; - - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; + for (Instruction &inst : basic_block) { CallInst *call = dyn_cast<CallInst>(&inst); // MaybeHandleCallArguments handles error reporting; we are silent here @@ -1591,31 +1434,27 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); for (GlobalVariable &global_var : m_module->globals()) { - std::string global_name = global_var.getName().str(); + llvm::StringRef global_name = global_var.getName(); - if (log) - log->Printf("Examining %s, DeclForGlobalValue returns %p", - global_name.c_str(), - static_cast<void *>(DeclForGlobal(&global_var))); + LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name, + static_cast<void *>(DeclForGlobal(&global_var))); - if (global_name.find("OBJC_IVAR") == 0) { + if (global_name.startswith("OBJC_IVAR")) { if (!HandleSymbol(&global_var)) { - m_error_stream.Printf("Error [IRForTarget]: Couldn't find Objective-C " - "indirect ivar symbol %s\n", - global_name.c_str()); + m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C " + "indirect ivar symbol {0}\n", + global_name); return false; } - } else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != - global_name.npos) { + } else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) { if (!HandleObjCClass(&global_var)) { m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " "for an Objective-C static method call\n"); return false; } - } else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != - global_name.npos) { + } else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) { if (!HandleObjCClass(&global_var)) { m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " "for an Objective-C static method call\n"); @@ -1624,9 +1463,9 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { } } else if (DeclForGlobal(&global_var)) { if (!MaybeHandleVariable(&global_var)) { - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " - "external variable %s\n", - global_name.c_str()); + m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite " + "external variable {0}\n", + global_name); return false; } @@ -1637,14 +1476,12 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { } static bool isGuardVariableRef(Value *V) { - Constant *Old = nullptr; + Constant *Old = dyn_cast<Constant>(V); - if (!(Old = dyn_cast<Constant>(V))) + if (!Old) return false; - ConstantExpr *CE = nullptr; - - if ((CE = dyn_cast<ConstantExpr>(V))) { + if (auto CE = dyn_cast<ConstantExpr>(V)) { if (CE->getOpcode() != Instruction::BitCast) return false; @@ -1653,12 +1490,8 @@ static bool isGuardVariableRef(Value *V) { GlobalVariable *GV = dyn_cast<GlobalVariable>(Old); - if (!GV || !GV->hasName() || - (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable - !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable - { + if (!GV || !GV->hasName() || !isGuardVariableSymbol(GV->getName())) return false; - } return true; } @@ -1674,20 +1507,12 @@ static void ExciseGuardStore(Instruction *guard_store) { } bool IRForTarget::RemoveGuards(BasicBlock &basic_block) { - /////////////////////////////////////////////////////// // Eliminate any reference to guard variables found. - // - - BasicBlock::iterator ii; - - typedef SmallVector<Instruction *, 2> InstrList; - typedef InstrList::iterator InstrIterator; InstrList guard_loads; InstrList guard_stores; - for (ii = basic_block.begin(); ii != basic_block.end(); ++ii) { - Instruction &inst = *ii; + for (Instruction &inst : basic_block) { if (LoadInst *load = dyn_cast<LoadInst>(&inst)) if (isGuardVariableRef(load->getPointerOperand())) @@ -1698,13 +1523,11 @@ bool IRForTarget::RemoveGuards(BasicBlock &basic_block) { guard_stores.push_back(&inst); } - InstrIterator iter; + for (Instruction *inst : guard_loads) + TurnGuardLoadIntoZero(inst); - for (iter = guard_loads.begin(); iter != guard_loads.end(); ++iter) - TurnGuardLoadIntoZero(*iter); - - for (iter = guard_stores.begin(); iter != guard_stores.end(); ++iter) - ExciseGuardStore(*iter); + for (Instruction *inst : guard_stores) + ExciseGuardStore(inst); return true; } @@ -1837,8 +1660,7 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { m_decl_map->DoStructLayout(); - if (log) - log->Printf("Element arrangement:"); + LLDB_LOG(log, "Element arrangement:"); uint32_t num_elements; uint32_t element_index; @@ -1884,9 +1706,9 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { } if (!iter->getName().equals("_cmd")) { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes '%s' " + m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' " "after 'self' argument (should take '_cmd')", - iter->getName().str().c_str()); + iter->getName()); return false; } @@ -1905,15 +1727,14 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { } if (!argument->getName().equals("$__lldb_arg")) { - m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes an " - "argument named '%s' instead of the struct pointer", - argument->getName().str().c_str()); + m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an " + "argument named '{0}' instead of the struct pointer", + argument->getName()); return false; } - if (log) - log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); + LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument)); BasicBlock &entry_block(llvm_function.getEntryBlock()); Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); @@ -1950,13 +1771,11 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { return false; } - if (log) - log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, name.GetCString(), - decl->getNameAsString().c_str(), offset); + LLDB_LOG(log, " \"{0}\" (\"{1}\") placed at {2}", name, + decl->getNameAsString(), offset); if (value) { - if (log) - log->Printf(" Replacing [%s]", PrintValue(value).c_str()); + LLDB_LOG(log, " Replacing [{0}]", PrintValue(value)); FunctionValueCache body_result_maker( [this, name, offset_type, offset, argument, @@ -2005,9 +1824,8 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { value->replaceAllUsesWith( body_result_maker.GetValue(instruction->getParent()->getParent())); } else { - if (log) - log->Printf("Unhandled non-constant type: \"%s\"", - PrintValue(value).c_str()); + LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"", + PrintValue(value)); return false; } @@ -2016,35 +1834,12 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { } } - if (log) - log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", - (int64_t)alignment, (uint64_t)size); + LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment, + (uint64_t)size); return true; } -llvm::Constant *IRForTarget::BuildRelocation(llvm::Type *type, - uint64_t offset) { - llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); - - llvm::Constant *offset_array[1]; - - offset_array[0] = offset_int; - - llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1); - llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); - llvm::Type *char_pointer_type = char_type->getPointerTo(); - - llvm::Constant *reloc_placeholder_bitcast = - ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); - llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr( - char_type, reloc_placeholder_bitcast, offsets); - llvm::Constant *reloc_bitcast = - ConstantExpr::getBitCast(reloc_getelementptr, type); - - return reloc_bitcast; -} - bool IRForTarget::runOnModule(Module &llvm_module) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -2062,7 +1857,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { oss.flush(); - log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); + LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s); } Function *const main_function = @@ -2070,21 +1865,18 @@ bool IRForTarget::runOnModule(Module &llvm_module) { : m_module->getFunction(m_func_name.GetStringRef()); if (!m_func_name.IsEmpty() && !main_function) { - if (log) - log->Printf("Couldn't find \"%s()\" in the module", - m_func_name.AsCString()); + LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name); - m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find wrapper " - "'%s' in the module", - m_func_name.AsCString()); + m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper " + "'{0}' in the module", + m_func_name); return false; } if (main_function) { if (!FixFunctionLinkage(*main_function)) { - if (log) - log->Printf("Couldn't fix the linkage for the function"); + LLDB_LOG(log, "Couldn't fix the linkage for the function"); return false; } @@ -2104,8 +1896,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { if (main_function) { if (!CreateResultVariable(*main_function)) { - if (log) - log->Printf("CreateResultVariable() failed"); + LLDB_LOG(log, "CreateResultVariable() failed"); // CreateResultVariable() reports its own errors, so we don't do so here @@ -2121,32 +1912,21 @@ bool IRForTarget::runOnModule(Module &llvm_module) { oss.flush(); - log->Printf("Module after creating the result variable: \n\"%s\"", - s.c_str()); + LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s); } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; - ++fi) { - llvm::Function *function = &*fi; - - if (function->begin() == function->end()) - continue; - - Function::iterator bbi; - - for (bbi = function->begin(); bbi != function->end(); ++bbi) { - if (!RemoveGuards(*bbi)) { - if (log) - log->Printf("RemoveGuards() failed"); + for (llvm::Function &function : *m_module) { + for (BasicBlock &bb : function) { + if (!RemoveGuards(bb)) { + LLDB_LOG(log, "RemoveGuards() failed"); // RemoveGuards() reports its own errors, so we don't do so here return false; } - if (!RewritePersistentAllocs(*bbi)) { - if (log) - log->Printf("RewritePersistentAllocs() failed"); + if (!RewritePersistentAllocs(bb)) { + LLDB_LOG(log, "RewritePersistentAllocs() failed"); // RewritePersistentAllocs() reports its own errors, so we don't do so // here @@ -2154,9 +1934,8 @@ bool IRForTarget::runOnModule(Module &llvm_module) { return false; } - if (!RemoveCXAAtExit(*bbi)) { - if (log) - log->Printf("RemoveCXAAtExit() failed"); + if (!RemoveCXAAtExit(bb)) { + LLDB_LOG(log, "RemoveCXAAtExit() failed"); // RemoveCXAAtExit() reports its own errors, so we don't do so here @@ -2170,24 +1949,17 @@ bool IRForTarget::runOnModule(Module &llvm_module) { // if (!RewriteObjCConstStrings()) { - if (log) - log->Printf("RewriteObjCConstStrings() failed"); + LLDB_LOG(log, "RewriteObjCConstStrings() failed"); // RewriteObjCConstStrings() reports its own errors, so we don't do so here return false; } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; - ++fi) { - llvm::Function *function = &*fi; - - for (llvm::Function::iterator bbi = function->begin(), - bbe = function->end(); - bbi != bbe; ++bbi) { - if (!RewriteObjCSelectors(*bbi)) { - if (log) - log->Printf("RewriteObjCSelectors() failed"); + for (llvm::Function &function : *m_module) { + for (llvm::BasicBlock &bb : function) { + if (!RewriteObjCSelectors(bb)) { + LLDB_LOG(log, "RewriteObjCSelectors() failed"); // RewriteObjCSelectors() reports its own errors, so we don't do so // here @@ -2195,9 +1967,8 @@ bool IRForTarget::runOnModule(Module &llvm_module) { return false; } - if (!RewriteObjCClassReferences(*bbi)) { - if (log) - log->Printf("RewriteObjCClassReferences() failed"); + if (!RewriteObjCClassReferences(bb)) { + LLDB_LOG(log, "RewriteObjCClassReferences() failed"); // RewriteObjCClasses() reports its own errors, so we don't do so here @@ -2206,16 +1977,10 @@ bool IRForTarget::runOnModule(Module &llvm_module) { } } - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); fi != fe; - ++fi) { - llvm::Function *function = &*fi; - - for (llvm::Function::iterator bbi = function->begin(), - bbe = function->end(); - bbi != bbe; ++bbi) { - if (!ResolveCalls(*bbi)) { - if (log) - log->Printf("ResolveCalls() failed"); + for (llvm::Function &function : *m_module) { + for (BasicBlock &bb : function) { + if (!ResolveCalls(bb)) { + LLDB_LOG(log, "ResolveCalls() failed"); // ResolveCalls() reports its own errors, so we don't do so here @@ -2230,8 +1995,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { if (main_function) { if (!ResolveExternals(*main_function)) { - if (log) - log->Printf("ResolveExternals() failed"); + LLDB_LOG(log, "ResolveExternals() failed"); // ResolveExternals() reports its own errors, so we don't do so here @@ -2239,8 +2003,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { } if (!ReplaceVariables(*main_function)) { - if (log) - log->Printf("ReplaceVariables() failed"); + LLDB_LOG(log, "ReplaceVariables() failed"); // ReplaceVariables() reports its own errors, so we don't do so here @@ -2256,7 +2019,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { oss.flush(); - log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); + LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s); } return true; diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h index f87fd8ac32cb..893620f7f8e0 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -10,6 +10,7 @@ #ifndef liblldb_IRForTarget_h_ #define liblldb_IRForTarget_h_ +#include "lldb/Core/ClangForward.h" #include "lldb/Symbol/TaggedASTType.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" @@ -331,27 +332,6 @@ private: /// a call to a function pointer whose value is the address of the function /// in the target process. - /// Write an initializer to a memory array of assumed sufficient size. - /// - /// \param[in] data - /// A pointer to the data to write to. - /// - /// \param[in] initializer - /// The initializer itself. - /// - /// \return - /// True on success; false otherwise - bool MaterializeInitializer(uint8_t *data, llvm::Constant *initializer); - - /// Move an internal variable into the static allocation section. - /// - /// \param[in] global_variable - /// The variable. - /// - /// \return - /// True on success; false otherwise - bool MaterializeInternalVariable(llvm::GlobalVariable *global_variable); - /// Handle a single externally-defined variable /// /// \param[in] value @@ -539,20 +519,6 @@ private: FunctionValueCache &entry_instruction_finder, lldb_private::Stream &error_stream); - /// Construct a reference to m_reloc_placeholder with a given type and - /// offset. This typically happens after inserting data into - /// m_data_allocator. - /// - /// \param[in] type - /// The type of the value being loaded. - /// - /// \param[in] offset - /// The offset of the value from the base of m_data_allocator. - /// - /// \return - /// The Constant for the reference, usually a ConstantExpr. - llvm::Constant *BuildRelocation(llvm::Type *type, uint64_t offset); - /// Commit the allocation in m_data_allocator and use its final location to /// replace m_reloc_placeholder. /// diff --git a/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h b/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h index 0e959f86fd2a..7553860f2492 100644 --- a/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h +++ b/source/Plugins/ExpressionParser/Clang/ModuleDependencyCollector.h @@ -9,21 +9,23 @@ #ifndef liblldb_ModuleDependencyCollector_h_ #define liblldb_ModuleDependencyCollector_h_ -#include "lldb/Utility/FileCollector.h" #include "clang/Frontend/Utils.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileCollector.h" namespace lldb_private { class ModuleDependencyCollectorAdaptor : public clang::ModuleDependencyCollector { public: - ModuleDependencyCollectorAdaptor(FileCollector &file_collector) + ModuleDependencyCollectorAdaptor( + std::shared_ptr<llvm::FileCollector> file_collector) : clang::ModuleDependencyCollector(""), m_file_collector(file_collector) { } void addFile(llvm::StringRef Filename, llvm::StringRef FileDst = {}) override { - m_file_collector.AddFile(Filename); + if (m_file_collector) + m_file_collector->addFile(Filename); } bool insertSeen(llvm::StringRef Filename) override { return false; } @@ -31,7 +33,7 @@ public: void writeFileMap() override {} private: - FileCollector &m_file_collector; + std::shared_ptr<llvm::FileCollector> m_file_collector; }; } // namespace lldb_private diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 6323889c2e09..19a987b0f004 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -14507,6 +14507,7 @@ bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { unwind_plan.SetSourceName("EmulateInstructionARM"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index d7e8e0491342..3e06fca2504c 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -149,7 +149,8 @@ EmulateInstructionARM64::CreateInstance(const ArchSpec &arch, InstructionType inst_type) { if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic( inst_type)) { - if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { + if (arch.GetTriple().getArch() == llvm::Triple::aarch64 || + arch.GetTriple().getArch() == llvm::Triple::aarch64_32) { return new EmulateInstructionARM64(arch); } } @@ -479,6 +480,7 @@ bool EmulateInstructionARM64::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionARM64"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(gpr_lr_arm64); return true; } diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index cbf3dda7896e..21b6296745bd 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -1150,6 +1150,7 @@ bool EmulateInstructionMIPS::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionMIPS"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_ra_mips); return true; diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 69f0278d1437..5fabbeb756cc 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -1042,6 +1042,7 @@ bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionMIPS64"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64); return true; diff --git a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp index c77fa04fc7d7..4b8d8dd2228c 100644 --- a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp +++ b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp @@ -135,6 +135,7 @@ bool EmulateInstructionPPC64::CreateFunctionEntryUnwind( unwind_plan.SetSourceName("EmulateInstructionPPC64"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le); return true; } diff --git a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp index c8ac04641e68..2e5dd5989e77 100644 --- a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp @@ -264,7 +264,7 @@ bool AddressSanitizerRuntime::NotifyBreakpointHit( *thread_sp, description, report)); StreamFileSP stream_sp( - process_sp->GetTarget().GetDebugger().GetOutputFile()); + process_sp->GetTarget().GetDebugger().GetOutputStreamSP()); if (stream_sp) { stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread " "info -s' to get extended information about the " diff --git a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp index 89f2139db71b..45a3aeeb204e 100644 --- a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp @@ -863,13 +863,11 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit( CreateStopReasonWithInstrumentationData( *thread_sp, stop_reason_description, report)); - StreamFileSP stream_sp( - process_sp->GetTarget().GetDebugger().GetOutputFile()); - if (stream_sp) { - stream_sp->Printf("ThreadSanitizer report breakpoint hit. Use 'thread " - "info -s' to get extended information about the " - "report.\n"); - } + StreamFile &s = process_sp->GetTarget().GetDebugger().GetOutputStream(); + s.Printf("ThreadSanitizer report breakpoint hit. Use 'thread " + "info -s' to get extended information about the " + "report.\n"); + return true; // Return true to stop the target } else return false; // Let target run diff --git a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp index 367098bb448e..50f1d48d03e0 100644 --- a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp @@ -124,7 +124,7 @@ StructuredData::ObjectSP UndefinedBehaviorSanitizerRuntime::RetrieveReportData( if (!frame_sp) return StructuredData::ObjectSP(); - StreamFileSP Stream(target.GetDebugger().GetOutputFile()); + StreamFileSP Stream = target.GetDebugger().GetOutputStreamSP(); EvaluateExpressionOptions options; options.SetUnwindOnError(true); diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 140d09ed43cf..fff44123539f 100644 --- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// - -#include "llvm/Support/MathExtras.h" - +#include "JITLoaderGDB.h" +#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -26,8 +25,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" - -#include "JITLoaderGDB.h" +#include "llvm/Support/MathExtras.h" #include <memory> @@ -59,21 +57,33 @@ enum EnableJITLoaderGDB { eEnableJITLoaderGDBOff, }; -static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] = { - {eEnableJITLoaderGDBDefault, "default", "Enable JIT compilation interface " - "for all platforms except macOS"}, - {eEnableJITLoaderGDBOn, "on", "Enable JIT compilation interface"}, - {eEnableJITLoaderGDBOff, "off", "Disable JIT compilation interface"} - }; +static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] = + { + { + eEnableJITLoaderGDBDefault, + "default", + "Enable JIT compilation interface for all platforms except macOS", + }, + { + eEnableJITLoaderGDBOn, + "on", + "Enable JIT compilation interface", + }, + { + eEnableJITLoaderGDBOff, + "off", + "Disable JIT compilation interface", + }, +}; -static constexpr PropertyDefinition g_properties[] = { - {"enable", OptionValue::eTypeEnum, true, - eEnableJITLoaderGDBDefault, nullptr, - OptionEnumValues(g_enable_jit_loader_gdb_enumerators), - "Enable GDB's JIT compilation interface (default: enabled on " - "all platforms except macOS)"}}; +#define LLDB_PROPERTIES_jitloadergdb +#include "JITLoaderGDBProperties.inc" -enum { ePropertyEnable, ePropertyEnableJITBreakpoint }; +enum { +#define LLDB_PROPERTIES_jitloadergdb +#include "JITLoaderGDBPropertiesEnum.inc" + ePropertyEnableJITBreakpoint +}; class PluginProperties : public Properties { public: @@ -83,13 +93,13 @@ public: PluginProperties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_jitloadergdb_properties); } EnableJITLoaderGDB GetEnable() const { return (EnableJITLoaderGDB)m_collection_sp->GetPropertyAtIndexAsEnumeration( nullptr, ePropertyEnable, - g_properties[ePropertyEnable].default_uint_value); + g_jitloadergdb_properties[ePropertyEnable].default_uint_value); } }; @@ -177,8 +187,8 @@ void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { return; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER)); - if (log) - log->Printf("JITLoaderGDB::%s looking for JIT register hook", __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s looking for JIT register hook", + __FUNCTION__); addr_t jit_addr = GetSymbolAddress( module_list, ConstString("__jit_debug_register_code"), eSymbolTypeAny); @@ -188,14 +198,12 @@ void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { m_jit_descriptor_addr = GetSymbolAddress( module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData); if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("JITLoaderGDB::%s failed to find JIT descriptor address", - __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s failed to find JIT descriptor address", + __FUNCTION__); return; } - if (log) - log->Printf("JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__); Breakpoint *bp = m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get(); @@ -211,8 +219,7 @@ bool JITLoaderGDB::JITDebugBreakpointHit(void *baton, user_id_t break_id, user_id_t break_loc_id) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER)); - if (log) - log->Printf("JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__); JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton); return instance->ReadJITDescriptor(false); } @@ -285,9 +292,8 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { size_t bytes_read = m_process->DoReadMemory(m_jit_descriptor_addr, &jit_desc, jit_desc_size, error); if (bytes_read != jit_desc_size || !error.Success()) { - if (log) - log->Printf("JITLoaderGDB::%s failed to read JIT descriptor", - __FUNCTION__); + LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT descriptor", + __FUNCTION__); return false; } @@ -301,9 +307,8 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { while (jit_relevant_entry != 0) { jit_code_entry<ptr_t> jit_entry; if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) { - if (log) - log->Printf("JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64, - __FUNCTION__, jit_relevant_entry); + LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64, + __FUNCTION__, jit_relevant_entry); return false; } @@ -312,10 +317,10 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { ModuleSP module_sp; if (jit_action == JIT_REGISTER_FN) { - if (log) - log->Printf("JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64 - " (%" PRIu64 " bytes)", - __FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size); + LLDB_LOGF(log, + "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64 + " (%" PRIu64 " bytes)", + __FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size); char jit_name[64]; snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr); @@ -331,20 +336,16 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { module_sp->GetObjectFile()->GetSymtab(); m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp)); - if (module_sp->GetObjectFile()->GetPluginName() == - ConstString("mach-o")) { - ObjectFile *image_object_file = module_sp->GetObjectFile(); - if (image_object_file) { - const SectionList *section_list = - image_object_file->GetSectionList(); - if (section_list) { - uint64_t vmaddrheuristic = 0; - uint64_t lower = (uint64_t)-1; - uint64_t upper = 0; - updateSectionLoadAddress(*section_list, target, symbolfile_addr, - symbolfile_size, vmaddrheuristic, lower, - upper); - } + if (auto image_object_file = + llvm::dyn_cast<ObjectFileMachO>(module_sp->GetObjectFile())) { + const SectionList *section_list = image_object_file->GetSectionList(); + if (section_list) { + uint64_t vmaddrheuristic = 0; + uint64_t lower = (uint64_t)-1; + uint64_t upper = 0; + updateSectionLoadAddress(*section_list, target, symbolfile_addr, + symbolfile_size, vmaddrheuristic, lower, + upper); } } else { bool changed = false; @@ -357,15 +358,14 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { module_list.Append(module_sp); target.ModulesDidLoad(module_list); } else { - if (log) - log->Printf("JITLoaderGDB::%s failed to load module for " - "JIT entry at 0x%" PRIx64, - __FUNCTION__, symbolfile_addr); + LLDB_LOGF(log, + "JITLoaderGDB::%s failed to load module for " + "JIT entry at 0x%" PRIx64, + __FUNCTION__, symbolfile_addr); } } else if (jit_action == JIT_UNREGISTER_FN) { - if (log) - log->Printf("JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64, - __FUNCTION__, symbolfile_addr); + LLDB_LOGF(log, "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64, + __FUNCTION__, symbolfile_addr); JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr); if (it != m_jit_objects.end()) { @@ -458,8 +458,8 @@ addr_t JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, SymbolContextList target_symbols; Target &target = m_process->GetTarget(); - if (!module_list.FindSymbolsWithNameAndType(name, symbol_type, - target_symbols)) + module_list.FindSymbolsWithNameAndType(name, symbol_type, target_symbols); + if (target_symbols.IsEmpty()) return LLDB_INVALID_ADDRESS; SymbolContext sym_ctx; diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDBProperties.td b/source/Plugins/JITLoader/GDB/JITLoaderGDBProperties.td new file mode 100644 index 000000000000..0493838bc85d --- /dev/null +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDBProperties.td @@ -0,0 +1,9 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "jitloadergdb" in { + def Enable: Property<"enable", "Enum">, + Global, + DefaultEnumValue<"eEnableJITLoaderGDBDefault">, + EnumValues<"OptionEnumValues(g_enable_jit_loader_gdb_enumerators)">, + Desc<"Enable GDB's JIT compilation interface (default: enabled on all platforms except macOS)">; +} diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index 87b5b5947f35..5cfd978774fd 100644 --- a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -17,6 +17,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" using namespace lldb; using namespace lldb_private; @@ -39,16 +40,17 @@ public: return; } - Status err; - TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage( - &err, lldb::eLanguageTypeC_plus_plus); - - if (!err.Success() || !type_system) { + auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage( + lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS), + std::move(err), "Failed to get scratch ClangASTContext"); return; } ClangASTContext *clang_ast_context = - llvm::dyn_cast<ClangASTContext>(type_system); + llvm::dyn_cast<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_context) { return; diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 44b9e5e24ccd..489fa7d0ad91 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -486,8 +486,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", - ConstString("^std::__[[:alnum:]]+::list<.+>(( )?&)?$"), stl_deref_flags, - true); + // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" + // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" + ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" + "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), + stl_deref_flags, true); AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, @@ -547,8 +550,8 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^std::__[[:alnum:]]+::atomic<.+>$"), stl_synth_flags, true); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$"))), + RegularExpression( + llvm::StringRef("^(std::__[[:alnum:]]+::)deque<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.libcxx.stddeque_SynthProvider"))); @@ -566,12 +569,6 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true); - AddCXXSummary( - cpp_category_sp, lldb_private::formatters::LibcxxFunctionSummaryProvider, - "libc++ std::function summary provider", - ConstString("^std::__[[:alnum:]]+::function<.+>$"), stl_summary_flags, - true); - stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(false); AddCXXSummary(cpp_category_sp, @@ -589,11 +586,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::list summary provider", ConstString("^std::__[[:alnum:]]+::forward_list<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(cpp_category_sp, - lldb_private::formatters::LibcxxContainerSummaryProvider, - "libc++ std::list summary provider", - ConstString("^std::__[[:alnum:]]+::list<.+>(( )?&)?$"), - stl_summary_flags, true); + AddCXXSummary( + cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::list summary provider", + // A POSIX variant of: "^std::__(?!cxx11:)[[:alnum:]]+::list<.+>(( )?&)?$" + // so that it does not clash with: "^std::(__cxx11::)?list<.+>(( )?&)?$" + ConstString("^std::__([A-Zabd-z0-9]|cx?[A-Za-wyz0-9]|cxx1?[A-Za-z02-9]|" + "cxx11[[:alnum:]])[[:alnum:]]*::list<.+>(( )?&)?$"), + stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", @@ -750,38 +750,32 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { false); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider"))); cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$")), SyntheticChildrenSP(new ScriptedSyntheticChildren( stl_synth_flags, "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); stl_summary_flags.SetDontShowChildren(false); stl_summary_flags.SetSkipPointers(true); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::vector<.+>(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP( - new RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::map<.+> >(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); cpp_category_sp->GetRegexTypeSummariesContainer()->Add( - RegularExpressionSP(new RegularExpression( - llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$"))), + RegularExpression(llvm::StringRef("^std::(__cxx11::)?list<.+>(( )?&)?$")), TypeSummaryImplSP( new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); @@ -860,6 +854,14 @@ static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { // FIXME because of a bug in the FormattersContainer we need to add a summary // for both X* and const X* (<rdar://problem/12717717>) AddCXXSummary( + cpp_category_sp, lldb_private::formatters::Char8StringSummaryProvider, + "char8_t * summary provider", ConstString("char8_t *"), string_flags); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::Char8StringSummaryProvider, + "char8_t [] summary provider", + ConstString("char8_t \\[[0-9]+\\]"), string_array_flags, true); + + AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags); AddCXXSummary(cpp_category_sp, @@ -896,6 +898,9 @@ static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { .SetHideItemNames(true) .SetShowMembersOneLiner(false); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char8SummaryProvider, + "char8_t summary provider", ConstString("char8_t"), + widechar_flags); AddCXXSummary( cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags); diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp index 959079070acc..3ea7589d8e4a 100644 --- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -32,6 +32,31 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +bool lldb_private::formatters::Char8StringSummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + return false; + + lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); + if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) + return false; + + StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(valobj_addr); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + + if (!StringPrinter::ReadStringAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options)) { + stream.Printf("Summary Unavailable"); + return true; + } + + return true; +} + bool lldb_private::formatters::Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { ProcessSP process_sp = valobj.GetProcessSP(); @@ -128,6 +153,32 @@ bool lldb_private::formatters::WCharStringSummaryProvider( return true; } +bool lldb_private::formatters::Char8SummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { + DataExtractor data; + Status error; + valobj.GetData(data, error); + + if (error.Fail()) + return false; + + std::string value; + valobj.GetValueAsCString(lldb::eFormatUnicode8, value); + if (!value.empty()) + stream.Printf("%s ", value.c_str()); + + StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); + options.SetData(data); + options.SetStream(&stream); + options.SetPrefixToken("u8"); + options.SetQuote('\''); + options.SetSourceSize(1); + options.SetBinaryZeroIsTerminator(false); + + return StringPrinter::ReadBufferAndDumpToStream< + StringPrinter::StringElementType::UTF8>(options); +} + bool lldb_private::formatters::Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) { DataExtractor data; diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h index 92bef2382eac..35498b3b568f 100644 --- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h @@ -16,6 +16,9 @@ namespace lldb_private { namespace formatters { +bool Char8StringSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t* + bool Char16StringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t* and unichar* @@ -27,6 +30,9 @@ bool Char32StringSummaryProvider( bool WCharStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // wchar_t* +bool Char8SummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // char8_t + bool Char16SummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // char16_t and unichar diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp index 815dafb6c724..78c453cd1b3c 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp @@ -30,8 +30,15 @@ public: ValueObjectSP GetChildAtIndex(size_t idx) override; private: + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + // Value objects created from raw data (i.e. in a different cluster) must + // be referenced via shared pointer to keep them alive, however. std::vector<ValueObjectSP> m_elements; - ValueObjectSP m_first; + ValueObject* m_first = nullptr; CompilerType m_bool_type; ByteOrder m_byte_order = eByteOrderInvalid; uint8_t m_byte_size = 0; @@ -50,7 +57,7 @@ BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) bool BitsetFrontEnd::Update() { m_elements.clear(); - m_first.reset(); + m_first = nullptr; TargetSP target_sp = m_backend.GetTargetSP(); if (!target_sp) @@ -63,7 +70,7 @@ bool BitsetFrontEnd::Update() { m_elements.assign(size, ValueObjectSP()); - m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true); + m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true).get(); return false; } @@ -86,7 +93,7 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { chunk = m_first->GetChildAtIndex(idx / *bit_size, true); } else { type = m_first->GetCompilerType(); - chunk = m_first; + chunk = m_first->GetSP(); } if (!type || !chunk) return {}; diff --git a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp index 116021588848..b1ad171d0b0c 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp @@ -31,7 +31,6 @@ public: private: size_t m_size = 0; - ValueObjectSP m_base_sp; }; } // namespace diff --git a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp index 4b72089c6ba2..2f06d684f953 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp @@ -38,16 +38,21 @@ public: } private: - ValueObjectSP m_container_sp; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + ValueObject* m_container_sp = nullptr; }; } // namespace bool QueueFrontEnd::Update() { - m_container_sp.reset(); + m_container_sp = nullptr; ValueObjectSP c_sp = m_backend.GetChildMemberWithName(ConstString("c"), true); if (!c_sp) return false; - m_container_sp = c_sp->GetSyntheticValue(); + m_container_sp = c_sp->GetSyntheticValue().get(); return false; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp index 8da7460f2275..45294e25f0f5 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp @@ -30,47 +30,58 @@ public: ValueObjectSP GetChildAtIndex(size_t idx) override; private: - std::vector<ValueObjectSP> m_elements; - ValueObjectSP m_base_sp; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + std::vector<ValueObject*> m_elements; + ValueObject* m_base = nullptr; }; } bool TupleFrontEnd::Update() { m_elements.clear(); - m_base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); - if (! m_base_sp) { + m_base = nullptr; + + ValueObjectSP base_sp; + base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); + if (!base_sp) { // Pre r304382 name of the base element. - m_base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); + base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); } - if (! m_base_sp) + if (!base_sp) return false; - m_elements.assign(m_base_sp->GetCompilerType().GetNumDirectBaseClasses(), - ValueObjectSP()); + m_base = base_sp.get(); + m_elements.assign(base_sp->GetCompilerType().GetNumDirectBaseClasses(), + nullptr); return false; } ValueObjectSP TupleFrontEnd::GetChildAtIndex(size_t idx) { if (idx >= m_elements.size()) return ValueObjectSP(); - if (!m_base_sp) + if (!m_base) return ValueObjectSP(); if (m_elements[idx]) - return m_elements[idx]; + return m_elements[idx]->GetSP(); CompilerType holder_type = - m_base_sp->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); + m_base->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); if (!holder_type) return ValueObjectSP(); - ValueObjectSP holder_sp = m_base_sp->GetChildAtIndex(idx, true); + ValueObjectSP holder_sp = m_base->GetChildAtIndex(idx, true); if (!holder_sp) return ValueObjectSP(); ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0, true); if (elem_sp) m_elements[idx] = - elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())); + elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())).get(); - return m_elements[idx]; + if (m_elements[idx]) + return m_elements[idx]->GetSP(); + return ValueObjectSP(); } SyntheticChildrenFrontEnd * diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp index 491cf048e459..62945bd3ce80 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp @@ -184,7 +184,6 @@ public: private: size_t m_size = 0; - ValueObjectSP m_base_sp; }; } // namespace diff --git a/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp b/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp index 66624e5beb6d..0ac7b8f8e02b 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp @@ -37,7 +37,12 @@ public: size_t GetIndexOfChildWithName(ConstString name) override; private: - std::vector<ValueObjectSP> m_members; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + std::vector<ValueObject*> m_members; }; } // end of anonymous namespace @@ -72,7 +77,7 @@ bool LibStdcppTupleSyntheticFrontEnd::Update() { if (value_sp) { StreamString name; name.Printf("[%zd]", m_members.size()); - m_members.push_back(value_sp->Clone(ConstString(name.GetString()))); + m_members.push_back(value_sp->Clone(ConstString(name.GetString())).get()); } } } @@ -85,8 +90,8 @@ bool LibStdcppTupleSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP LibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(size_t idx) { - if (idx < m_members.size()) - return m_members[idx]; + if (idx < m_members.size() && m_members[idx]) + return m_members[idx]->GetSP(); return lldb::ValueObjectSP(); } diff --git a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp index 3860f960cb3d..cceb511cdc46 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp @@ -39,9 +39,14 @@ public: bool GetSummary(Stream &stream, const TypeSummaryOptions &options); private: - ValueObjectSP m_ptr_obj; - ValueObjectSP m_obj_obj; - ValueObjectSP m_del_obj; + // The lifetime of a ValueObject and all its derivative ValueObjects + // (children, clones, etc.) is managed by a ClusterManager. These + // objects are only destroyed when every shared pointer to any of them + // is destroyed, so we must not store a shared pointer to any ValueObject + // derived from our backend ValueObject (since we're in the same cluster). + ValueObject* m_ptr_obj = nullptr; + ValueObject* m_obj_obj = nullptr; + ValueObject* m_del_obj = nullptr; ValueObjectSP GetTuple(); }; @@ -92,17 +97,17 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); if (ptr_obj) - m_ptr_obj = ptr_obj->Clone(ConstString("pointer")); + 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")); + m_del_obj = del_obj->Clone(ConstString("deleter")).get(); if (m_ptr_obj) { Status error; ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); if (error.Success()) { - m_obj_obj = obj_obj->Clone(ConstString("object")); + m_obj_obj = obj_obj->Clone(ConstString("object")).get(); } } @@ -113,12 +118,12 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { - if (idx == 0) - return m_ptr_obj; - if (idx == 1) - return m_del_obj; - if (idx == 2) - return m_obj_obj; + if (idx == 0 && m_ptr_obj) + return m_ptr_obj->GetSP(); + if (idx == 1 && m_del_obj) + return m_del_obj->GetSP(); + if (idx == 2 && m_obj_obj) + return m_obj_obj->GetSP(); return lldb::ValueObjectSP(); } diff --git a/source/Plugins/Language/ObjC/CoreMedia.cpp b/source/Plugins/Language/ObjC/CoreMedia.cpp index d19290ec56fb..247429da1b06 100644 --- a/source/Plugins/Language/ObjC/CoreMedia.cpp +++ b/source/Plugins/Language/ObjC/CoreMedia.cpp @@ -10,6 +10,7 @@ #include "CoreMedia.h" #include "lldb/Utility/Flags.h" +#include "lldb/Utility/Log.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Target.h" @@ -25,18 +26,21 @@ bool lldb_private::formatters::CMTimeSummaryProvider( if (!type.IsValid()) return false; - TypeSystem *type_system = + auto type_system_or_err = valobj.GetExecutionContextRef() .GetTargetSP() - ->GetScratchTypeSystemForLanguage(nullptr, lldb::eLanguageTypeC); - if (!type_system) + ->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS), + std::move(err), "Failed to get scratch type system"); return false; - + } // fetch children by offset to compensate for potential lack of debug info - auto int64_ty = - type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64); - auto int32_ty = - type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32); + auto int64_ty = type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( + eEncodingSint, 64); + auto int32_ty = type_system_or_err->GetBuiltinTypeForEncodingAndBitSize( + eEncodingSint, 32); auto value_sp(valobj.GetSyntheticChildAtOffset(0, int64_ty, true)); auto timescale_sp(valobj.GetSyntheticChildAtOffset(8, int32_ty, true)); diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp index 404dabf2870c..7219c016dfd1 100644 --- a/source/Plugins/Language/ObjC/NSArray.cpp +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -461,12 +461,13 @@ lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontE : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_id_type() { if (valobj_sp) { - clang::ASTContext *ast = valobj_sp->GetExecutionContextRef() - .GetTargetSP() - ->GetScratchClangASTContext() - ->getASTContext(); - if (ast) - m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy); + auto *clang_ast_context = valobj_sp->GetExecutionContextRef() + .GetTargetSP() + ->GetScratchClangASTContext(); + if (clang_ast_context) + m_id_type = CompilerType( + clang_ast_context, + clang_ast_context->getASTContext()->ObjCBuiltinIdTy.getAsOpaquePtr()); if (valobj_sp->GetProcessSP()) m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); } @@ -609,12 +610,13 @@ lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: if (valobj_sp) { CompilerType type = valobj_sp->GetCompilerType(); if (type) { - ClangASTContext *ast = valobj_sp->GetExecutionContextRef() - .GetTargetSP() - ->GetScratchClangASTContext(); - if (ast) - m_id_type = CompilerType(ast->getASTContext(), - ast->getASTContext()->ObjCBuiltinIdTy); + auto *clang_ast_context = valobj_sp->GetExecutionContextRef() + .GetTargetSP() + ->GetScratchClangASTContext(); + if (clang_ast_context) + m_id_type = CompilerType(clang_ast_context, + clang_ast_context->getASTContext() + ->ObjCBuiltinIdTy.getAsOpaquePtr()); } } } diff --git a/source/Plugins/Language/ObjC/NSDictionary.h b/source/Plugins/Language/ObjC/NSDictionary.h index ecb3fccdf877..44d56f9c2c68 100644 --- a/source/Plugins/Language/ObjC/NSDictionary.h +++ b/source/Plugins/Language/ObjC/NSDictionary.h @@ -68,10 +68,10 @@ public: }; typedef Matcher::UP MatcherUP; - MatcherUP GetFullMatch(ConstString n) { return llvm::make_unique<Full>(n); } + MatcherUP GetFullMatch(ConstString n) { return std::make_unique<Full>(n); } MatcherUP GetPrefixMatch(ConstString p) { - return llvm::make_unique<Prefix>(p); + return std::make_unique<Prefix>(p); } }; diff --git a/source/Plugins/Language/ObjC/NSString.cpp b/source/Plugins/Language/ObjC/NSString.cpp index 4800c955e5f5..55e129b098dc 100644 --- a/source/Plugins/Language/ObjC/NSString.cpp +++ b/source/Plugins/Language/ObjC/NSString.cpp @@ -78,12 +78,12 @@ bool lldb_private::formatters::NSStringSummaryProvider( return false; ConstString class_name_cs = descriptor->GetClassName(); - const char *class_name = class_name_cs.GetCString(); + llvm::StringRef class_name = class_name_cs.GetStringRef(); - if (!class_name || !*class_name) + if (class_name.empty()) return false; - bool is_tagged_ptr = (0 == strcmp(class_name, "NSTaggedPointerString")) && + bool is_tagged_ptr = class_name == "NSTaggedPointerString" && descriptor->GetTaggedPointerInfo(); // for a tagged pointer, the descriptor has everything we need if (is_tagged_ptr) @@ -111,7 +111,7 @@ bool lldb_private::formatters::NSStringSummaryProvider( bool is_inline = (info_bits & 0x60) == 0; bool has_explicit_length = (info_bits & (1 | 4)) != 4; bool is_unicode = (info_bits & 0x10) == 0x10; - bool is_path_store = strcmp(class_name, "NSPathStore2") == 0; + bool is_path_store = class_name == "NSPathStore2"; bool has_null = (info_bits & 8) == 8; size_t explicit_length = 0; @@ -135,14 +135,14 @@ bool lldb_private::formatters::NSStringSummaryProvider( } } - if (strcmp(class_name, "NSString") && strcmp(class_name, "CFStringRef") && - strcmp(class_name, "CFMutableStringRef") && - strcmp(class_name, "__NSCFConstantString") && - strcmp(class_name, "__NSCFString") && - strcmp(class_name, "NSCFConstantString") && - strcmp(class_name, "NSCFString") && strcmp(class_name, "NSPathStore2")) { + const llvm::StringSet<> supported_string_classes = { + "NSString", "CFMutableStringRef", + "CFStringRef", "__NSCFConstantString", + "__NSCFString", "NSCFConstantString", + "NSCFString", "NSPathStore2"}; + if (supported_string_classes.count(class_name) == 0) { // not one of us - but tell me class name - stream.Printf("class name = %s", class_name); + stream.Printf("class name = %s", class_name_cs.GetCString()); return true; } diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp index f9ab18688de7..c5bfb5747c13 100644 --- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/Threading.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" #include "CF.h" diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index b392282c3eb1..f38014505a8b 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -231,7 +231,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( SymbolContextList scl; target.GetImages().FindSymbolsMatchingRegExAndType( - RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl, true); + RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl); // Case 1,2 or 3 if (scl.GetSize() >= 1) { diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 41f38a4e3dcd..02e62a263286 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -79,11 +79,10 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( if (name && strstr(name, vtable_demangled_prefix) == name) { Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("0x%16.16" PRIx64 - ": static-type = '%s' has vtable symbol '%s'\n", - original_ptr, in_value.GetTypeName().GetCString(), - name); + LLDB_LOGF(log, + "0x%16.16" PRIx64 + ": static-type = '%s' has vtable symbol '%s'\n", + original_ptr, in_value.GetTypeName().GetCString(), name); // We are a C++ class, that's good. Get the class name and look it // up: const char *class_name = name + strlen(vtable_demangled_prefix); @@ -96,87 +95,81 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( const bool exact_match = true; TypeList class_types; - uint32_t num_matches = 0; // First look in the module that the vtable symbol came from and // look for a single exact match. llvm::DenseSet<SymbolFile *> searched_symbol_files; - if (sc.module_sp) { - num_matches = sc.module_sp->FindTypes( - ConstString(lookup_name), exact_match, 1, - searched_symbol_files, class_types); - } + if (sc.module_sp) + sc.module_sp->FindTypes(ConstString(lookup_name), exact_match, 1, + searched_symbol_files, class_types); // If we didn't find a symbol, then move on to the entire module // list in the target and get as many unique matches as possible - if (num_matches == 0) { - num_matches = target.GetImages().FindTypes( - nullptr, ConstString(lookup_name), exact_match, UINT32_MAX, - searched_symbol_files, class_types); - } + if (class_types.Empty()) + target.GetImages().FindTypes(nullptr, ConstString(lookup_name), + exact_match, UINT32_MAX, + searched_symbol_files, class_types); lldb::TypeSP type_sp; - if (num_matches == 0) { - if (log) - log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", - original_ptr); + if (class_types.Empty()) { + LLDB_LOGF(log, "0x%16.16" PRIx64 ": is not dynamic\n", + original_ptr); return TypeAndOrName(); } - if (num_matches == 1) { + if (class_types.GetSize() == 1) { type_sp = class_types.GetTypeAtIndex(0); if (type_sp) { if (ClangASTContext::IsCXXClassType( type_sp->GetForwardCompilerType())) { - if (log) - log->Printf( - "0x%16.16" PRIx64 - ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 - "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); + LLDB_LOGF( + log, + "0x%16.16" PRIx64 + ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 + "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); type_info.SetTypeSP(type_sp); } } - } else if (num_matches > 1) { + } else { size_t i; if (log) { - for (i = 0; i < num_matches; i++) { + for (i = 0; i < class_types.GetSize(); i++) { type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { - if (log) - log->Printf( - "0x%16.16" PRIx64 - ": static-type = '%s' has multiple matching dynamic " - "types: uid={0x%" PRIx64 "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); + LLDB_LOGF( + log, + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types: uid={0x%" PRIx64 "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); } } } - for (i = 0; i < num_matches; i++) { + for (i = 0; i < class_types.GetSize(); i++) { type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { if (ClangASTContext::IsCXXClassType( type_sp->GetForwardCompilerType())) { - if (log) - log->Printf( - "0x%16.16" PRIx64 ": static-type = '%s' has multiple " - "matching dynamic types, picking " - "this one: uid={0x%" PRIx64 - "}, type-name='%s'\n", - original_ptr, in_value.GetTypeName().AsCString(), - type_sp->GetID(), type_sp->GetName().GetCString()); + LLDB_LOGF( + log, + "0x%16.16" PRIx64 ": static-type = '%s' has multiple " + "matching dynamic types, picking " + "this one: uid={0x%" PRIx64 "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), + type_sp->GetID(), type_sp->GetName().GetCString()); type_info.SetTypeSP(type_sp); } } } - if (log && i == num_matches) { - log->Printf( - "0x%16.16" PRIx64 - ": static-type = '%s' has multiple matching dynamic " - "types, didn't find a C++ match\n", - original_ptr, in_value.GetTypeName().AsCString()); + if (log) { + LLDB_LOGF(log, + "0x%16.16" PRIx64 + ": static-type = '%s' has multiple matching dynamic " + "types, didn't find a C++ match\n", + original_ptr, in_value.GetTypeName().AsCString()); } } if (type_info) @@ -351,7 +344,7 @@ protected: bool demangled_any = false; bool error_any = false; for (auto &entry : command.entries()) { - if (entry.ref.empty()) + if (entry.ref().empty()) continue; // the actual Mangled class should be strict about this, but on the @@ -359,21 +352,21 @@ protected: // they will come out with an extra underscore - be willing to strip this // on behalf of the user. This is the moral equivalent of the -_/-n // options to c++filt - auto name = entry.ref; + auto name = entry.ref(); if (name.startswith("__Z")) name = name.drop_front(); - Mangled mangled(name, true); + Mangled mangled(name); if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus) { ConstString demangled( mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus)); demangled_any = true; - result.AppendMessageWithFormat("%s ---> %s\n", entry.ref.str().c_str(), + result.AppendMessageWithFormat("%s ---> %s\n", entry.c_str(), demangled.GetCString()); } else { error_any = true; result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n", - entry.ref.str().c_str()); + entry.ref().str().c_str()); } } @@ -471,8 +464,8 @@ lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() { if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) { // Limit the number of modules that are searched for these breakpoints for // Apple binaries. - filter_modules.Append(FileSpec("libc++abi.dylib")); - filter_modules.Append(FileSpec("libSystem.B.dylib")); + filter_modules.EmplaceBack("libc++abi.dylib"); + filter_modules.EmplaceBack("libSystem.B.dylib"); } return target.GetSearchFilterForModuleList(&filter_modules); } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 18f2a1829a41..1f27a4f0b3ed 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -38,12 +38,13 @@ public: LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? if (log) { - log->Printf("AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%" - "u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p", - current_id, - static_cast<void *>(&decl_ctx->getParentASTContext()), - name.getAsString().c_str(), decl_ctx->getDeclKindName(), - static_cast<const void *>(decl_ctx)); + LLDB_LOGF(log, + "AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%" + "u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p", + current_id, + static_cast<void *>(&decl_ctx->getParentASTContext()), + name.getAsString().c_str(), decl_ctx->getDeclKindName(), + static_cast<const void *>(decl_ctx)); } do { @@ -77,19 +78,20 @@ public: LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? if (log) { - log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on " - "(ASTContext*)%p Completing (TagDecl*)%p named %s", - current_id, static_cast<void *>(&tag_decl->getASTContext()), - static_cast<void *>(tag_decl), - tag_decl->getName().str().c_str()); - - log->Printf(" AOEAS::CT[%u] Before:", current_id); + LLDB_LOGF(log, + "AppleObjCExternalASTSource::CompleteType[%u] on " + "(ASTContext*)%p Completing (TagDecl*)%p named %s", + current_id, static_cast<void *>(&tag_decl->getASTContext()), + static_cast<void *>(tag_decl), + tag_decl->getName().str().c_str()); + + LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id); ASTDumper dumper((clang::Decl *)tag_decl); dumper.ToLog(log, " [CT] "); } if (log) { - log->Printf(" AOEAS::CT[%u] After:", current_id); + LLDB_LOGF(log, " AOEAS::CT[%u] After:", current_id); ASTDumper dumper((clang::Decl *)tag_decl); dumper.ToLog(log, " [CT] "); } @@ -104,14 +106,15 @@ public: LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? if (log) { - log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on " - "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s", - current_id, - static_cast<void *>(&interface_decl->getASTContext()), - static_cast<void *>(interface_decl), - interface_decl->getName().str().c_str()); - - log->Printf(" AOEAS::CT[%u] Before:", current_id); + LLDB_LOGF(log, + "AppleObjCExternalASTSource::CompleteType[%u] on " + "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s", + current_id, + static_cast<void *>(&interface_decl->getASTContext()), + static_cast<void *>(interface_decl), + interface_decl->getName().str().c_str()); + + LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id); ASTDumper dumper((clang::Decl *)interface_decl); dumper.ToLog(log, " [CT] "); } @@ -119,7 +122,7 @@ public: m_decl_vendor.FinishDecl(interface_decl); if (log) { - log->Printf(" [CT] After:"); + LLDB_LOGF(log, " [CT] After:"); ASTDumper dumper((clang::Decl *)interface_decl); dumper.ToLog(log, " [CT] "); } @@ -148,12 +151,13 @@ private: }; AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) - : DeclVendor(), m_runtime(runtime), m_ast_ctx(runtime.GetProcess() - ->GetTarget() - .GetArchitecture() - .GetTriple() - .getTriple() - .c_str()), + : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime), + m_ast_ctx(runtime.GetProcess() + ->GetTarget() + .GetArchitecture() + .GetTriple() + .getTriple() + .c_str()), m_type_realizer_sp(m_runtime.GetEncodingToType()) { m_external_source = new AppleObjCExternalASTSource(*this); llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr( @@ -462,8 +466,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(interface_decl, name, true, m_type_realizer_sp); - if (log) - log->Printf("[ AOTV::FD] Instance method [%s] [%s]", name, types); + LLDB_LOGF(log, "[ AOTV::FD] Instance method [%s] [%s]", name, types); if (method_decl) interface_decl->addDecl(method_decl); @@ -481,8 +484,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::ObjCMethodDecl *method_decl = method_type.BuildMethod( interface_decl, name, false, m_type_realizer_sp); - if (log) - log->Printf("[ AOTV::FD] Class method [%s] [%s]", name, types); + LLDB_LOGF(log, "[ AOTV::FD] Class method [%s] [%s]", name, types); if (method_decl) interface_decl->addDecl(method_decl); @@ -498,10 +500,9 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { const bool for_expression = false; - if (log) - log->Printf( - "[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, name, - type, offset_ptr); + LLDB_LOGF(log, + "[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, + name, type, offset_ptr); CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType( m_ast_ctx, type, for_expression); @@ -527,9 +528,10 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { if (log) { ASTDumper method_dumper((clang::Decl *)interface_decl); - log->Printf("[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C " - "interface for %s", - descriptor->GetClassName().AsCString()); + LLDB_LOGF(log, + "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C " + "interface for %s", + descriptor->GetClassName().AsCString()); } if (!descriptor->Describe(superclass_func, instance_method_func, @@ -539,7 +541,8 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { if (log) { ASTDumper method_dumper((clang::Decl *)interface_decl); - log->Printf( + LLDB_LOGF( + log, "[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface"); method_dumper.ToLog(log, " [AOTV::FD] "); @@ -558,10 +561,9 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, Log *log(GetLogIfAllCategoriesSet( LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? - if (log) - log->Printf("AppleObjCDeclVendor::FindDecls [%u] ('%s', %s, %u, )", - current_id, (const char *)name.AsCString(), - append ? "true" : "false", max_matches); + LLDB_LOGF(log, "AppleObjCDeclVendor::FindDecls [%u] ('%s', %s, %u, )", + current_id, (const char *)name.AsCString(), + append ? "true" : "false", max_matches); if (!append) decls.clear(); @@ -595,24 +597,25 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, if (metadata) isa_value = metadata->GetISAPtr(); - log->Printf("AOCTV::FT [%u] Found %s (isa 0x%" PRIx64 - ") in the ASTContext", - current_id, dumper.GetCString(), isa_value); + LLDB_LOGF(log, + "AOCTV::FT [%u] Found %s (isa 0x%" PRIx64 + ") in the ASTContext", + current_id, dumper.GetCString(), isa_value); } decls.push_back(result_iface_decl); ret++; break; } else { - if (log) - log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but " - "it's not something we know about", - current_id); + LLDB_LOGF(log, + "AOCTV::FT [%u] There's something in the ASTContext, but " + "it's not something we know about", + current_id); break; } } else if (log) { - log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext", - current_id, name.AsCString()); + LLDB_LOGF(log, "AOCTV::FT [%u] Couldn't find %s in the ASTContext", + current_id, name.AsCString()); } // It's not. If it exists, we have to put it into our ASTContext. @@ -620,8 +623,7 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name); if (!isa) { - if (log) - log->Printf("AOCTV::FT [%u] Couldn't find the isa", current_id); + LLDB_LOGF(log, "AOCTV::FT [%u] Couldn't find the isa", current_id); break; } @@ -629,10 +631,10 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa); if (!iface_decl) { - if (log) - log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for " - "isa 0x%" PRIx64, - current_id, (uint64_t)isa); + LLDB_LOGF(log, + "AOCTV::FT [%u] Couldn't get the Objective-C interface for " + "isa 0x%" PRIx64, + current_id, (uint64_t)isa); break; } @@ -641,8 +643,8 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl); ASTDumper dumper(new_iface_type); - log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")", current_id, - dumper.GetCString(), (uint64_t)isa); + LLDB_LOGF(log, "AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")", + current_id, dumper.GetCString(), (uint64_t)isa); } decls.push_back(iface_decl); @@ -655,8 +657,7 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, clang::ExternalASTMerger::ImporterSource AppleObjCDeclVendor::GetImporterSource() { - return {*m_ast_ctx.getASTContext(), - *m_ast_ctx.getFileManager(), - m_ast_ctx.GetOriginMap() - }; + return clang::ExternalASTMerger::ImporterSource(*m_ast_ctx.getASTContext(), + *m_ast_ctx.getFileManager(), + m_ast_ctx.GetOriginMap()); } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h index 77b30b7fde79..99ca4b748709 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -10,19 +10,23 @@ #define liblldb_AppleObjCDeclVendor_h_ #include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/DeclVendor.h" #include "lldb/lldb-private.h" +#include "Plugins/ExpressionParser/Clang/ClangDeclVendor.h" #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" namespace lldb_private { class AppleObjCExternalASTSource; -class AppleObjCDeclVendor : public DeclVendor { +class AppleObjCDeclVendor : public ClangDeclVendor { public: AppleObjCDeclVendor(ObjCLanguageRuntime &runtime); + static bool classof(const DeclVendor *vendor) { + return vendor->GetKind() == eAppleObjCDeclVendor; + } + uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches, std::vector<clang::NamedDecl *> &decls) override; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 52ed3628520f..8ca9ad7b843a 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -223,11 +223,14 @@ Address *AppleObjCRuntime::GetPrintForDebuggerAddr() { SymbolContextList contexts; SymbolContext context; - if ((!modules.FindSymbolsWithNameAndType(ConstString("_NSPrintForDebugger"), - eSymbolTypeCode, contexts)) && - (!modules.FindSymbolsWithNameAndType(ConstString("_CFPrintForDebugger"), - eSymbolTypeCode, contexts))) - return nullptr; + modules.FindSymbolsWithNameAndType(ConstString("_NSPrintForDebugger"), + eSymbolTypeCode, contexts); + if (contexts.IsEmpty()) { + modules.FindSymbolsWithNameAndType(ConstString("_CFPrintForDebugger"), + eSymbolTypeCode, contexts); + if (contexts.IsEmpty()) + return nullptr; + } contexts.GetContextAtIndex(0, context); @@ -444,10 +447,12 @@ bool AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing() { SymbolContextList sc_list; - return target.GetImages().FindSymbolsWithNameAndType( - s_method_signature, eSymbolTypeCode, sc_list) || - target.GetImages().FindSymbolsWithNameAndType( - s_arclite_method_signature, eSymbolTypeCode, sc_list); + target.GetImages().FindSymbolsWithNameAndType(s_method_signature, + eSymbolTypeCode, sc_list); + if (sc_list.IsEmpty()) + target.GetImages().FindSymbolsWithNameAndType(s_arclite_method_signature, + eSymbolTypeCode, sc_list); + return !sc_list.IsEmpty(); } lldb::SearchFilterSP AppleObjCRuntime::CreateExceptionSearchFilter() { diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index c8884fd5c9b9..88bfe2ce0203 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -395,10 +395,11 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) - log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 - " from _objc_debug_class_hash to " - "isa->descriptor cache", - isa); + LLDB_LOGF(log, + "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 + " from _objc_debug_class_hash to " + "isa->descriptor cache", + isa); AddClass(isa, descriptor_sp); } @@ -417,7 +418,8 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) - log->Printf( + LLDB_LOGF( + log, "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor " "cache", diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 635eaff637bc..9bdbef393e39 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -582,9 +582,9 @@ protected: case 0: break; case 1: { - regex_up.reset(new RegularExpression()); - if (!regex_up->Compile(llvm::StringRef::withNullAsEmpty( - command.GetArgumentAtIndex(0)))) { + regex_up.reset(new RegularExpression( + llvm::StringRef::withNullAsEmpty(command.GetArgumentAtIndex(0)))); + if (!regex_up->IsValid()) { result.AppendError( "invalid argument - please provide a valid regular expression"); result.SetStatus(lldb::eReturnStatusFailed); @@ -1209,11 +1209,11 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) { objc_class_sp = GetClassDescriptorFromISA(isa); if (isa && !objc_class_sp) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("0x%" PRIx64 - ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was " - "not in class descriptor cache 0x%" PRIx64, - isa_pointer, isa); + LLDB_LOGF(log, + "0x%" PRIx64 + ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was " + "not in class descriptor cache 0x%" PRIx64, + isa_pointer, isa); } } } @@ -1317,8 +1317,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( // Read the total number of classes from the hash table const uint32_t num_classes = hash_table.GetCount(); if (num_classes == 0) { - if (log) - log->Printf("No dynamic classes found in gdb_objc_realized_classes."); + LLDB_LOGF(log, "No dynamic classes found in gdb_objc_realized_classes."); return DescriptorMapUpdateResult::Success(0); } @@ -1337,17 +1336,16 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( g_get_dynamic_class_info_body, eLanguageTypeObjC, g_get_dynamic_class_info_name, error)); if (error.Fail()) { - if (log) - log->Printf( - "Failed to get Utility Function for implementation lookup: %s", - error.AsCString()); + LLDB_LOGF(log, + "Failed to get Utility Function for implementation lookup: %s", + error.AsCString()); m_get_class_info_code.reset(); } else { diagnostics.Clear(); if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) { if (log) { - log->Printf("Failed to install implementation lookup"); + LLDB_LOGF(log, "Failed to install implementation lookup"); diagnostics.Dump(log); } m_get_class_info_code.reset(); @@ -1372,17 +1370,16 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( clang_uint32_t_type, arguments, thread_sp, error); if (error.Fail()) { - if (log) - log->Printf( - "Failed to make function caller for implementation lookup: %s.", - error.AsCString()); + 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) { if (log) { - log->Printf("Failed to get implementation lookup function caller."); + LLDB_LOGF(log, "Failed to get implementation lookup function caller."); diagnostics.Dump(log); } @@ -1399,10 +1396,10 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); if (class_infos_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("unable to allocate %" PRIu32 - " bytes in process for shared cache read", - class_infos_byte_size); + LLDB_LOGF(log, + "unable to allocate %" PRIu32 + " bytes in process for shared cache read", + class_infos_byte_size); return DescriptorMapUpdateResult::Fail(); } @@ -1451,8 +1448,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in num_class_infos = return_value.GetScalar().ULong(); - if (log) - log->Printf("Discovered %u ObjC classes\n", num_class_infos); + LLDB_LOGF(log, "Discovered %u ObjC classes\n", num_class_infos); if (num_class_infos > 0) { // Read the ClassInfo structures DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0); @@ -1468,13 +1464,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( success = true; } else { if (log) { - log->Printf("Error evaluating our find class name function."); + LLDB_LOGF(log, "Error evaluating our find class name function."); diagnostics.Dump(log); } } } else { if (log) { - log->Printf("Error writing function arguments."); + LLDB_LOGF(log, "Error writing function arguments."); diagnostics.Dump(log); } } @@ -1507,17 +1503,18 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, if (isa == 0) { if (should_log) - log->Printf( - "AppleObjCRuntimeV2 found NULL isa, ignoring this class info"); + LLDB_LOGF( + log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info"); continue; } // Check if we already know about this ISA, if we do, the info will never // change, so we can just skip it. if (ISAIsCached(isa)) { if (should_log) - log->Printf("AppleObjCRuntimeV2 found cached isa=0x%" PRIx64 - ", ignoring this class info", - isa); + LLDB_LOGF(log, + "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64 + ", ignoring this class info", + isa); offset += 4; } else { // Read the 32 bit hash for the class name @@ -1536,15 +1533,16 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, AddClass(isa, descriptor_sp, descriptor_sp->GetClassName().AsCString(nullptr)); num_parsed++; if (should_log) - log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 - ", hash=0x%8.8x, name=%s", - isa, name_hash, - descriptor_sp->GetClassName().AsCString("<unknown>")); + LLDB_LOGF(log, + "AppleObjCRuntimeV2 added isa=0x%" PRIx64 + ", hash=0x%8.8x, name=%s", + isa, name_hash, + descriptor_sp->GetClassName().AsCString("<unknown>")); } } if (should_log) - log->Printf("AppleObjCRuntimeV2 parsed %" PRIu32 " class infos", - num_parsed); + LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos", + num_parsed); return num_parsed; } @@ -1603,7 +1601,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { // 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("class_getNameRaw"); + 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); @@ -1646,17 +1644,16 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { shared_class_expression.c_str(), eLanguageTypeObjC, g_get_shared_cache_class_info_name, error)); if (error.Fail()) { - if (log) - log->Printf( - "Failed to get Utility function for implementation lookup: %s.", - error.AsCString()); + LLDB_LOGF(log, + "Failed to get Utility function for implementation lookup: %s.", + error.AsCString()); m_get_shared_cache_class_info_code.reset(); } else { diagnostics.Clear(); if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) { if (log) { - log->Printf("Failed to install implementation lookup."); + LLDB_LOGF(log, "Failed to install implementation lookup."); diagnostics.Dump(log); } m_get_shared_cache_class_info_code.reset(); @@ -1703,10 +1700,10 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); if (class_infos_addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("unable to allocate %" PRIu32 - " bytes in process for shared cache read", - class_infos_byte_size); + LLDB_LOGF(log, + "unable to allocate %" PRIu32 + " bytes in process for shared cache read", + class_infos_byte_size); return DescriptorMapUpdateResult::Fail(); } @@ -1757,9 +1754,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in num_class_infos = return_value.GetScalar().ULong(); - if (log) - log->Printf("Discovered %u ObjC classes in shared cache\n", - num_class_infos); + LLDB_LOGF(log, "Discovered %u ObjC classes in shared cache\n", + num_class_infos); assert(num_class_infos <= num_classes); if (num_class_infos > 0) { if (num_class_infos > num_classes) { @@ -1786,13 +1782,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { } } else { if (log) { - log->Printf("Error evaluating our find class name function."); + LLDB_LOGF(log, "Error evaluating our find class name function."); diagnostics.Dump(log); } } } else { if (log) { - log->Printf("Error writing function arguments."); + LLDB_LOGF(log, "Error writing function arguments."); diagnostics.Dump(log); } } @@ -1827,9 +1823,10 @@ bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory( new ClassDescriptorV2(*this, elt.second, elt.first.AsCString())); if (log && log->GetVerbose()) - log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 - " (%s) from dynamic table to isa->descriptor cache", - elt.second, elt.first.AsCString()); + 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()); } @@ -1912,14 +1909,14 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { DescriptorMapUpdateResult shared_cache_update_result = UpdateISAToDescriptorMapSharedCache(); - if (log) - log->Printf("attempted to read objc class data - results: " - "[dynamic_update]: ran: %s, count: %" PRIu32 - " [shared_cache_update]: ran: %s, count: %" PRIu32, - dynamic_update_result.m_update_ran ? "yes" : "no", - dynamic_update_result.m_num_found, - shared_cache_update_result.m_update_ran ? "yes" : "no", - shared_cache_update_result.m_num_found); + LLDB_LOGF(log, + "attempted to read objc class data - results: " + "[dynamic_update]: ran: %s, count: %" PRIu32 + " [shared_cache_update]: ran: %s, count: %" PRIu32, + dynamic_update_result.m_update_ran ? "yes" : "no", + dynamic_update_result.m_num_found, + shared_cache_update_result.m_update_ran ? "yes" : "no", + shared_cache_update_result.m_num_found); // warn if: // - we could not run either expression @@ -2032,8 +2029,8 @@ lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { if (name_cstr) { llvm::StringRef name_strref(name_cstr); - static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); - static const llvm::StringRef class_prefix("OBJC_CLASS_$_"); + llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); + llvm::StringRef class_prefix("OBJC_CLASS_$_"); if (name_strref.startswith(ivar_prefix)) { llvm::StringRef ivar_skipped_prefix = @@ -2516,8 +2513,7 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( ObjCISA isa, ObjCISA &ret_isa) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); - if (log) - log->Printf("AOCRT::NPI Evalulate(isa = 0x%" PRIx64 ")", (uint64_t)isa); + LLDB_LOGF(log, "AOCRT::NPI Evalulate(isa = 0x%" PRIx64 ")", (uint64_t)isa); if ((isa & ~m_objc_debug_isa_class_mask) == 0) return false; @@ -2543,10 +2539,10 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( // read the count again, and update the cache if the count has been // updated. if (index > m_indexed_isa_cache.size()) { - if (log) - log->Printf("AOCRT::NPI (index = %" PRIu64 - ") exceeds cache (size = %" PRIu64 ")", - (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); + LLDB_LOGF(log, + "AOCRT::NPI (index = %" PRIu64 + ") exceeds cache (size = %" PRIu64 ")", + (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); Process *process(m_runtime.GetProcess()); @@ -2561,9 +2557,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( if (error.Fail()) return false; - if (log) - log->Printf("AOCRT::NPI (new class count = %" PRIu64 ")", - (uint64_t)objc_indexed_classes_count); + LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")", + (uint64_t)objc_indexed_classes_count); if (objc_indexed_classes_count > m_indexed_isa_cache.size()) { // Read the class entries we don't have. We should just read all of @@ -2581,9 +2576,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( if (error.Fail() || bytes_read != buffer.GetByteSize()) return false; - if (log) - log->Printf("AOCRT::NPI (read new classes count = %" PRIu64 ")", - (uint64_t)num_new_classes); + LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")", + (uint64_t)num_new_classes); // Append the new entries to the existing cache. DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), @@ -2600,9 +2594,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( if (index > m_indexed_isa_cache.size()) return false; - if (log) - log->Printf("AOCRT::NPI Evalulate(ret_isa = 0x%" PRIx64 ")", - (uint64_t)m_indexed_isa_cache[index]); + LLDB_LOGF(log, "AOCRT::NPI Evalulate(ret_isa = 0x%" PRIx64 ")", + (uint64_t)m_indexed_isa_cache[index]); ret_isa = m_indexed_isa_cache[index]; return (ret_isa != 0); // this is a pointer so 0 is not a valid value @@ -2647,8 +2640,9 @@ bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() { std::function<lldb::addr_t(ConstString)> get_symbol = [this](ConstString sym) -> lldb::addr_t { SymbolContextList sc_list; - if (GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType( - sym, lldb::eSymbolTypeData, sc_list) == 1) { + GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType( + sym, lldb::eSymbolTypeData, sc_list); + if (sc_list.GetSize() == 1) { SymbolContext sc; sc_list.GetContextAtIndex(0, sc); if (sc.symbol) diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index b3eb09caa86d..379ef3dca86c 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -543,7 +543,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines( Status error; DataExtractor data; error = argument_values.GetValueAtIndex(0)->GetValueAsData(&exe_ctx, data, - 0, nullptr); + nullptr); lldb::offset_t offset = 0; lldb::addr_t region_addr = data.GetPointer(&offset); @@ -593,7 +593,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions( if (log) { StreamString s; m_regions.back().Dump(s); - log->Printf("Read vtable region: \n%s", s.GetData()); + LLDB_LOGF(log, "Read vtable region: \n%s", s.GetData()); } next_region = m_regions.back().GetNextRegionAddr(); @@ -704,7 +704,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( // step through any method dispatches. Warn to that effect and get out of // here. if (process_sp->CanJIT()) { - process_sp->GetTarget().GetDebugger().GetErrorFile()->Printf( + process_sp->GetTarget().GetDebugger().GetErrorStream().Printf( "Could not find implementation lookup function \"%s\"" " step in through ObjC method dispatch will not work.\n", get_impl_name.AsCString()); @@ -779,25 +779,24 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, m_lookup_implementation_function_code, eLanguageTypeObjC, g_lookup_implementation_function_name, error)); if (error.Fail()) { - if (log) - log->Printf( - "Failed to get Utility Function for implementation lookup: %s.", - error.AsCString()); + LLDB_LOGF( + log, + "Failed to get Utility Function for implementation lookup: %s.", + error.AsCString()); m_impl_code.reset(); return args_addr; } if (!m_impl_code->Install(diagnostics, exe_ctx)) { if (log) { - log->Printf("Failed to install implementation lookup."); + LLDB_LOGF(log, "Failed to install implementation lookup."); diagnostics.Dump(log); } m_impl_code.reset(); return args_addr; } } else { - if (log) - log->Printf("No method lookup implementation code."); + LLDB_LOGF(log, "No method lookup implementation code."); return LLDB_INVALID_ADDRESS; } @@ -811,10 +810,9 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, impl_function_caller = m_impl_code->MakeFunctionCaller( clang_void_ptr_type, dispatch_values, thread_sp, error); if (error.Fail()) { - if (log) - log->Printf( - "Error getting function caller for dispatch lookup: \"%s\".", - error.AsCString()); + LLDB_LOGF(log, + "Error getting function caller for dispatch lookup: \"%s\".", + error.AsCString()); return args_addr; } } else { @@ -833,7 +831,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, if (!impl_function_caller->WriteFunctionArguments( exe_ctx, args_addr, dispatch_values, diagnostics)) { if (log) { - log->Printf("Error writing function arguments."); + LLDB_LOGF(log, "Error writing function arguments."); diagnostics.Dump(log); } return args_addr; @@ -934,9 +932,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, lldb::addr_t obj_addr = argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong(); if (obj_addr == 0x0) { - if (log) - log->Printf( - "Asked to step to dispatch to nil object, returning empty plan."); + LLDB_LOGF( + log, + "Asked to step to dispatch to nil object, returning empty plan."); return ret_plan_sp; } @@ -976,13 +974,11 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (super_value.GetScalar().IsValid()) isa_addr = super_value.GetScalar().ULongLong(); else { - if (log) - log->Printf("Failed to extract the super class value from the " - "class in objc_super."); + LLDB_LOGF(log, "Failed to extract the super class value from the " + "class in objc_super."); } } else { - if (log) - log->Printf("Failed to extract the class value from objc_super."); + LLDB_LOGF(log, "Failed to extract the class value from objc_super."); } } else { // In the objc_msgSendSuper case, we don't get the object @@ -998,8 +994,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (super_value.GetScalar().IsValid()) { isa_addr = super_value.GetScalar().ULongLong(); } else { - if (log) - log->Printf("Failed to extract the class value from objc_super."); + LLDB_LOGF(log, "Failed to extract the class value from objc_super."); } } } else { @@ -1022,8 +1017,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (isa_value.GetScalar().IsValid()) { isa_addr = isa_value.GetScalar().ULongLong(); } else { - if (log) - log->Printf("Failed to extract the isa value from object."); + LLDB_LOGF(log, "Failed to extract the isa value from object."); } } @@ -1033,9 +1027,10 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (isa_addr != LLDB_INVALID_ADDRESS) { if (log) { - log->Printf("Resolving call for class - 0x%" PRIx64 - " and selector - 0x%" PRIx64, - isa_addr, sel_addr); + LLDB_LOGF(log, + "Resolving call for class - 0x%" PRIx64 + " and selector - 0x%" PRIx64, + isa_addr, sel_addr); } ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*thread.GetProcess()); @@ -1047,9 +1042,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (impl_addr != LLDB_INVALID_ADDRESS) { // Yup, it was in the cache, so we can run to that address directly. - if (log) - log->Printf("Found implementation address in cache: 0x%" PRIx64, - impl_addr); + LLDB_LOGF(log, "Found implementation address in cache: 0x%" PRIx64, + impl_addr); ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(thread, impl_addr, stop_others); @@ -1137,7 +1131,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, if (log) { StreamString s; ret_plan_sp->GetDescription(&s, eDescriptionLevelFull); - log->Printf("Using ObjC step plan: %s.\n", s.GetData()); + LLDB_LOGF(log, "Using ObjC step plan: %s.\n", s.GetData()); } } } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 26654e9212b9..6402e80d6f98 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -18,7 +18,6 @@ #include <vector> using namespace lldb_private; -using namespace lldb_utility; AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( ObjCLanguageRuntime &runtime) @@ -32,16 +31,14 @@ AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( .c_str())); } -std::string -AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer &type) { +std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) { StreamString buffer; while (type.HasAtLeast(1) && type.Peek() != '=') buffer.Printf("%c", type.Next()); return buffer.GetString(); } -std::string -AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer &type) { +std::string AppleObjCTypeEncodingParser::ReadQuotedString(StringLexer &type) { StreamString buffer; while (type.HasAtLeast(1) && type.Peek() != '"') buffer.Printf("%c", type.Next()); @@ -51,8 +48,7 @@ AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer &type) { return buffer.GetString(); } -uint32_t -AppleObjCTypeEncodingParser::ReadNumber(lldb_utility::StringLexer &type) { +uint32_t AppleObjCTypeEncodingParser::ReadNumber(StringLexer &type) { uint32_t total = 0; while (type.HasAtLeast(1) && isdigit(type.Peek())) total = 10 * total + (type.Next() - '0'); @@ -68,7 +64,7 @@ AppleObjCTypeEncodingParser::StructElement::StructElement() AppleObjCTypeEncodingParser::StructElement AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + StringLexer &type, bool for_expression) { StructElement retval; if (type.NextIf('"')) @@ -81,25 +77,21 @@ AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx, return retval; } -clang::QualType -AppleObjCTypeEncodingParser::BuildStruct(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, - bool for_expression) { +clang::QualType AppleObjCTypeEncodingParser::BuildStruct( + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, '{', '}', clang::TTK_Struct); } -clang::QualType -AppleObjCTypeEncodingParser::BuildUnion(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, - bool for_expression) { +clang::QualType AppleObjCTypeEncodingParser::BuildUnion( + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, '(', ')', clang::TTK_Union); } clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( - clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type, - bool for_expression, char opener, char closer, uint32_t kind) { + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression, + char opener, char closer, uint32_t kind) { if (!type.NextIf(opener)) return clang::QualType(); std::string name(ReadStructName(type)); @@ -149,8 +141,9 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( } ClangASTContext::AddFieldToRecordType( union_type, element.name.c_str(), - CompilerType(&ast_ctx, element.type), lldb::eAccessPublic, - element.bitfield); + CompilerType(ClangASTContext::GetASTContext(&ast_ctx), + element.type.getAsOpaquePtr()), + lldb::eAccessPublic, element.bitfield); ++count; } ClangASTContext::CompleteTagDeclarationDefinition(union_type); @@ -158,10 +151,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( return ClangUtil::GetQualType(union_type); } -clang::QualType -AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, - bool for_expression) { +clang::QualType AppleObjCTypeEncodingParser::BuildArray( + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { if (!type.NextIf('[')) return clang::QualType(); uint32_t size = ReadNumber(type); @@ -172,7 +163,9 @@ AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx, if (!lldb_ctx) return clang::QualType(); CompilerType array_type(lldb_ctx->CreateArrayType( - CompilerType(&ast_ctx, element_type), size, false)); + CompilerType(ClangASTContext::GetASTContext(&ast_ctx), + element_type.getAsOpaquePtr()), + size, false)); return ClangUtil::GetQualType(array_type); } @@ -182,8 +175,7 @@ AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx, // consume but ignore the type info and always return an 'id'; if anything, // dynamic typing will resolve things for us anyway clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType( - clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type, - bool for_expression) { + clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) { if (!type.NextIf('@')) return clang::QualType(); @@ -375,7 +367,8 @@ CompilerType AppleObjCTypeEncodingParser::RealizeType( if (name && name[0]) { StringLexer lexer(name); clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression); - return CompilerType(&ast_ctx, qual_type); + return CompilerType(ClangASTContext::GetASTContext(&ast_ctx), + qual_type.getAsOpaquePtr()); } return CompilerType(); } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h index e576e8f283f2..590bc4ba9eae 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h @@ -15,12 +15,8 @@ #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" -namespace lldb_utility { -class StringLexer; -} - namespace lldb_private { - +class StringLexer; class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType { public: AppleObjCTypeEncodingParser(ObjCLanguageRuntime &runtime); @@ -39,41 +35,35 @@ private: ~StructElement() = default; }; - clang::QualType BuildType(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildType(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression, uint32_t *bitfield_bit_size = nullptr); - clang::QualType BuildStruct(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildStruct(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); - clang::QualType BuildAggregate(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildAggregate(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression, char opener, char closer, uint32_t kind); - clang::QualType BuildUnion(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildUnion(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); - clang::QualType BuildArray(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + clang::QualType BuildArray(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); - std::string ReadStructName(lldb_utility::StringLexer &type); + std::string ReadStructName(StringLexer &type); - StructElement ReadStructElement(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + StructElement ReadStructElement(clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression); clang::QualType BuildObjCObjectPointerType(clang::ASTContext &ast_ctx, - lldb_utility::StringLexer &type, + StringLexer &type, bool for_expression); - uint32_t ReadNumber(lldb_utility::StringLexer &type); + uint32_t ReadNumber(StringLexer &type); - std::string ReadQuotedString(lldb_utility::StringLexer &type); + std::string ReadQuotedString(StringLexer &type); ObjCLanguageRuntime &m_runtime; }; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index d18435c9c6db..af630eee7265 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -141,17 +141,15 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr()); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (target_addr == 0) { - if (log) - log->Printf("Got target implementation of 0x0, stopping."); + LLDB_LOGF(log, "Got target implementation of 0x0, stopping."); SetPlanComplete(); return true; } if (m_trampoline_handler->AddrIsMsgForward(target_addr)) { - if (log) - log->Printf( - "Implementation lookup returned msgForward function: 0x%" PRIx64 - ", stopping.", - target_addr); + LLDB_LOGF(log, + "Implementation lookup returned msgForward function: 0x%" PRIx64 + ", stopping.", + target_addr); SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext( eSymbolContextEverything); @@ -167,18 +165,17 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { return false; } - if (log) - log->Printf("Running to ObjC method implementation: 0x%" PRIx64, - target_addr); + LLDB_LOGF(log, "Running to ObjC method implementation: 0x%" PRIx64, + target_addr); ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*GetThread().GetProcess()); assert(objc_runtime != nullptr); objc_runtime->AddToMethodCache(m_isa_addr, m_sel_addr, target_addr); - if (log) - log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 - "} = addr=0x%" PRIx64 " to cache.", - m_isa_addr, m_sel_addr, target_addr); + LLDB_LOGF(log, + "Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 + "} = addr=0x%" PRIx64 " to cache.", + m_isa_addr, m_sel_addr, target_addr); // Extract the target address from the value: diff --git a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp index 631c15c46ce8..87ae4c2c6c48 100644 --- a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp @@ -64,9 +64,10 @@ void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr, lldb::addr_t impl_addr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) { - log->Printf("Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 - " implementation 0x%" PRIx64 ".", - class_addr, selector, impl_addr); + LLDB_LOGF(log, + "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64 + " implementation 0x%" PRIx64 ".", + class_addr, selector, impl_addr); } m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>( ClassAndSel(class_addr, selector), impl_addr)); @@ -102,8 +103,8 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { const ModuleList &modules = m_process->GetTarget().GetImages(); SymbolContextList sc_list; - const size_t matching_symbols = - modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); + modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); + const size_t matching_symbols = sc_list.GetSize(); if (matching_symbols) { SymbolContext sc; @@ -120,20 +121,17 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { TypeList types; llvm::DenseSet<SymbolFile *> searched_symbol_files; - const uint32_t num_types = module_sp->FindTypes( - name, exact_match, max_matches, searched_symbol_files, types); - - if (num_types) { - uint32_t i; - for (i = 0; i < num_types; ++i) { - TypeSP type_sp(types.GetTypeAtIndex(i)); - - if (ClangASTContext::IsObjCObjectOrInterfaceType( - type_sp->GetForwardCompilerType())) { - if (type_sp->IsCompleteObjCClass()) { - m_complete_class_cache[name] = type_sp; - return type_sp; - } + module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files, + types); + + for (uint32_t i = 0; i < types.GetSize(); ++i) { + TypeSP type_sp(types.GetTypeAtIndex(i)); + + if (ClangASTContext::IsObjCObjectOrInterfaceType( + type_sp->GetForwardCompilerType())) { + if (type_sp->IsCompleteObjCClass()) { + m_complete_class_cache[name] = type_sp; + return type_sp; } } } diff --git a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h index 1925c78ed342..39acd6e9f268 100644 --- a/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h +++ b/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h @@ -17,6 +17,7 @@ #include "llvm/Support/Casting.h" #include "lldb/Breakpoint/BreakpointPrecondition.h" +#include "lldb/Core/ClangForward.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Symbol/CompilerType.h" diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp index 60549663db66..b396781e6726 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp @@ -140,10 +140,10 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) { // We've been using a triple and datalayout of some ARM variant all along, // so we need to let the backend know that this is no longer the case. if (log) { - log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__, - real_triple.str().c_str()); - log->Printf( - "%s - Changing RS datalayout to '%s'", __FUNCTION__, + LLDB_LOGF(log, "%s - Changing RS target triple to '%s'", __FUNCTION__, + real_triple.str().c_str()); + LLDB_LOGF( + log, "%s - Changing RS datalayout to '%s'", __FUNCTION__, target_machine->createDataLayout().getStringRepresentation().c_str()); } module.setTargetTriple(real_triple); diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index c9cd34cf379d..5200749d759f 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -138,9 +138,8 @@ bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { size_t read = ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), err); if (read != arg_size || !err.Success()) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 " '%s'", - __FUNCTION__, uint64_t(i), err.AsCString()); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 " '%s'", + __FUNCTION__, uint64_t(i), err.AsCString()); return false; } } @@ -173,8 +172,7 @@ bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { // check the stack alignment was correct (16 byte aligned) if ((sp & 0xf) != 0x0) { - if (log) - log->Printf("%s - stack misaligned", __FUNCTION__); + LLDB_LOGF(log, "%s - stack misaligned", __FUNCTION__); return false; } @@ -213,9 +211,8 @@ bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -258,9 +255,8 @@ bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -285,15 +281,13 @@ bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // arguments passed on the stack else { - if (log) - log->Printf("%s - reading arguments spilled to stack not implemented", - __FUNCTION__); + LLDB_LOGF(log, "%s - reading arguments spilled to stack not implemented", + __FUNCTION__); } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64, __FUNCTION__, - uint64_t(i)); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64, __FUNCTION__, + uint64_t(i)); return false; } } @@ -337,9 +331,8 @@ bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -385,9 +378,8 @@ bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { } // fail if we couldn't read this argument if (!success) { - if (log) - log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s", - __FUNCTION__, uint64_t(i), err.AsCString("n/a")); + LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", + __FUNCTION__, uint64_t(i), err.AsCString("n/a")); return false; } } @@ -399,8 +391,7 @@ bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) { // verify that we have a target if (!exe_ctx.GetTargetPtr()) { - if (log) - log->Printf("%s - invalid target", __FUNCTION__); + LLDB_LOGF(log, "%s - invalid target", __FUNCTION__); return false; } @@ -430,9 +421,8 @@ bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) { default: // unsupported architecture if (log) { - log->Printf( - "%s - architecture not supported: '%s'", __FUNCTION__, - exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName()); + LLDB_LOGF(log, "%s - architecture not supported: '%s'", __FUNCTION__, + exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName()); } return false; } @@ -452,28 +442,20 @@ bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) { // elements fails the contents of &coord are undefined and `false` is // returned, `true` otherwise - RegularExpression regex; - RegularExpression::Match regex_match(3); - - bool matched = false; - if (regex.Compile(llvm::StringRef("^([0-9]+),([0-9]+),([0-9]+)$")) && - regex.Execute(coord_s, ®ex_match)) - matched = true; - else if (regex.Compile(llvm::StringRef("^([0-9]+),([0-9]+)$")) && - regex.Execute(coord_s, ®ex_match)) - matched = true; - else if (regex.Compile(llvm::StringRef("^([0-9]+)$")) && - regex.Execute(coord_s, ®ex_match)) - matched = true; - - if (!matched) + llvm::SmallVector<llvm::StringRef, 4> matches; + + if (!RegularExpression("^([0-9]+),([0-9]+),([0-9]+)$") + .Execute(coord_s, &matches) && + !RegularExpression("^([0-9]+),([0-9]+)$").Execute(coord_s, &matches) && + !RegularExpression("^([0-9]+)$").Execute(coord_s, &matches)) return false; - auto get_index = [&](int idx, uint32_t &i) -> bool { + auto get_index = [&](size_t idx, uint32_t &i) -> bool { std::string group; errno = 0; - if (regex_match.GetMatchAtIndex(coord_s.str().c_str(), idx + 1, group)) - return !llvm::StringRef(group).getAsInteger<uint32_t>(10, i); + if (idx + 1 < matches.size()) { + return !llvm::StringRef(matches[idx + 1]).getAsInteger<uint32_t>(10, i); + } return true; }; @@ -492,9 +474,8 @@ bool SkipPrologue(lldb::ModuleSP &module, Address &addr) { ConstString name = sc.GetFunctionName(); if (offset) addr.Slide(offset); - if (log) - log->Printf("%s: Prologue offset for %s is %" PRIu32, __FUNCTION__, - name.AsCString(), offset); + LLDB_LOGF(log, "%s: Prologue offset for %s is %" PRIu32, __FUNCTION__, + name.AsCString(), offset); } return true; } else @@ -809,7 +790,7 @@ RenderScriptRuntime::CreateInstance(Process *process, // symbol. Searcher::CallbackReturn RSBreakpointResolver::SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *, bool) { + SymbolContext &context, Address *) { ModuleSP module = context.module_sp; if (!module || !IsRenderScriptScriptModule(module)) @@ -839,7 +820,7 @@ RSBreakpointResolver::SearchCallback(SearchFilter &filter, Searcher::CallbackReturn RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, lldb_private::SymbolContext &context, - Address *, bool) { + Address *) { // We need to have access to the list of reductions currently parsed, as // reduce names don't actually exist as symbols in a module. They are only // identifiable by parsing the .rs.info packet, or finding the expand symbol. @@ -884,14 +865,13 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, if (filter.AddressPasses(address)) { bool new_bp; if (!SkipPrologue(module, address)) { - if (log) - log->Printf("%s: Error trying to skip prologue", __FUNCTION__); + LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__); } m_breakpoint->AddLocation(address, &new_bp); - if (log) - log->Printf("%s: %s reduction breakpoint on %s in %s", __FUNCTION__, - new_bp ? "new" : "existing", kernel_name.GetCString(), - address.GetModule()->GetFileSpec().GetCString()); + LLDB_LOGF(log, "%s: %s reduction breakpoint on %s in %s", + __FUNCTION__, new_bp ? "new" : "existing", + kernel_name.GetCString(), + address.GetModule()->GetFileSpec().GetCString()); } } } @@ -900,8 +880,7 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, } Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback( - SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing) { + SearchFilter &filter, SymbolContext &context, Address *addr) { if (!m_breakpoint) return eCallbackReturnContinue; @@ -920,48 +899,43 @@ Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback( for (auto &name : names) { const RSScriptGroupDescriptorSP sg = FindScriptGroup(ConstString(name)); if (!sg) { - if (log) - log->Printf("%s: could not find script group for %s", __FUNCTION__, - name.c_str()); + LLDB_LOGF(log, "%s: could not find script group for %s", __FUNCTION__, + name.c_str()); continue; } - if (log) - log->Printf("%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str()); + LLDB_LOGF(log, "%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str()); for (const RSScriptGroupDescriptor::Kernel &k : sg->m_kernels) { if (log) { - log->Printf("%s: Adding breakpoint for %s", __FUNCTION__, - k.m_name.AsCString()); - log->Printf("%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr); + LLDB_LOGF(log, "%s: Adding breakpoint for %s", __FUNCTION__, + k.m_name.AsCString()); + LLDB_LOGF(log, "%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr); } const lldb_private::Symbol *sym = module->FindFirstSymbolWithNameAndType(k.m_name, eSymbolTypeCode); if (!sym) { - if (log) - log->Printf("%s: Unable to find symbol for %s", __FUNCTION__, - k.m_name.AsCString()); + LLDB_LOGF(log, "%s: Unable to find symbol for %s", __FUNCTION__, + k.m_name.AsCString()); continue; } if (log) { - log->Printf("%s: Found symbol name is %s", __FUNCTION__, - sym->GetName().AsCString()); + LLDB_LOGF(log, "%s: Found symbol name is %s", __FUNCTION__, + sym->GetName().AsCString()); } auto address = sym->GetAddress(); if (!SkipPrologue(module, address)) { - if (log) - log->Printf("%s: Error trying to skip prologue", __FUNCTION__); + LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__); } bool new_bp; m_breakpoint->AddLocation(address, &new_bp); - if (log) - log->Printf("%s: Placed %sbreakpoint on %s", __FUNCTION__, - new_bp ? "new " : "", k.m_name.AsCString()); + LLDB_LOGF(log, "%s: Placed %sbreakpoint on %s", __FUNCTION__, + new_bp ? "new " : "", k.m_name.AsCString()); // exit after placing the first breakpoint if we do not intend to stop on // all kernels making up this script group @@ -1136,8 +1110,7 @@ void RenderScriptRuntime::HookCallback(RuntimeHook *hook, ExecutionContext &exe_ctx) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - if (log) - log->Printf("%s - '%s'", __FUNCTION__, hook->defn->name); + LLDB_LOGF(log, "%s - '%s'", __FUNCTION__, hook->defn->name); if (hook->defn->grabber) { (this->*(hook->defn->grabber))(hook, exe_ctx); @@ -1163,19 +1136,18 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( }}; if (!GetArgs(context, args.data(), args.size())) { - if (log) - log->Printf("%s - Error while reading the function parameters", - __FUNCTION__); + LLDB_LOGF(log, "%s - Error while reading the function parameters", + __FUNCTION__); return; } else if (log) { - log->Printf("%s - groupName : 0x%" PRIx64, __FUNCTION__, - addr_t(args[eGroupName])); - log->Printf("%s - groupNameSize: %" PRIu64, __FUNCTION__, - uint64_t(args[eGroupNameSize])); - log->Printf("%s - kernel : 0x%" PRIx64, __FUNCTION__, - addr_t(args[eKernel])); - log->Printf("%s - kernelCount : %" PRIu64, __FUNCTION__, - uint64_t(args[eKernelCount])); + LLDB_LOGF(log, "%s - groupName : 0x%" PRIx64, __FUNCTION__, + addr_t(args[eGroupName])); + LLDB_LOGF(log, "%s - groupNameSize: %" PRIu64, __FUNCTION__, + uint64_t(args[eGroupNameSize])); + LLDB_LOGF(log, "%s - kernel : 0x%" PRIx64, __FUNCTION__, + addr_t(args[eKernel])); + LLDB_LOGF(log, "%s - kernelCount : %" PRIu64, __FUNCTION__, + uint64_t(args[eKernelCount])); } // parse script group name @@ -1187,12 +1159,10 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( m_process->ReadMemory(addr_t(args[eGroupName]), buffer.get(), len, err); buffer.get()[len] = '\0'; if (!err.Success()) { - if (log) - log->Printf("Error reading scriptgroup name from target"); + LLDB_LOGF(log, "Error reading scriptgroup name from target"); return; } else { - if (log) - log->Printf("Extracted scriptgroup name %s", buffer.get()); + LLDB_LOGF(log, "Extracted scriptgroup name %s", buffer.get()); } // write back the script group name group_name.SetCString(buffer.get()); @@ -1214,9 +1184,8 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( m_scriptGroups.push_back(group); } else { // already have this script group - if (log) - log->Printf("Attempt to add duplicate script group %s", - group_name.AsCString()); + LLDB_LOGF(log, "Attempt to add duplicate script group %s", + group_name.AsCString()); return; } } @@ -1234,21 +1203,18 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( size_t read = m_process->ReadMemory(ptr_addr, &kernel_addr, target_ptr_size, err); if (!err.Success() || read != target_ptr_size) { - if (log) - log->Printf("Error parsing kernel address %" PRIu64 " in script group", - i); + LLDB_LOGF(log, "Error parsing kernel address %" PRIu64 " in script group", + i); return; } - if (log) - log->Printf("Extracted scriptgroup kernel address - 0x%" PRIx64, - kernel_addr); + LLDB_LOGF(log, "Extracted scriptgroup kernel address - 0x%" PRIx64, + kernel_addr); kernel.m_addr = kernel_addr; // try to resolve the associated kernel name if (!ResolveKernelName(kernel.m_addr, kernel.m_name)) { - if (log) - log->Printf("Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i, - kernel_addr); + LLDB_LOGF(log, "Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i, + kernel_addr); return; } @@ -1261,9 +1227,8 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( // verify this function is a valid kernel if (IsKnownKernel(base_kernel)) { kernel.m_name = base_kernel; - if (log) - log->Printf("%s - found non expand version '%s'", __FUNCTION__, - base_kernel.GetCString()); + LLDB_LOGF(log, "%s - found non expand version '%s'", __FUNCTION__, + base_kernel.GetCString()); } } } @@ -1276,15 +1241,13 @@ void RenderScriptRuntime::CaptureDebugHintScriptGroup2( Target &target = m_process->GetTarget(); const BreakpointList &list = target.GetBreakpointList(); const size_t num_breakpoints = list.GetSize(); - if (log) - log->Printf("Resolving %zu breakpoints", num_breakpoints); + LLDB_LOGF(log, "Resolving %zu breakpoints", num_breakpoints); for (size_t i = 0; i < num_breakpoints; ++i) { const BreakpointSP bp = list.GetBreakpointAtIndex(i); if (bp) { if (bp->MatchesName(group_name.AsCString())) { - if (log) - log->Printf("Found breakpoint with name %s", - group_name.AsCString()); + LLDB_LOGF(log, "Found breakpoint with name %s", + group_name.AsCString()); bp->ResolveBreakpoint(); } } @@ -1322,9 +1285,8 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - Error while reading the function parameters", - __FUNCTION__); + LLDB_LOGF(log, "%s - Error while reading the function parameters", + __FUNCTION__); return; } @@ -1342,10 +1304,9 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( uint64_t result = 0; size_t read = m_process->ReadMemory(addr, &result, target_ptr_size, err); if (read != target_ptr_size || !err.Success()) { - if (log) - log->Printf( - "%s - Error while reading allocation list argument %" PRIu64, - __FUNCTION__, i); + LLDB_LOGF(log, + "%s - Error while reading allocation list argument %" PRIu64, + __FUNCTION__, i); } else { allocs.push_back(result); } @@ -1375,8 +1336,8 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( if (log) { if (alloc->context.isValid() && *alloc->context.get() != addr_t(args[eRsContext])) - log->Printf("%s - Allocation used by multiple contexts", - __FUNCTION__); + LLDB_LOGF(log, "%s - Allocation used by multiple contexts", + __FUNCTION__); } alloc->context = addr_t(args[eRsContext]); } @@ -1388,7 +1349,7 @@ void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( if (log) { if (script->context.isValid() && *script->context.get() != addr_t(args[eRsContext])) - log->Printf("%s - Script used by multiple contexts", __FUNCTION__); + LLDB_LOGF(log, "%s - Script used by multiple contexts", __FUNCTION__); } script->context = addr_t(args[eRsContext]); } @@ -1416,26 +1377,26 @@ void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook, bool success = GetArgs(context, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error reading the function parameters.", __FUNCTION__); + LLDB_LOGF(log, "%s - error reading the function parameters.", __FUNCTION__); return; } if (log) { - log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 - ":%" PRIu64 "bytes.", - __FUNCTION__, uint64_t(args[eRsContext]), - uint64_t(args[eRsScript]), uint64_t(args[eRsId]), - uint64_t(args[eRsData]), uint64_t(args[eRsLength])); + LLDB_LOGF(log, + "%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 + ":%" PRIu64 "bytes.", + __FUNCTION__, uint64_t(args[eRsContext]), + uint64_t(args[eRsScript]), uint64_t(args[eRsId]), + uint64_t(args[eRsData]), uint64_t(args[eRsLength])); addr_t script_addr = addr_t(args[eRsScript]); if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) { auto rsm = m_scriptMappings[script_addr]; if (uint64_t(args[eRsId]) < rsm->m_globals.size()) { auto rsg = rsm->m_globals[uint64_t(args[eRsId])]; - log->Printf("%s - Setting of '%s' within '%s' inferred", __FUNCTION__, - rsg.m_name.AsCString(), - rsm->m_module->GetFileSpec().GetFilename().AsCString()); + LLDB_LOGF(log, "%s - Setting of '%s' within '%s' inferred", + __FUNCTION__, rsg.m_name.AsCString(), + rsm->m_module->GetFileSpec().GetFilename().AsCString()); } } } @@ -1455,16 +1416,14 @@ void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook, bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error while reading the function parameters", - __FUNCTION__); + LLDB_LOGF(log, "%s - error while reading the function parameters", + __FUNCTION__); return; } - if (log) - log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", - __FUNCTION__, uint64_t(args[eRsContext]), - uint64_t(args[eRsAlloc]), uint64_t(args[eRsForceZero])); + LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", + __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]), + uint64_t(args[eRsForceZero])); AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc])); if (alloc) @@ -1487,29 +1446,25 @@ void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook, bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error while reading the function parameters.", - __FUNCTION__); + LLDB_LOGF(log, "%s - error while reading the function parameters.", + __FUNCTION__); return; } - if (log) - log->Printf("%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, - uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc])); + LLDB_LOGF(log, "%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, + uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc])); for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) { auto &allocation_up = *iter; // get the unique pointer if (allocation_up->address.isValid() && *allocation_up->address.get() == addr_t(args[eRsAlloc])) { m_allocations.erase(iter); - if (log) - log->Printf("%s - deleted allocation entry.", __FUNCTION__); + LLDB_LOGF(log, "%s - deleted allocation entry.", __FUNCTION__); return; } } - if (log) - log->Printf("%s - couldn't find destroyed allocation.", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't find destroyed allocation.", __FUNCTION__); } void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook, @@ -1526,32 +1481,28 @@ void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook, ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}}; bool success = GetArgs(exe_ctx, &args[0], args.size()); if (!success) { - if (log) - log->Printf("%s - error while reading the function parameters.", - __FUNCTION__); + LLDB_LOGF(log, "%s - error while reading the function parameters.", + __FUNCTION__); return; } std::string res_name; process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), res_name, err); if (err.Fail()) { - if (log) - log->Printf("%s - error reading res_name: %s.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error reading res_name: %s.", __FUNCTION__, + err.AsCString()); } std::string cache_dir; process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cache_dir, err); if (err.Fail()) { - if (log) - log->Printf("%s - error reading cache_dir: %s.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error reading cache_dir: %s.", __FUNCTION__, + err.AsCString()); } - if (log) - log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", - __FUNCTION__, uint64_t(args[eRsContext]), - uint64_t(args[eRsScript]), res_name.c_str(), cache_dir.c_str()); + LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", + __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsScript]), + res_name.c_str(), cache_dir.c_str()); if (res_name.size() > 0) { StreamString strm; @@ -1566,13 +1517,14 @@ void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook, script->context = addr_t(args[eRsContext]); } - if (log) - log->Printf("%s - '%s' tagged with context 0x%" PRIx64 - " and script 0x%" PRIx64 ".", - __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]), - uint64_t(args[eRsScript])); + LLDB_LOGF(log, + "%s - '%s' tagged with context 0x%" PRIx64 + " and script 0x%" PRIx64 ".", + __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]), + uint64_t(args[eRsScript])); } else if (log) { - log->Printf("%s - resource name invalid, Script not tagged.", __FUNCTION__); + LLDB_LOGF(log, "%s - resource name invalid, Script not tagged.", + __FUNCTION__); } } @@ -1593,8 +1545,7 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, machine != llvm::Triple::ArchType::mipsel && machine != llvm::Triple::ArchType::mips64el && machine != llvm::Triple::ArchType::x86_64) { - if (log) - log->Printf("%s - unable to hook runtime functions.", __FUNCTION__); + LLDB_LOGF(log, "%s - unable to hook runtime functions.", __FUNCTION__); return; } @@ -1618,23 +1569,22 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ConstString(symbol_name), eSymbolTypeCode); if (!sym) { if (log) { - log->Printf("%s - symbol '%s' related to the function %s not found", - __FUNCTION__, symbol_name, hook_defn->name); + LLDB_LOGF(log, "%s - symbol '%s' related to the function %s not found", + __FUNCTION__, symbol_name, hook_defn->name); } continue; } addr_t addr = sym->GetLoadAddress(&target); if (addr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("%s - unable to resolve the address of hook function '%s' " - "with symbol '%s'.", - __FUNCTION__, hook_defn->name, symbol_name); + LLDB_LOGF(log, + "%s - unable to resolve the address of hook function '%s' " + "with symbol '%s'.", + __FUNCTION__, hook_defn->name, symbol_name); continue; } else { - if (log) - log->Printf("%s - function %s, address resolved at 0x%" PRIx64, - __FUNCTION__, hook_defn->name, addr); + LLDB_LOGF(log, "%s - function %s, address resolved at 0x%" PRIx64, + __FUNCTION__, hook_defn->name, addr); } RuntimeHookSP hook(new RuntimeHook()); @@ -1644,11 +1594,12 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, hook->bp_sp->SetCallback(HookCallback, hook.get(), true); m_runtimeHooks[addr] = hook; if (log) { - log->Printf("%s - successfully hooked '%s' in '%s' version %" PRIu64 - " at 0x%" PRIx64 ".", - __FUNCTION__, hook_defn->name, - module->GetFileSpec().GetFilename().AsCString(), - (uint64_t)hook_defn->version, (uint64_t)addr); + LLDB_LOGF(log, + "%s - successfully hooked '%s' in '%s' version %" PRIu64 + " at 0x%" PRIx64 ".", + __FUNCTION__, hook_defn->name, + module->GetFileSpec().GetFilename().AsCString(), + (uint64_t)hook_defn->version, (uint64_t)addr); } hook_placed[idx] = true; } @@ -1661,8 +1612,8 @@ void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, const HookDefn &hook_defn = s_runtimeHookDefns[i]; if (hook_defn.kind != kind) continue; - log->Printf("%s - function %s was not hooked", __FUNCTION__, - hook_defn.name); + LLDB_LOGF(log, "%s - function %s was not hooked", __FUNCTION__, + hook_defn.name); } } } @@ -1697,11 +1648,11 @@ void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) { if (m_scriptMappings.find(script) != m_scriptMappings.end()) { // if the module we have stored is different to the one we just received. if (m_scriptMappings[script] != rsmodule_sp) { - if (log) - log->Printf( - "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", - __FUNCTION__, (uint64_t)script, - rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); + LLDB_LOGF( + log, + "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", + __FUNCTION__, (uint64_t)script, + rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); } } // We don't have a script mapping for the current script. @@ -1713,11 +1664,9 @@ void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) { rsmodule_sp->m_resname = res_name; // Add Script/Module pair to map. m_scriptMappings[script] = rsmodule_sp; - if (log) - log->Printf( - "%s - script %" PRIx64 " associated with rsmodule '%s'.", - __FUNCTION__, (uint64_t)script, - rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); + LLDB_LOGF(log, "%s - script %" PRIx64 " associated with rsmodule '%s'.", + __FUNCTION__, (uint64_t)script, + rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); } } } @@ -1730,8 +1679,7 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, StackFrame *frame_ptr, uint64_t *result) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - if (log) - log->Printf("%s(%s)", __FUNCTION__, expr); + LLDB_LOGF(log, "%s(%s)", __FUNCTION__, expr); ValueObjectSP expr_result; EvaluateExpressionOptions options; @@ -1741,8 +1689,7 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, target.EvaluateExpression(expr, frame_ptr, expr_result, options); if (!expr_result) { - if (log) - log->Printf("%s: couldn't evaluate expression.", __FUNCTION__); + LLDB_LOGF(log, "%s: couldn't evaluate expression.", __FUNCTION__); return false; } @@ -1751,16 +1698,14 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, Status err = expr_result->GetError(); // Expression returned is void, so this is actually a success if (err.GetError() == UserExpression::kNoResult) { - if (log) - log->Printf("%s - expression returned void.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression returned void.", __FUNCTION__); result = nullptr; return true; } - if (log) - log->Printf("%s - error evaluating expression result: %s", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error evaluating expression result: %s", __FUNCTION__, + err.AsCString()); return false; } @@ -1769,9 +1714,8 @@ bool RenderScriptRuntime::EvalRSExpression(const char *expr, *result = expr_result->GetValueAsUnsigned(0, &success); if (!success) { - if (log) - log->Printf("%s - couldn't convert expression result to uint32_t", - __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't convert expression result to uint32_t", + __FUNCTION__); return false; } @@ -1884,8 +1828,7 @@ bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->address.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -1895,12 +1838,10 @@ bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->address.get(), x, y, z); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -1922,8 +1863,7 @@ bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->address.isValid() || !alloc->context.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -1933,12 +1873,10 @@ bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->context.get(), *alloc->address.get()); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -1960,8 +1898,7 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->type_ptr.isValid() || !alloc->context.isValid()) { - if (log) - log->Printf("%s - Failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - Failed to find allocation details.", __FUNCTION__); return false; } @@ -1983,12 +1920,10 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, *alloc->context.get(), bits, *alloc->type_ptr.get()); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2007,10 +1942,10 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, addr_t element_ptr = static_cast<lldb::addr_t>(results[3]); alloc->element.element_ptr = element_ptr; - if (log) - log->Printf("%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 - ") Element*: 0x%" PRIx64 ".", - __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr); + LLDB_LOGF(log, + "%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 + ") Element*: 0x%" PRIx64 ".", + __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr); return true; } @@ -2024,8 +1959,7 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!elem.element_ptr.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2042,12 +1976,10 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem, int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, context, *elem.element_ptr.get()); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2063,11 +1995,11 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem, elem.type_vec_size = static_cast<uint32_t>(results[2]); elem.field_count = static_cast<uint32_t>(results[3]); - if (log) - log->Printf("%s - data type %" PRIu32 ", pixel type %" PRIu32 - ", vector size %" PRIu32 ", field count %" PRIu32, - __FUNCTION__, *elem.type.get(), *elem.type_kind.get(), - *elem.type_vec_size.get(), *elem.field_count.get()); + LLDB_LOGF(log, + "%s - data type %" PRIu32 ", pixel type %" PRIu32 + ", vector size %" PRIu32 ", field count %" PRIu32, + __FUNCTION__, *elem.type.get(), *elem.type_kind.get(), + *elem.type_vec_size.get(), *elem.field_count.get()); // If this Element has subelements then JIT rsaElementGetSubElements() for // details about its fields @@ -2084,8 +2016,7 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2107,12 +2038,10 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, context, field_count, field_count, field_count, *elem.element_ptr.get(), field_count, field_index); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2120,8 +2049,7 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, if (!EvalRSExpression(expr_buffer, frame_ptr, &results)) return false; - if (log) - log->Printf("%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results); + LLDB_LOGF(log, "%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results); switch (expr_index) { case 0: // Element* of child @@ -2136,9 +2064,8 @@ bool RenderScriptRuntime::JITSubelements(Element &elem, if (!err.Fail()) child.type_name = ConstString(name); else { - if (log) - log->Printf("%s - warning: Couldn't read field name.", - __FUNCTION__); + LLDB_LOGF(log, "%s - warning: Couldn't read field name.", + __FUNCTION__); } break; } @@ -2173,8 +2100,7 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc, if (!alloc->address.isValid() || !alloc->dimension.isValid() || !alloc->data_ptr.isValid() || !alloc->element.datum_size.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2196,9 +2122,8 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc, alloc->size = dim_x * dim_y * dim_z * *alloc->element.datum_size.get(); - if (log) - log->Printf("%s - inferred size of struct allocation %" PRIu32 ".", - __FUNCTION__, *alloc->size.get()); + LLDB_LOGF(log, "%s - inferred size of struct allocation %" PRIu32 ".", + __FUNCTION__, *alloc->size.get()); return true; } @@ -2213,12 +2138,10 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->address.get(), dim_x, dim_y, dim_z); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2242,8 +2165,7 @@ bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!alloc->address.isValid() || !alloc->data_ptr.isValid()) { - if (log) - log->Printf("%s - failed to find allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -2253,12 +2175,10 @@ bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc, int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, *alloc->address.get(), 0, 1, 0); if (written < 0) { - if (log) - log->Printf("%s - encoding error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (written >= jit_max_expr_size) { - if (log) - log->Printf("%s - expression too long.", __FUNCTION__); + LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); return false; } @@ -2354,9 +2274,8 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem, // '#rs_padding_[0-9]+' if (found && num_children < elem.children.size()) { const uint32_t size_diff = elem.children.size() - num_children; - if (log) - log->Printf("%s - %" PRIu32 " padding struct entries", __FUNCTION__, - size_diff); + LLDB_LOGF(log, "%s - %" PRIu32 " padding struct entries", __FUNCTION__, + size_diff); for (uint32_t i = 0; i < size_diff; ++i) { ConstString name = elem.children[num_children + i].type_name; @@ -2377,9 +2296,8 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem, // Save name of variable in Element. elem.type_name = valobj_sp->GetTypeName(); - if (log) - log->Printf("%s - element name set to %s", __FUNCTION__, - elem.type_name.AsCString()); + LLDB_LOGF(log, "%s - element name set to %s", __FUNCTION__, + elem.type_name.AsCString()); return; } @@ -2424,9 +2342,8 @@ void RenderScriptRuntime::SetElementSize(Element &elem) { elem.padding = padding; elem.datum_size = data_size + padding; - if (log) - log->Printf("%s - element size set to %" PRIu32, __FUNCTION__, - data_size + padding); + LLDB_LOGF(log, "%s - element size set to %" PRIu32, __FUNCTION__, + data_size + padding); } // Given an allocation, this function copies the allocation contents from @@ -2439,13 +2356,11 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc, // JIT all the allocation details if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info", + __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { - if (log) - log->Printf("%s - couldn't JIT allocation details", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__); return nullptr; } } @@ -2458,9 +2373,8 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc, const uint32_t size = *alloc->size.get(); std::shared_ptr<uint8_t> buffer(new uint8_t[size]); if (!buffer) { - if (log) - log->Printf("%s - couldn't allocate a %" PRIu32 " byte buffer", - __FUNCTION__, size); + LLDB_LOGF(log, "%s - couldn't allocate a %" PRIu32 " byte buffer", + __FUNCTION__, size); return nullptr; } @@ -2469,10 +2383,10 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc, lldb::addr_t data_ptr = *alloc->data_ptr.get(); GetProcess()->ReadMemory(data_ptr, buffer.get(), size, err); if (err.Fail()) { - if (log) - log->Printf("%s - '%s' Couldn't read %" PRIu32 - " bytes of allocation data from 0x%" PRIx64, - __FUNCTION__, err.AsCString(), size, data_ptr); + LLDB_LOGF(log, + "%s - '%s' Couldn't read %" PRIu32 + " bytes of allocation data from 0x%" PRIx64, + __FUNCTION__, err.AsCString(), size, data_ptr); return nullptr; } @@ -2493,19 +2407,16 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, if (!alloc) return false; - if (log) - log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, - *alloc->address.get()); + LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__, + *alloc->address.get()); // JIT all the allocation details if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info.", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", + __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { - if (log) - log->Printf("%s - couldn't JIT allocation details", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__); return false; } } @@ -2559,9 +2470,8 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, sizeof(AllocationDetails::FileHeader), sizeof(AllocationDetails::ElementHeader)); - if (log) - log->Printf("%s - header type %" PRIu32 ", element size %" PRIu32, - __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size); + LLDB_LOGF(log, "%s - header type %" PRIu32 ", element size %" PRIu32, + __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size); // Check if the target allocation and file both have the same number of bytes // for an Element @@ -2717,19 +2627,16 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, if (!alloc) return false; - if (log) - log->Printf("%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, - *alloc->address.get()); + LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, + *alloc->address.get()); // JIT all the allocation details if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info.", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", + __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { - if (log) - log->Printf("%s - couldn't JIT allocation details.", __FUNCTION__); + LLDB_LOGF(log, "%s - couldn't JIT allocation details.", __FUNCTION__); return false; } } @@ -2743,14 +2650,14 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Check we can create writable file FileSpec file_spec(path); FileSystem::Instance().Resolve(file_spec); - File file; - FileSystem::Instance().Open(file, file_spec, - File::eOpenOptionWrite | - File::eOpenOptionCanCreate | - File::eOpenOptionTruncate); + auto file = FileSystem::Instance().Open( + file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionTruncate); if (!file) { - strm.Printf("Error: Failed to open '%s' for writing", path); + std::string error = llvm::toString(file.takeError()); + strm.Printf("Error: Failed to open '%s' for writing: %s", path, + error.c_str()); strm.EOL(); return false; } @@ -2779,11 +2686,10 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Write the file header size_t num_bytes = sizeof(AllocationDetails::FileHeader); - if (log) - log->Printf("%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, - (uint64_t)num_bytes); + LLDB_LOGF(log, "%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, + (uint64_t)num_bytes); - Status err = file.Write(&head, num_bytes); + Status err = file.get()->Write(&head, num_bytes); if (!err.Success()) { strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); strm.EOL(); @@ -2805,11 +2711,10 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Write headers for allocation element type to file num_bytes = element_header_size; - if (log) - log->Printf("%s - writing element headers, 0x%" PRIx64 " bytes.", - __FUNCTION__, (uint64_t)num_bytes); + LLDB_LOGF(log, "%s - writing element headers, 0x%" PRIx64 " bytes.", + __FUNCTION__, (uint64_t)num_bytes); - err = file.Write(element_header_buffer.get(), num_bytes); + err = file.get()->Write(element_header_buffer.get(), num_bytes); if (!err.Success()) { strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); strm.EOL(); @@ -2818,11 +2723,10 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, // Write allocation data to file num_bytes = static_cast<size_t>(*alloc->size.get()); - if (log) - log->Printf("%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, - (uint64_t)num_bytes); + LLDB_LOGF(log, "%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, + (uint64_t)num_bytes); - err = file.Write(buffer.get(), num_bytes); + err = file.get()->Write(buffer.get(), num_bytes); if (!err.Success()) { strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); strm.EOL(); @@ -2894,17 +2798,17 @@ bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) { addr_t addr = debug_present->GetLoadAddress(&target); GetProcess()->WriteMemory(addr, &flag, sizeof(flag), err); if (err.Success()) { - if (log) - log->Printf("%s - debugger present flag set on debugee.", - __FUNCTION__); + LLDB_LOGF(log, "%s - debugger present flag set on debugee.", + __FUNCTION__); m_debuggerPresentFlagged = true; } else if (log) { - log->Printf("%s - error writing debugger present flags '%s' ", - __FUNCTION__, err.AsCString()); + LLDB_LOGF(log, "%s - error writing debugger present flags '%s' ", + __FUNCTION__, err.AsCString()); } } else if (log) { - log->Printf( + LLDB_LOGF( + log, "%s - error writing debugger present flags - symbol not found", __FUNCTION__); } @@ -3004,8 +2908,7 @@ bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines, return false; } - if (log) - log->Printf("Found RenderScript reduction '%s'", spec[2].str().c_str()); + LLDB_LOGF(log, "Found RenderScript reduction '%s'", spec[2].str().c_str()); m_reductions.push_back(RSReductionDescriptor(this, sig, accum_data_size, spec[2], spec[3], spec[4], @@ -3082,10 +2985,8 @@ bool RSModuleDescriptor::ParseRSInfo() { { const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes()); raw_rs_info.split(info_lines, '\n'); - if (log) - log->Printf("'.rs.info symbol for '%s':\n%s", - m_module->GetFileSpec().GetCString(), - raw_rs_info.str().c_str()); + LLDB_LOGF(log, "'.rs.info symbol for '%s':\n%s", + m_module->GetFileSpec().GetCString(), raw_rs_info.str().c_str()); } enum { @@ -3153,9 +3054,8 @@ bool RSModuleDescriptor::ParseRSInfo() { success = ParseVersionInfo(line, n_lines); break; default: { - if (log) - log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__, - line->str().c_str()); + LLDB_LOGF(log, "%s - skipping .rs.info field '%s'", __FUNCTION__, + line->str().c_str()); continue; } } @@ -3276,15 +3176,13 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, if (!alloc) return false; // FindAllocByID() will print error message for us here - if (log) - log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, - *alloc->address.get()); + LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__, + *alloc->address.get()); // Check we have information about the allocation, if not calculate it if (alloc->ShouldRefresh()) { - if (log) - log->Printf("%s - allocation details not calculated yet, jitting info.", - __FUNCTION__); + LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", + __FUNCTION__); // JIT all the allocation information if (!RefreshAllocation(alloc, frame_ptr)) { @@ -3313,9 +3211,8 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t data_size = *alloc->element.datum_size.get(); - if (log) - log->Printf("%s - element size %" PRIu32 " bytes, including padding", - __FUNCTION__, data_size); + LLDB_LOGF(log, "%s - element size %" PRIu32 " bytes, including padding", + __FUNCTION__, data_size); // Allocate a buffer to copy data into std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); @@ -3340,10 +3237,10 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t size = *alloc->size.get(); // Size of whole allocation const uint32_t padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0; - if (log) - log->Printf("%s - stride %" PRIu32 " bytes, size %" PRIu32 - " bytes, padding %" PRIu32, - __FUNCTION__, stride, size, padding); + LLDB_LOGF(log, + "%s - stride %" PRIu32 " bytes, size %" PRIu32 + " bytes, padding %" PRIu32, + __FUNCTION__, stride, size, padding); // Find dimensions used to index loops, so need to be non-zero uint32_t dim_x = alloc->dimension.get()->dim_1; @@ -3395,8 +3292,7 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, *alloc->data_ptr.get() + offset); if (written < 0 || written >= jit_max_expr_size) { - if (log) - log->Printf("%s - error in snprintf().", __FUNCTION__); + LLDB_LOGF(log, "%s - error in snprintf().", __FUNCTION__); continue; } @@ -3573,17 +3469,16 @@ void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) { for (const auto &module : m_rsmodules) BreakOnModuleKernels(module); - if (log) - log->Printf("%s(True) - breakpoints set on all currently loaded kernels.", - __FUNCTION__); + LLDB_LOGF(log, + "%s(True) - breakpoints set on all currently loaded kernels.", + __FUNCTION__); } else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels. { m_breakAllKernels = false; - if (log) - log->Printf("%s(False) - breakpoints no longer automatically set.", - __FUNCTION__); + LLDB_LOGF(log, "%s(False) - breakpoints no longer automatically set.", + __FUNCTION__); } } @@ -3595,8 +3490,8 @@ RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) { GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); if (!m_filtersp) { - if (log) - log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__); + LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", + __FUNCTION__); return nullptr; } @@ -3610,9 +3505,8 @@ RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) { Status err; target.AddNameToBreakpoint(bp, "RenderScriptKernel", err); if (err.Fail() && log) - if (log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); return bp; } @@ -3624,8 +3518,8 @@ RenderScriptRuntime::CreateReductionBreakpoint(ConstString name, GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); if (!m_filtersp) { - if (log) - log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__); + LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", + __FUNCTION__); return nullptr; } @@ -3640,8 +3534,8 @@ RenderScriptRuntime::CreateReductionBreakpoint(ConstString name, Status err; target.AddNameToBreakpoint(bp, "RenderScriptReduction", err); if (err.Fail() && log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); return bp; } @@ -3663,9 +3557,8 @@ bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, var_sp, err)); if (!err.Success()) { - if (log) - log->Printf("%s - error, couldn't find '%s' in frame", __FUNCTION__, - var_name); + LLDB_LOGF(log, "%s - error, couldn't find '%s' in frame", __FUNCTION__, + var_name); return false; } @@ -3673,9 +3566,8 @@ bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, bool success = false; val = value_sp->GetValueAsUnsigned(0, &success); if (!success) { - if (log) - log->Printf("%s - error, couldn't parse '%s' as an uint32_t.", - __FUNCTION__, var_name); + LLDB_LOGF(log, "%s - error, couldn't parse '%s' as an uint32_t.", + __FUNCTION__, var_name); return false; } @@ -3695,8 +3587,7 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!thread_ptr) { - if (log) - log->Printf("%s - Error, No thread pointer", __FUNCTION__); + LLDB_LOGF(log, "%s - Error, No thread pointer", __FUNCTION__); return false; } @@ -3718,17 +3609,15 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, if (!func_name) continue; - if (log) - log->Printf("%s - Inspecting function '%s'", __FUNCTION__, - func_name.GetCString()); + LLDB_LOGF(log, "%s - Inspecting function '%s'", __FUNCTION__, + func_name.GetCString()); // Check if function name has .expand suffix if (!func_name.GetStringRef().endswith(".expand")) continue; - if (log) - log->Printf("%s - Found .expand function '%s'", __FUNCTION__, - func_name.GetCString()); + LLDB_LOGF(log, "%s - Found .expand function '%s'", __FUNCTION__, + func_name.GetCString()); // Get values for variables in .expand frame that tell us the current // kernel invocation @@ -3770,9 +3659,8 @@ bool RenderScriptRuntime::KernelBreakpointHit(void *baton, // Coordinate we want to stop on RSCoordinate target_coord = *static_cast<RSCoordinate *>(baton); - if (log) - log->Printf("%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__, break_id, - target_coord.x, target_coord.y, target_coord.z); + LLDB_LOGF(log, "%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__, + break_id, target_coord.x, target_coord.y, target_coord.z); // Select current thread ExecutionContext context(ctx->exe_ctx_ref); @@ -3782,22 +3670,19 @@ bool RenderScriptRuntime::KernelBreakpointHit(void *baton, // Find current kernel invocation from .expand frame variables RSCoordinate current_coord{}; if (!GetKernelCoordinate(current_coord, thread_ptr)) { - if (log) - log->Printf("%s - Error, couldn't select .expand stack frame", - __FUNCTION__); + LLDB_LOGF(log, "%s - Error, couldn't select .expand stack frame", + __FUNCTION__); return false; } - if (log) - log->Printf("%s - " FMT_COORD, __FUNCTION__, current_coord.x, - current_coord.y, current_coord.z); + LLDB_LOGF(log, "%s - " FMT_COORD, __FUNCTION__, current_coord.x, + current_coord.y, current_coord.z); // Check if the current kernel invocation coordinate matches our target // coordinate if (target_coord == current_coord) { - if (log) - log->Printf("%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x, - current_coord.y, current_coord.z); + LLDB_LOGF(log, "%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x, + current_coord.y, current_coord.z); BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id); @@ -3865,8 +3750,8 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name, GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); if (!m_filtersp) { - if (log) - log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__); + LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", + __FUNCTION__); return nullptr; } @@ -3880,8 +3765,8 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name, Status err; target.AddNameToBreakpoint(bp, name.GetCString(), err); if (err.Fail() && log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); // ask the breakpoint to resolve itself bp->ResolveBreakpoint(); return bp; @@ -3964,9 +3849,8 @@ RenderScriptRuntime::CreateAllocation(addr_t address) { auto it = m_allocations.begin(); while (it != m_allocations.end()) { if (*((*it)->address) == address) { - if (log) - log->Printf("%s - Removing allocation id: %d, address: 0x%" PRIx64, - __FUNCTION__, (*it)->id, address); + LLDB_LOGF(log, "%s - Removing allocation id: %d, address: 0x%" PRIx64, + __FUNCTION__, (*it)->id, address); it = m_allocations.erase(it); } else { @@ -3988,9 +3872,8 @@ bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr, Address resolved; // RenderScript module if (!target.GetSectionLoadList().ResolveLoadAddress(kernel_addr, resolved)) { - if (log) - log->Printf("%s: unable to resolve 0x%" PRIx64 " to a loaded symbol", - __FUNCTION__, kernel_addr); + LLDB_LOGF(log, "%s: unable to resolve 0x%" PRIx64 " to a loaded symbol", + __FUNCTION__, kernel_addr); return false; } @@ -4000,9 +3883,8 @@ bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr, name = sym->GetName(); assert(IsRenderScriptModule(resolved.CalculateSymbolContextModule())); - if (log) - log->Printf("%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__, - kernel_addr, name.GetCString()); + LLDB_LOGF(log, "%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__, + kernel_addr, name.GetCString()); return true; } @@ -4256,13 +4138,12 @@ public: // Matching a comma separated list of known words is fairly // straightforward with PCRE, but we're using ERE, so we end up with a // little ugliness... - RegularExpression::Match match(/* max_matches */ 5); RegularExpression match_type_list( llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$")); assert(match_type_list.IsValid()); - if (!match_type_list.Execute(option_val, &match)) { + if (!match_type_list.Execute(option_val)) { err_str.PutCString( "a comma-separated list of kernel types is required"); return false; @@ -4696,32 +4577,36 @@ public: return false; } - Stream *output_strm = nullptr; - StreamFile outfile_stream; + Stream *output_stream_p = nullptr; + std::unique_ptr<Stream> output_stream_storage; + const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead if (outfile_spec) { // Open output file std::string path = outfile_spec.GetPath(); - auto error = FileSystem::Instance().Open( - outfile_stream.GetFile(), outfile_spec, - File::eOpenOptionWrite | File::eOpenOptionCanCreate); - if (error.Success()) { - output_strm = &outfile_stream; + auto file = FileSystem::Instance().Open( + outfile_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate); + if (file) { + output_stream_storage = + std::make_unique<StreamFile>(std::move(file.get())); + output_stream_p = output_stream_storage.get(); result.GetOutputStream().Printf("Results written to '%s'", path.c_str()); result.GetOutputStream().EOL(); } else { - result.AppendErrorWithFormat("Couldn't open file '%s'", path.c_str()); + 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 - output_strm = &result.GetOutputStream(); + output_stream_p = &result.GetOutputStream(); - assert(output_strm != nullptr); + assert(output_stream_p != nullptr); bool dumped = - runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id); + runtime->DumpAllocation(*output_stream_p, m_exe_ctx.GetFramePtr(), id); if (dumped) result.SetStatus(eReturnStatusSuccessFinishResult); diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 3923221d4302..c3740ba55a11 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -67,8 +67,8 @@ public: void Dump(Stream *s) const override {} Searcher::CallbackReturn SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) override; + SymbolContext &context, + Address *addr) override; lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } @@ -117,8 +117,8 @@ public: void Dump(Stream *s) const override {} Searcher::CallbackReturn SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) override; + SymbolContext &context, + Address *addr) override; lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } @@ -262,8 +262,8 @@ public: void Dump(Stream *s) const override {} Searcher::CallbackReturn SearchCallback(SearchFilter &filter, - SymbolContext &context, Address *addr, - bool containing) override; + SymbolContext &context, + Address *addr) override; lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; } diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp index 4725e8c5b0eb..a6d225d2fbd8 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp @@ -93,9 +93,8 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) { assert(orig && "CallInst has no called function"); llvm::FunctionType *orig_type = orig->getFunctionType(); auto name = orig->getName(); - if (log) - log->Printf("%s - cloning to StructRet function for '%s'", __FUNCTION__, - name.str().c_str()); + LLDB_LOGF(log, "%s - cloning to StructRet function for '%s'", __FUNCTION__, + name.str().c_str()); unsigned num_params = orig_type->getNumParams(); std::vector<llvm::Type *> new_params{num_params + 1, nullptr}; @@ -113,9 +112,9 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) { if (!return_type_ptr_type) return nullptr; - if (log) - log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n", - __FUNCTION__, (void *)return_type_ptr_type); + LLDB_LOGF(log, + "%s - return type pointer type for StructRet clone @ '0x%p':\n", + __FUNCTION__, (void *)return_type_ptr_type); // put the sret pointer argument in place at the beginning of the // argument list. params.emplace(params.begin(), return_type_ptr_type); diff --git a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp index d489eaf11115..de17d986a860 100644 --- a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp +++ b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp @@ -16,7 +16,19 @@ using namespace lldb_private; using namespace lldb_private::breakpad; namespace { -enum class Token { Unknown, Module, Info, CodeID, File, Func, Public, Stack, CFI, Init }; +enum class Token { + Unknown, + Module, + Info, + CodeID, + File, + Func, + Public, + Stack, + CFI, + Init, + Win, +}; } template<typename T> @@ -33,6 +45,7 @@ template <> Token stringTo<Token>(llvm::StringRef Str) { .Case("STACK", Token::Stack) .Case("CFI", Token::CFI) .Case("INIT", Token::Init) + .Case("WIN", Token::Win) .Default(Token::Unknown); } @@ -127,6 +140,8 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) { switch (Tok) { case Token::CFI: return Record::StackCFI; + case Token::Win: + return Record::StackWin; default: return llvm::None; } @@ -134,13 +149,13 @@ llvm::Optional<Record::Kind> Record::classify(llvm::StringRef Line) { case Token::Unknown: // Optimistically assume that any unrecognised token means this is a line // record, those don't have a special keyword and start directly with a - // hex number. CODE_ID should never be at the start of a line, but if it - // is, it can be treated the same way as a garbled line record. + // hex number. return Record::Line; case Token::CodeID: case Token::CFI: case Token::Init: + case Token::Win: // These should never appear at the start of a valid record. return llvm::None; } @@ -390,6 +405,81 @@ llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, return OS << " " << R.UnwindRules; } +llvm::Optional<StackWinRecord> StackWinRecord::parse(llvm::StringRef Line) { + // STACK WIN type rva code_size prologue_size epilogue_size parameter_size + // saved_register_size local_size max_stack_size has_program_string + // program_string_OR_allocates_base_pointer + + if (consume<Token>(Line) != Token::Stack) + return llvm::None; + if (consume<Token>(Line) != Token::Win) + return llvm::None; + + llvm::StringRef Str; + uint8_t Type; + std::tie(Str, Line) = getToken(Line); + // Right now we only support the "FrameData" frame type. + if (!to_integer(Str, Type) || FrameType(Type) != FrameType::FrameData) + return llvm::None; + + lldb::addr_t RVA; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, RVA, 16)) + return llvm::None; + + lldb::addr_t CodeSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, CodeSize, 16)) + return llvm::None; + + // Skip fields which we aren't using right now. + std::tie(Str, Line) = getToken(Line); // prologue_size + std::tie(Str, Line) = getToken(Line); // epilogue_size + + lldb::addr_t ParameterSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, ParameterSize, 16)) + return llvm::None; + + lldb::addr_t SavedRegisterSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, SavedRegisterSize, 16)) + return llvm::None; + + lldb::addr_t LocalSize; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, LocalSize, 16)) + return llvm::None; + + std::tie(Str, Line) = getToken(Line); // max_stack_size + + uint8_t HasProgramString; + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, HasProgramString)) + return llvm::None; + // FrameData records should always have a program string. + if (!HasProgramString) + return llvm::None; + + return StackWinRecord(RVA, CodeSize, ParameterSize, SavedRegisterSize, + LocalSize, Line.trim()); +} + +bool breakpad::operator==(const StackWinRecord &L, const StackWinRecord &R) { + return L.RVA == R.RVA && L.CodeSize == R.CodeSize && + L.ParameterSize == R.ParameterSize && + L.SavedRegisterSize == R.SavedRegisterSize && + L.LocalSize == R.LocalSize && L.ProgramString == R.ProgramString; +} + +llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, + const StackWinRecord &R) { + return OS << llvm::formatv( + "STACK WIN 4 {0:x-} {1:x-} ? ? {2} {3} {4} ? 1 {5}", R.RVA, + R.CodeSize, R.ParameterSize, R.SavedRegisterSize, R.LocalSize, + R.ProgramString); +} + llvm::StringRef breakpad::toString(Record::Kind K) { switch (K) { case Record::Module: @@ -406,6 +496,8 @@ llvm::StringRef breakpad::toString(Record::Kind K) { return "PUBLIC"; case Record::StackCFI: return "STACK CFI"; + case Record::StackWin: + return "STACK WIN"; } llvm_unreachable("Unknown record kind!"); } diff --git a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h index 5d5cdb319c10..27bef975125d 100644 --- a/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h +++ b/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h @@ -20,7 +20,7 @@ namespace breakpad { class Record { public: - enum Kind { Module, Info, File, Func, Line, Public, StackCFI }; + enum Kind { Module, Info, File, Func, Line, Public, StackCFI, StackWin }; /// Attempt to guess the kind of the record present in the argument without /// doing a full parse. The returned kind will always be correct for valid @@ -157,6 +157,29 @@ public: bool operator==(const StackCFIRecord &L, const StackCFIRecord &R); llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StackCFIRecord &R); +class StackWinRecord : public Record { +public: + static llvm::Optional<StackWinRecord> parse(llvm::StringRef Line); + + StackWinRecord(lldb::addr_t RVA, lldb::addr_t CodeSize, + lldb::addr_t ParameterSize, lldb::addr_t SavedRegisterSize, + lldb::addr_t LocalSize, llvm::StringRef ProgramString) + : Record(StackWin), RVA(RVA), CodeSize(CodeSize), + ParameterSize(ParameterSize), SavedRegisterSize(SavedRegisterSize), + LocalSize(LocalSize), ProgramString(ProgramString) {} + + enum class FrameType : uint8_t { FPO = 0, FrameData = 4 }; + lldb::addr_t RVA; + lldb::addr_t CodeSize; + lldb::addr_t ParameterSize; + lldb::addr_t SavedRegisterSize; + lldb::addr_t LocalSize; + llvm::StringRef ProgramString; +}; + +bool operator==(const StackWinRecord &L, const StackWinRecord &R); +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StackWinRecord &R); + } // namespace breakpad } // namespace lldb_private diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp index 60dd9f9cecf0..3b9e0e2092a9 100644 --- a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp +++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp @@ -42,6 +42,8 @@ llvm::Optional<Header> Header::parse(llvm::StringRef text) { return Header{ArchSpec(triple), std::move(uuid)}; } +char ObjectFileBreakpad::ID; + void ObjectFileBreakpad::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, @@ -125,7 +127,7 @@ Symtab *ObjectFileBreakpad::GetSymtab() { void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) { if (m_sections_up) return; - m_sections_up = llvm::make_unique<SectionList>(); + m_sections_up = std::make_unique<SectionList>(); llvm::Optional<Record::Kind> current_section; offset_t section_start; diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h index e8885e0cc898..cb4bba01fb71 100644 --- a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h +++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h @@ -48,6 +48,13 @@ public: uint32_t GetPluginVersion() override { return 1; } + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + // ObjectFile Protocol. bool ParseHeader() override; @@ -78,8 +85,6 @@ public: UUID GetUUID() override { return m_uuid; } - FileSpecList GetDebugSymbolFilePaths() override { return FileSpecList(); } - uint32_t GetDependentModules(FileSpecList &files) override { return 0; } Type CalculateType() override { return eTypeDebugInfo; } diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index d62afa34bbe8..3f8502548fc2 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/LZMA.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/SectionLoadList.h" @@ -29,12 +30,13 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" - #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/Decompressor.h" #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/CRC.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MipsABIFlags.h" @@ -80,41 +82,6 @@ const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00; const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01; const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02; -// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants -#define NT_PRSTATUS 1 -#define NT_PRFPREG 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 -#define NT_AUXV 6 -#define NT_SIGINFO 0x53494749 -#define NT_FILE 0x46494c45 -#define NT_PRXFPREG 0x46e62b7f -#define NT_PPC_VMX 0x100 -#define NT_PPC_SPE 0x101 -#define NT_PPC_VSX 0x102 -#define NT_386_TLS 0x200 -#define NT_386_IOPERM 0x201 -#define NT_X86_XSTATE 0x202 -#define NT_S390_HIGH_GPRS 0x300 -#define NT_S390_TIMER 0x301 -#define NT_S390_TODCMP 0x302 -#define NT_S390_TODPREG 0x303 -#define NT_S390_CTRS 0x304 -#define NT_S390_PREFIX 0x305 -#define NT_S390_LAST_BREAK 0x306 -#define NT_S390_SYSTEM_CALL 0x307 -#define NT_S390_TDB 0x308 -#define NT_S390_VXRS_LOW 0x309 -#define NT_S390_VXRS_HIGH 0x30a -#define NT_ARM_VFP 0x400 -#define NT_ARM_TLS 0x401 -#define NT_ARM_HW_BREAK 0x402 -#define NT_ARM_HW_WATCH 0x403 -#define NT_ARM_SYSTEM_CALL 0x404 -#define NT_METAG_CBUF 0x500 -#define NT_METAG_RPIPE 0x501 -#define NT_METAG_TLS 0x502 - //===----------------------------------------------------------------------===// /// \class ELFRelocation /// Generic wrapper for ELFRel and ELFRela. @@ -264,8 +231,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) { const char *cstr = data.GetCStr(offset, llvm::alignTo(n_namesz, 4)); if (cstr == nullptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); - if (log) - log->Printf("Failed to parse note name lacking nul terminator"); + LLDB_LOGF(log, "Failed to parse note name lacking nul terminator"); return false; } @@ -333,6 +299,8 @@ static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) { return LLDB_INVALID_CPUTYPE; } +char ObjectFileELF::ID; + // Arbitrary constant used as UUID prefix for core files. const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C); @@ -429,67 +397,9 @@ bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp, return false; } -/* - * crc function from http://svnweb.freebsd.org/base/head/sys/libkern/crc32.c - * - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - */ -static uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size) { - static const uint32_t g_crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; - const uint8_t *p = (const uint8_t *)buf; - - crc = crc ^ ~0U; - while (size--) - crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - return crc ^ ~0U; -} - -static uint32_t calc_gnu_debuglink_crc32(const void *buf, size_t size) { - return calc_crc32(0U, buf, size); +static uint32_t calc_crc32(uint32_t init, const DataExtractor &data) { + return llvm::crc32( + init, llvm::makeArrayRef(data.GetDataStart(), data.GetByteSize())); } uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32( @@ -509,8 +419,7 @@ uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32( break; } - core_notes_crc = calc_crc32(core_notes_crc, segment_data.GetDataStart(), - segment_data.GetByteSize()); + core_notes_crc = calc_crc32(core_notes_crc, segment_data); } } @@ -608,10 +517,9 @@ size_t ObjectFileELF::GetModuleSpecifications( llvm::Triple::OSType spec_ostype = spec.GetArchitecture().GetTriple().getOS(); - if (log) - log->Printf("ObjectFileELF::%s file '%s' module OSABI: %s", - __FUNCTION__, file.GetPath().c_str(), - OSABIAsCString(header.e_ident[EI_OSABI])); + LLDB_LOGF(log, "ObjectFileELF::%s file '%s' module OSABI: %s", + __FUNCTION__, file.GetPath().c_str(), + OSABIAsCString(header.e_ident[EI_OSABI])); // SetArchitecture should have set the vendor to unknown vendor = spec.GetArchitecture().GetTriple().getVendor(); @@ -623,10 +531,10 @@ size_t ObjectFileELF::GetModuleSpecifications( GetOsFromOSABI(header.e_ident[EI_OSABI], ostype); assert(spec_ostype == ostype); if (spec_ostype != llvm::Triple::OSType::UnknownOS) { - if (log) - log->Printf("ObjectFileELF::%s file '%s' set ELF module OS type " - "from ELF header OSABI.", - __FUNCTION__, file.GetPath().c_str()); + LLDB_LOGF(log, + "ObjectFileELF::%s file '%s' set ELF module OS type " + "from ELF header OSABI.", + __FUNCTION__, file.GetPath().c_str()); } data_sp = MapFileData(file, -1, file_offset); @@ -652,12 +560,12 @@ size_t ObjectFileELF::GetModuleSpecifications( llvm::Triple &spec_triple = spec.GetArchitecture().GetTriple(); - if (log) - log->Printf("ObjectFileELF::%s file '%s' module set to triple: %s " - "(architecture %s)", - __FUNCTION__, file.GetPath().c_str(), - spec_triple.getTriple().c_str(), - spec.GetArchitecture().GetArchitectureName()); + LLDB_LOGF(log, + "ObjectFileELF::%s file '%s' module set to triple: %s " + "(architecture %s)", + __FUNCTION__, file.GetPath().c_str(), + spec_triple.getTriple().c_str(), + spec.GetArchitecture().GetArchitectureName()); if (!uuid.IsValid()) { uint32_t core_notes_crc = 0; @@ -682,8 +590,7 @@ size_t ObjectFileELF::GetModuleSpecifications( core_notes_crc = CalculateELFNotesSegmentsCRC32(program_headers, data); } else { - gnu_debuglink_crc = calc_gnu_debuglink_crc32( - data.GetDataStart(), data.GetByteSize()); + gnu_debuglink_crc = calc_crc32(0, data); } } using u32le = llvm::support::ulittle32_t; @@ -721,27 +628,16 @@ ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length) - : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), - m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0), - m_program_headers(), m_section_headers(), m_dynamic_symbols(), - m_filespec_up(), m_entry_point_address(), m_arch_spec() { + : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset) { if (file) m_file = *file; - ::memset(&m_header, 0, sizeof(m_header)); } ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp, DataBufferSP &header_data_sp, const lldb::ProcessSP &process_sp, addr_t header_addr) - : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), - m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0), - m_program_headers(), m_section_headers(), m_dynamic_symbols(), - m_filespec_up(), m_entry_point_address(), m_arch_spec() { - ::memset(&m_header, 0, sizeof(m_header)); -} - -ObjectFileELF::~ObjectFileELF() {} + : ObjectFile(module_sp, process_sp, header_addr, header_data_sp) {} bool ObjectFileELF::IsExecutable() const { return ((m_header.e_type & ET_EXEC) != 0) || (m_header.e_entry != 0); @@ -872,8 +768,7 @@ UUID ObjectFileELF::GetUUID() { } } else { if (!m_gnu_debuglink_crc) - m_gnu_debuglink_crc = calc_gnu_debuglink_crc32(m_data.GetDataStart(), - m_data.GetByteSize()); + m_gnu_debuglink_crc = calc_crc32(0, m_data); if (m_gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. u32le data(m_gnu_debuglink_crc); @@ -885,14 +780,10 @@ UUID ObjectFileELF::GetUUID() { return m_uuid; } -lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() { - FileSpecList file_spec_list; - - if (!m_gnu_debuglink_file.empty()) { - FileSpec file_spec(m_gnu_debuglink_file); - file_spec_list.Append(file_spec); - } - return file_spec_list; +llvm::Optional<FileSpec> ObjectFileELF::GetDebugLink() { + if (m_gnu_debuglink_file.empty()) + return llvm::None; + return FileSpec(m_gnu_debuglink_file); } uint32_t ObjectFileELF::GetDependentModules(FileSpecList &files) { @@ -1120,9 +1011,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, return error; } - if (log) - log->Printf("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, - __FUNCTION__, note.n_name.c_str(), note.n_type); + LLDB_LOGF(log, "ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, + __FUNCTION__, note.n_name.c_str(), note.n_type); // Process FreeBSD ELF notes. if ((note.n_name == LLDB_NT_OWNER_FREEBSD) && @@ -1147,11 +1037,11 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, arch_spec.GetTriple().setOSName(os_name); arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf("ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 - ".%" PRIu32, - __FUNCTION__, version_major, version_minor, - static_cast<uint32_t>(version_info % 1000)); + LLDB_LOGF(log, + "ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 + ".%" PRIu32, + __FUNCTION__, version_major, version_minor, + static_cast<uint32_t>(version_info % 1000)); } // Process GNU ELF notes. else if (note.n_name == LLDB_NT_OWNER_GNU) { @@ -1172,12 +1062,11 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); arch_spec.GetTriple().setVendor( llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf( - "ObjectFileELF::%s detected Linux, min version %" PRIu32 - ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[1], version_info[2], - version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s detected Linux, min version %" PRIu32 + ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[1], version_info[2], + version_info[3]); // FIXME we have the minimal version number, we could be propagating // that. version_info[1] = OS Major, version_info[2] = OS Minor, // version_info[3] = Revision. @@ -1186,30 +1075,28 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS); arch_spec.GetTriple().setVendor( llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf("ObjectFileELF::%s detected Hurd (unsupported), min " - "version %" PRIu32 ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[1], version_info[2], - version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s detected Hurd (unsupported), min " + "version %" PRIu32 ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[1], version_info[2], + version_info[3]); break; case LLDB_NT_GNU_ABI_OS_SOLARIS: arch_spec.GetTriple().setOS(llvm::Triple::OSType::Solaris); arch_spec.GetTriple().setVendor( llvm::Triple::VendorType::UnknownVendor); - if (log) - log->Printf( - "ObjectFileELF::%s detected Solaris, min version %" PRIu32 - ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[1], version_info[2], - version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s detected Solaris, min version %" PRIu32 + ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[1], version_info[2], + version_info[3]); break; default: - if (log) - log->Printf( - "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 - ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, - __FUNCTION__, version_info[0], version_info[1], - version_info[2], version_info[3]); + LLDB_LOGF(log, + "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 + ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, + __FUNCTION__, version_info[0], version_info[1], + version_info[2], version_info[3]); break; } } @@ -1618,9 +1505,8 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, section_size) == section_size)) { Status error = RefineModuleDetailsFromNote(data, arch_spec, uuid); if (error.Fail()) { - if (log) - log->Printf("ObjectFileELF::%s ELF note processing failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "ObjectFileELF::%s ELF note processing failed: %s", + __FUNCTION__, error.AsCString()); } } } @@ -1790,6 +1676,8 @@ class VMAddressProvider { VMMap Segments = VMMap(Alloc); VMMap Sections = VMMap(Alloc); lldb_private::Log *Log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); + size_t SegmentCount = 0; + std::string SegmentName; VMRange GetVMRange(const ELFSectionHeader &H) { addr_t Address = H.sh_addr; @@ -1804,18 +1692,23 @@ class VMAddressProvider { } public: - VMAddressProvider(ObjectFile::Type Type) : ObjectType(Type) {} + VMAddressProvider(ObjectFile::Type Type, llvm::StringRef SegmentName) + : ObjectType(Type), SegmentName(SegmentName) {} + + std::string GetNextSegmentName() const { + return llvm::formatv("{0}[{1}]", SegmentName, SegmentCount).str(); + } llvm::Optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) { if (H.p_memsz == 0) { - LLDB_LOG(Log, - "Ignoring zero-sized PT_LOAD segment. Corrupt object file?"); + LLDB_LOG(Log, "Ignoring zero-sized {0} segment. Corrupt object file?", + SegmentName); return llvm::None; } if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) { - LLDB_LOG(Log, - "Ignoring overlapping PT_LOAD segment. Corrupt object file?"); + LLDB_LOG(Log, "Ignoring overlapping {0} segment. Corrupt object file?", + SegmentName); return llvm::None; } return VMRange(H.p_vaddr, H.p_memsz); @@ -1850,6 +1743,7 @@ public: void AddSegment(const VMRange &Range, SectionSP Seg) { Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg)); + ++SegmentCount; } void AddSection(SectionAddressInfo Info, SectionSP Sect) { @@ -1867,29 +1761,32 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { if (m_sections_up) return; - m_sections_up = llvm::make_unique<SectionList>(); - VMAddressProvider address_provider(GetType()); + m_sections_up = std::make_unique<SectionList>(); + VMAddressProvider regular_provider(GetType(), "PT_LOAD"); + VMAddressProvider tls_provider(GetType(), "PT_TLS"); - size_t LoadID = 0; for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) { const ELFProgramHeader &PHdr = EnumPHdr.value(); - if (PHdr.p_type != PT_LOAD) + if (PHdr.p_type != PT_LOAD && PHdr.p_type != PT_TLS) continue; - auto InfoOr = address_provider.GetAddressInfo(PHdr); + VMAddressProvider &provider = + PHdr.p_type == PT_TLS ? tls_provider : regular_provider; + auto InfoOr = provider.GetAddressInfo(PHdr); if (!InfoOr) continue; - ConstString Name(("PT_LOAD[" + llvm::Twine(LoadID++) + "]").str()); uint32_t Log2Align = llvm::Log2_64(std::max<elf_xword>(PHdr.p_align, 1)); SectionSP Segment = std::make_shared<Section>( - GetModule(), this, SegmentID(EnumPHdr.index()), Name, - eSectionTypeContainer, InfoOr->GetRangeBase(), InfoOr->GetByteSize(), - PHdr.p_offset, PHdr.p_filesz, Log2Align, /*flags*/ 0); + GetModule(), this, SegmentID(EnumPHdr.index()), + ConstString(provider.GetNextSegmentName()), eSectionTypeContainer, + InfoOr->GetRangeBase(), InfoOr->GetByteSize(), PHdr.p_offset, + PHdr.p_filesz, Log2Align, /*flags*/ 0); Segment->SetPermissions(GetPermissions(PHdr)); + Segment->SetIsThreadSpecific(PHdr.p_type == PT_TLS); m_sections_up->AddSection(Segment); - address_provider.AddSegment(*InfoOr, std::move(Segment)); + provider.AddSegment(*InfoOr, std::move(Segment)); } ParseSectionHeaders(); @@ -1904,7 +1801,9 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { const uint64_t file_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size; - auto InfoOr = address_provider.GetAddressInfo(header); + VMAddressProvider &provider = + header.sh_flags & SHF_TLS ? tls_provider : regular_provider; + auto InfoOr = provider.GetAddressInfo(header); if (!InfoOr) continue; @@ -1935,13 +1834,77 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { section_sp->SetIsThreadSpecific(header.sh_flags & SHF_TLS); (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_up) .AddSection(section_sp); - address_provider.AddSection(std::move(*InfoOr), std::move(section_sp)); + provider.AddSection(std::move(*InfoOr), std::move(section_sp)); } // For eTypeDebugInfo files, the Symbol Vendor will take care of updating the // 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. + if (auto gdd_obj_file = GetGnuDebugDataObjectFile()) { + if (auto gdd_objfile_section_list = gdd_obj_file->GetSectionList()) { + if (SectionSP symtab_section_sp = + gdd_objfile_section_list->FindSectionByType( + eSectionTypeELFSymbolTable, true)) { + SectionSP module_section_sp = unified_section_list.FindSectionByType( + eSectionTypeELFSymbolTable, true); + if (module_section_sp) + unified_section_list.ReplaceSection(module_section_sp->GetID(), + symtab_section_sp); + else + unified_section_list.AddSection(symtab_section_sp); + } + } + } +} + +std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { + if (m_gnu_debug_data_object_file != nullptr) + return m_gnu_debug_data_object_file; + + SectionSP section = + GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata")); + if (!section) + return nullptr; + + if (!lldb_private::lzma::isAvailable()) { + GetModule()->ReportWarning( + "No LZMA support found for reading .gnu_debugdata section"); + return nullptr; + } + + // Uncompress the data + DataExtractor data; + section->GetSectionData(data); + llvm::SmallVector<uint8_t, 0> uncompressedData; + auto err = lldb_private::lzma::uncompress(data.GetData(), uncompressedData); + if (err) { + GetModule()->ReportWarning( + "An error occurred while decompression the section %s: %s", + section->GetName().AsCString(), llvm::toString(std::move(err)).c_str()); + return nullptr; + } + + // Construct ObjectFileELF object from decompressed buffer + DataBufferSP gdd_data_buf( + new DataBufferHeap(uncompressedData.data(), uncompressedData.size())); + auto fspec = GetFileSpec().CopyByAppendingPathComponent( + llvm::StringRef("gnu_debugdata")); + m_gnu_debug_data_object_file.reset(new ObjectFileELF( + GetModule(), gdd_data_buf, 0, &fspec, 0, gdd_data_buf->GetByteSize())); + + // This line is essential; otherwise a breakpoint can be set but not hit. + m_gnu_debug_data_object_file->SetType(ObjectFile::eTypeDebugInfo); + + 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; } // Find the arm/aarch64 mapping symbol character in the given symbol name. @@ -2246,8 +2209,6 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, bool is_global = symbol.getBinding() == STB_GLOBAL; uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags; - bool is_mangled = (symbol_name[0] == '_' && symbol_name[1] == 'Z'); - llvm::StringRef symbol_ref(symbol_name); // Symbol names may contain @VERSION suffixes. Find those and strip them @@ -2255,7 +2216,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, size_t version_pos = symbol_ref.find('@'); bool has_suffix = version_pos != llvm::StringRef::npos; llvm::StringRef symbol_bare = symbol_ref.substr(0, version_pos); - Mangled mangled(ConstString(symbol_bare), is_mangled); + Mangled mangled(symbol_bare); // Now append the suffix back to mangled and unmangled names. Only do it if // the demangling was successful (string is not empty). @@ -2486,14 +2447,11 @@ static unsigned ParsePLTRelocations( break; const char *symbol_name = strtab_data.PeekCStr(symbol.st_name); - bool is_mangled = - symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false; uint64_t plt_index = plt_offset + i * plt_entsize; Symbol jump_symbol( i + start_id, // Symbol table index symbol_name, // symbol name. - is_mangled, // is the symbol name mangled? eSymbolTypeTrampoline, // Type of this symbol false, // Is this globally visible? false, // Is this symbol debug info? @@ -2654,7 +2612,7 @@ unsigned ObjectFileELF::ApplyRelocations( ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); - log->Printf("Failed to apply debug info relocations"); + LLDB_LOGF(log, "Failed to apply debug info relocations"); break; } uint32_t truncated_addr = (value & 0xFFFFFFFF); @@ -2749,19 +2707,29 @@ Symtab *ObjectFileELF::GetSymtab() { // while the reverse is not necessarily true. Section *symtab = section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); - if (!symtab) { - // The symtab section is non-allocable and can be stripped, so if it - // doesn't exist then use the dynsym section which should always be - // there. - symtab = - section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) - .get(); - } if (symtab) { m_symtab_up.reset(new Symtab(symtab->GetObjectFile())); symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, symtab); } + // The symtab section is non-allocable and can be stripped, while the + // .dynsym section which should always be always be there. To support the + // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo + // section, nomatter if .symtab was already parsed or not. This is because + // minidebuginfo normally removes the .symtab symbols which have their + // matching .dynsym counterparts. + if (!symtab || + GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) { + Section *dynsym = + section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) + .get(); + if (dynsym) { + if (!m_symtab_up) + m_symtab_up.reset(new Symtab(dynsym->GetObjectFile())); + symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, dynsym); + } + } + // DT_JMPREL // If present, this entry's d_ptr member holds the address of // relocation @@ -2803,6 +2771,50 @@ Symtab *ObjectFileELF::GetSymtab() { if (m_symtab_up == nullptr) m_symtab_up.reset(new Symtab(this)); + // In the event that there's no symbol entry for the entry point we'll + // artifically create one. We delegate to the symtab object the figuring + // out of the proper size, this will usually make it span til the next + // symbol it finds in the section. This means that if there are missing + // symbols the entry point might span beyond its function definition. + // We're fine with this as it doesn't make it worse than not having a + // symbol entry at all. + if (CalculateType() == eTypeExecutable) { + ArchSpec arch = GetArchitecture(); + auto entry_point_addr = GetEntryPointAddress(); + bool is_valid_entry_point = + entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset(); + addr_t entry_point_file_addr = entry_point_addr.GetFileAddress(); + 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); + // 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)) + m_address_class_map[entry_point_file_addr ^ 1] = + AddressClass::eCodeAlternateISA; + else + m_address_class_map[entry_point_file_addr] = AddressClass::eCode; + } + } + m_symtab_up->CalculateSymbolSizes(); } @@ -2881,7 +2893,6 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, Symbol eh_symbol( symbol_id, // Symbol table index. symbol_name, // Symbol name. - false, // Is the symbol name mangled? eSymbolTypeCode, // Type of this symbol. true, // Is this globally visible? false, // Is this symbol debug info? diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index b63a5d14d4f5..3b273896cb59 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -56,8 +56,6 @@ struct ELFNote { /// the ObjectFile protocol. class ObjectFileELF : public lldb_private::ObjectFile { public: - ~ObjectFileELF() override; - // Static Functions static void Initialize(); @@ -91,6 +89,13 @@ public: uint32_t GetPluginVersion() override; + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + // ObjectFile Protocol. bool ParseHeader() override; @@ -117,7 +122,9 @@ public: lldb_private::UUID GetUUID() override; - lldb_private::FileSpecList GetDebugSymbolFilePaths() override; + /// Return the contents of the .gnu_debuglink section, if the object file + /// contains it. + llvm::Optional<lldb_private::FileSpec> GetDebugLink(); uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; @@ -190,7 +197,7 @@ private: /// ELF .gnu_debuglink file and crc data if available. std::string m_gnu_debuglink_file; - uint32_t m_gnu_debuglink_crc; + uint32_t m_gnu_debuglink_crc = 0; /// Collection of program headers. ProgramHeaderColl m_program_headers; @@ -201,6 +208,10 @@ private: /// Collection of symbols from the dynamic table. DynamicSymbolColl m_dynamic_symbols; + /// Object file parsed from .gnu_debugdata section (\sa + /// GetGnuDebugDataObjectFile()) + std::shared_ptr<ObjectFileELF> m_gnu_debug_data_object_file; + /// List of file specifications corresponding to the modules (shared /// libraries) on which this object file depends. mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_up; @@ -376,6 +387,14 @@ private: lldb_private::UUID &uuid); bool AnySegmentHasPhysicalAddress(); + + /// Takes the .gnu_debugdata and returns the decompressed object file that is + /// stored within that section. + /// + /// \returns either the decompressed object file stored within the + /// .gnu_debugdata section or \c nullptr if an error occured or if there's no + /// section with that name. + std::shared_ptr<ObjectFileELF> GetGnuDebugDataObjectFile(); }; #endif // liblldb_ObjectFileELF_h_ diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index eaf973da3835..c55b96d9110b 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -39,6 +39,8 @@ using namespace lldb; using namespace lldb_private; +char ObjectFileJIT::ID; + void ObjectFileJIT::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h index 99241126cd1a..c992683cfc3c 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -46,6 +46,13 @@ public: lldb::offset_t length, lldb_private::ModuleSpecList &specs); + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + // Member Functions bool ParseHeader() override; diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index c1fe0cc8ddda..b777a5319104 100644 --- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -120,10 +120,10 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { return nullptr; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); - if (log) - log->Printf("OperatingSystemPython::GetDynamicRegisterInfo() fetching " - "thread register definitions from python for pid %" PRIu64, - m_process->GetID()); + LLDB_LOGF(log, + "OperatingSystemPython::GetDynamicRegisterInfo() fetching " + "thread register definitions from python for pid %" PRIu64, + m_process->GetID()); StructuredData::DictionarySP dictionary = m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp); @@ -169,12 +169,12 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list, api_lock.try_lock(); auto interpreter_lock = m_interpreter->AcquireInterpreterLock(); - if (log) - log->Printf("OperatingSystemPython::UpdateThreadList() fetching thread " - "data from python for pid %" PRIu64, - m_process->GetID()); + LLDB_LOGF(log, + "OperatingSystemPython::UpdateThreadList() fetching thread " + "data from python for pid %" PRIu64, + m_process->GetID()); - // The threads that are in "new_thread_list" upon entry are the threads from + // The threads that are in "core_thread_list" upon entry are the threads from // the lldb_private::Process subclass, no memory threads will be in this // list. StructuredData::ArraySP threads_list = @@ -190,7 +190,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list, if (log) { StreamString strm; threads_list->Dump(strm); - log->Printf("threads_list = %s", strm.GetData()); + LLDB_LOGF(log, "threads_list = %s", strm.GetData()); } const uint32_t num_threads = threads_list->GetSize(); @@ -316,21 +316,21 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread, if (reg_data_addr != LLDB_INVALID_ADDRESS) { // The registers data is in contiguous memory, just create the register // context using the address provided - if (log) - log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid " - "= 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64 - ") creating memory register context", - thread->GetID(), thread->GetProtocolID(), reg_data_addr); + LLDB_LOGF(log, + "OperatingSystemPython::CreateRegisterContextForThread (tid " + "= 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64 + ") creating memory register context", + thread->GetID(), thread->GetProtocolID(), reg_data_addr); reg_ctx_sp = std::make_shared<RegisterContextMemory>( *thread, 0, *GetDynamicRegisterInfo(), reg_data_addr); } else { // No register data address is provided, query the python plug-in to let it // make up the data as it sees fit - if (log) - log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid " - "= 0x%" PRIx64 ", 0x%" PRIx64 - ") fetching register data from python", - thread->GetID(), thread->GetProtocolID()); + LLDB_LOGF(log, + "OperatingSystemPython::CreateRegisterContextForThread (tid " + "= 0x%" PRIx64 ", 0x%" PRIx64 + ") fetching register data from python", + thread->GetID(), thread->GetProtocolID()); StructuredData::StringSP reg_context_data = m_interpreter->OSPlugin_RegisterContextData(m_python_object_sp, @@ -351,10 +351,10 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread, // if we still have no register data, fallback on a dummy context to avoid // crashing if (!reg_ctx_sp) { - if (log) - log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid " - "= 0x%" PRIx64 ") forcing a dummy register context", - thread->GetID()); + LLDB_LOGF(log, + "OperatingSystemPython::CreateRegisterContextForThread (tid " + "= 0x%" PRIx64 ") forcing a dummy register context", + thread->GetID()); reg_ctx_sp = std::make_shared<RegisterContextDummy>( *thread, 0, target.GetArchitecture().GetAddressByteSize()); } @@ -375,10 +375,10 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid, addr_t context) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("OperatingSystemPython::CreateThread (tid = 0x%" PRIx64 - ", context = 0x%" PRIx64 ") fetching register data from python", - tid, context); + LLDB_LOGF(log, + "OperatingSystemPython::CreateThread (tid = 0x%" PRIx64 + ", context = 0x%" PRIx64 ") fetching register data from python", + tid, context); if (m_interpreter && m_python_object_sp) { // First thing we have to do is to try to get the API lock, and the diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index d10557596ff8..b12e21deb459 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -27,11 +27,11 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" -#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include "llvm/ADT/ScopeExit.h" using namespace lldb; using namespace lldb_private; @@ -276,8 +276,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, } else command.Printf("rsync %s %s %s:%s", GetRSyncOpts(), src_path.c_str(), GetHostname(), dst_path.c_str()); - if (log) - log->Printf("[PutFile] Running command: %s\n", command.GetData()); + LLDB_LOGF(log, "[PutFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr, nullptr, std::chrono::minutes(1)); @@ -334,8 +333,7 @@ lldb_private::Status PlatformPOSIX::GetFile( command.Printf("rsync %s %s:%s %s", GetRSyncOpts(), m_remote_platform_sp->GetHostname(), src_path.c_str(), dst_path.c_str()); - if (log) - log->Printf("[GetFile] Running command: %s\n", command.GetData()); + LLDB_LOGF(log, "[GetFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr, nullptr, std::chrono::minutes(1)); @@ -348,8 +346,7 @@ lldb_private::Status PlatformPOSIX::GetFile( // read/write, read/write, read/write, ... // close src // close dst - if (log) - log->Printf("[GetFile] Using block by block transfer....\n"); + LLDB_LOGF(log, "[GetFile] Using block by block transfer....\n"); Status error; user_id_t fd_src = OpenFile(source, File::eOpenOptionRead, lldb::eFilePermissionsFileDefault, error); @@ -515,24 +512,21 @@ lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info, error = debugger.GetTargetList().CreateTarget( debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); target = new_target_sp.get(); - if (log) - log->Printf("PlatformPOSIX::%s created new target", __FUNCTION__); + LLDB_LOGF(log, "PlatformPOSIX::%s created new target", __FUNCTION__); } else { error.Clear(); - if (log) - log->Printf("PlatformPOSIX::%s target already existed, setting target", - __FUNCTION__); + LLDB_LOGF(log, "PlatformPOSIX::%s target already existed, setting target", + __FUNCTION__); } if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); if (log) { ModuleSP exe_module_sp = target->GetExecutableModule(); - log->Printf("PlatformPOSIX::%s set selected target to %p %s", - __FUNCTION__, (void *)target, - exe_module_sp - ? exe_module_sp->GetFileSpec().GetPath().c_str() - : "<null>"); + LLDB_LOGF(log, "PlatformPOSIX::%s set selected target to %p %s", + __FUNCTION__, (void *)target, + exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() + : "<null>"); } process_sp = @@ -804,12 +798,13 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, "for path: %s", utility_error.AsCString()); return LLDB_INVALID_IMAGE_TOKEN; } - + // Make sure we deallocate the input string memory: - CleanUp path_cleanup([process, path_addr] { - process->DeallocateMemory(path_addr); + auto path_cleanup = llvm::make_scope_exit([process, path_addr] { + // Deallocate the buffer. + process->DeallocateMemory(path_addr); }); - + process->WriteMemory(path_addr, path.c_str(), path_len, utility_error); if (utility_error.Fail()) { error.SetErrorStringWithFormat("dlopen error: could not write path string:" @@ -830,21 +825,24 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, } // Make sure we deallocate the result structure memory - CleanUp return_cleanup([process, return_addr] { - process->DeallocateMemory(return_addr); + auto return_cleanup = llvm::make_scope_exit([process, return_addr] { + // Deallocate the buffer + process->DeallocateMemory(return_addr); }); - + // This will be the address of the storage for paths, if we are using them, // or nullptr to signal we aren't. lldb::addr_t path_array_addr = 0x0; - llvm::Optional<CleanUp> path_array_cleanup; + llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> + path_array_cleanup; // This is the address to a buffer large enough to hold the largest path // conjoined with the library name we're passing in. This is a convenience // to avoid having to call malloc in the dlopen function. lldb::addr_t buffer_addr = 0x0; - llvm::Optional<CleanUp> buffer_cleanup; - + llvm::Optional<llvm::detail::scope_exit<std::function<void()>>> + buffer_cleanup; + // Set the values into our args and write them to the target: if (paths != nullptr) { // First insert the paths into the target. This is expected to be a @@ -877,8 +875,9 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, } // Make sure we deallocate the paths array. - path_array_cleanup.emplace([process, path_array_addr] { - process->DeallocateMemory(path_array_addr); + path_array_cleanup.emplace([process, path_array_addr]() { + // Deallocate the path array. + process->DeallocateMemory(path_array_addr); }); process->WriteMemory(path_array_addr, path_array.data(), @@ -904,8 +903,9 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, } // Make sure we deallocate the buffer memory: - buffer_cleanup.emplace([process, buffer_addr] { - process->DeallocateMemory(buffer_addr); + buffer_cleanup.emplace([process, buffer_addr]() { + // Deallocate the buffer. + process->DeallocateMemory(buffer_addr); }); } @@ -930,10 +930,11 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, // Make sure we clean up the args structure. We can't reuse it because the // Platform lives longer than the process and the Platforms don't get a // signal to clean up cached data when a process goes away. - CleanUp args_cleanup([do_dlopen_function, &exe_ctx, func_args_addr] { - do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr); - }); - + auto args_cleanup = + llvm::make_scope_exit([do_dlopen_function, &exe_ctx, func_args_addr] { + do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr); + }); + // Now run the caller: EvaluateExpressionOptions options; options.SetExecutionPolicy(eExecutionPolicyAlways); diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 9c52b59e2b06..1e62ddfe94fd 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -169,21 +169,21 @@ bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec &module_file_spec, const auto module_path = module_file_spec.GetPath(false); if (!m_gdb_client.GetModuleInfo(module_file_spec, arch, module_spec)) { - if (log) - log->Printf( - "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", - __FUNCTION__, module_path.c_str(), - arch.GetTriple().getTriple().c_str()); + LLDB_LOGF( + log, + "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", + __FUNCTION__, module_path.c_str(), + arch.GetTriple().getTriple().c_str()); return false; } if (log) { StreamString stream; module_spec.Dump(stream); - log->Printf( - "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", - __FUNCTION__, module_path.c_str(), arch.GetTriple().getTriple().c_str(), - stream.GetData()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", + __FUNCTION__, module_path.c_str(), + arch.GetTriple().getTriple().c_str(), stream.GetData()); } return true; @@ -253,9 +253,9 @@ FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() { Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); FileSpec working_dir; if (m_gdb_client.GetWorkingDir(working_dir) && log) - log->Printf( - "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", - working_dir.GetCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", + working_dir.GetCString()); return working_dir; } else { return Platform::GetRemoteWorkingDirectory(); @@ -268,9 +268,8 @@ bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory( // Clear the working directory it case it doesn't get set correctly. This // will for use to re-read it Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", - working_dir.GetCString()); + LLDB_LOGF(log, "PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", + working_dir.GetCString()); return m_gdb_client.SetWorkingDir(working_dir) == 0; } else return Platform::SetRemoteWorkingDirectory(working_dir); @@ -370,8 +369,7 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); Status error; - if (log) - log->Printf("PlatformRemoteGDBServer::%s() called", __FUNCTION__); + LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() called", __FUNCTION__); auto num_file_actions = launch_info.GetNumFileActions(); for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) { @@ -408,10 +406,10 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { const char *arch_triple = arch_spec.GetTriple().str().c_str(); m_gdb_client.SendLaunchArchPacket(arch_triple); - if (log) - log->Printf( - "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", - __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); + LLDB_LOGF( + log, + "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", + __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); int arg_packet_err; { @@ -427,22 +425,21 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) { const auto pid = m_gdb_client.GetCurrentProcessID(false); if (pid != LLDB_INVALID_PROCESS_ID) { launch_info.SetProcessID(pid); - if (log) - log->Printf("PlatformRemoteGDBServer::%s() pid %" PRIu64 - " launched successfully", - __FUNCTION__, pid); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s() pid %" PRIu64 + " launched successfully", + __FUNCTION__, pid); } else { - if (log) - log->Printf("PlatformRemoteGDBServer::%s() launch succeeded but we " - "didn't get a valid process id back!", - __FUNCTION__); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::%s() launch succeeded but we " + "didn't get a valid process id back!", + __FUNCTION__); error.SetErrorString("failed to get PID"); } } else { error.SetErrorString(error_str.c_str()); - if (log) - log->Printf("PlatformRemoteGDBServer::%s() launch failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "PlatformRemoteGDBServer::%s() launch failed: %s", + __FUNCTION__, error.AsCString()); } } else { error.SetErrorStringWithFormat("'A' packet returned an error: %i", @@ -600,11 +597,10 @@ Status PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode) { Status error = m_gdb_client.MakeDirectory(file_spec, mode); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " - "error = %u (%s)", - file_spec.GetCString(), mode, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) " + "error = %u (%s)", + file_spec.GetCString(), mode, error.GetError(), error.AsCString()); return error; } @@ -612,11 +608,11 @@ Status PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) { Status error = m_gdb_client.GetFilePermissions(file_spec, file_permissions); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::GetFilePermissions(path='%s', " - "file_permissions=%o) error = %u (%s)", - file_spec.GetCString(), file_permissions, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::GetFilePermissions(path='%s', " + "file_permissions=%o) error = %u (%s)", + file_spec.GetCString(), file_permissions, error.GetError(), + error.AsCString()); return error; } @@ -624,16 +620,17 @@ Status PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) { Status error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::SetFilePermissions(path='%s', " - "file_permissions=%o) error = %u (%s)", - file_spec.GetCString(), file_permissions, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::SetFilePermissions(path='%s', " + "file_permissions=%o) error = %u (%s)", + file_spec.GetCString(), file_permissions, error.GetError(), + error.AsCString()); return error; } lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec, - uint32_t flags, uint32_t mode, + File::OpenOptions flags, + uint32_t mode, Status &error) { return m_gdb_client.OpenFile(file_spec, flags, mode, error); } @@ -671,20 +668,19 @@ Status PlatformRemoteGDBServer::CreateSymlink( { Status error = m_gdb_client.CreateSymlink(src, dst); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " - "error = %u (%s)", - src.GetCString(), dst.GetCString(), error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') " + "error = %u (%s)", + src.GetCString(), dst.GetCString(), error.GetError(), + error.AsCString()); return error; } Status PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) { Status error = m_gdb_client.Unlink(file_spec); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", - file_spec.GetCString(), error.GetError(), error.AsCString()); + LLDB_LOGF(log, "PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", + file_spec.GetCString(), error.GetError(), error.AsCString()); return error; } diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index c774daa8ab73..13edcbab9f59 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -113,7 +113,7 @@ public: Status SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) override; - lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags, + lldb::user_id_t OpenFile(const FileSpec &file_spec, File::OpenOptions flags, uint32_t mode, Status &error) override; bool CloseFile(lldb::user_id_t fd, Status &error) override; diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp index 3ec410fe7d76..f70ef97a2bc5 100644 --- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp +++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp @@ -254,9 +254,8 @@ CreatePosixSpawnFileAction(const FileAction &action, case FileAction::eFileActionNone: default: - if (log) - log->Printf("%s(): unsupported file action %u", __FUNCTION__, - action.GetAction()); + LLDB_LOGF(log, "%s(): unsupported file action %u", __FUNCTION__, + action.GetAction()); break; } @@ -288,8 +287,7 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, int error_code; if ((error_code = ::posix_spawnattr_init(&attr)) != 0) { - if (log) - log->Printf("::posix_spawnattr_init(&attr) failed"); + LLDB_LOGF(log, "::posix_spawnattr_init(&attr) failed"); error.SetError(error_code, eErrorTypePOSIX); return error; } @@ -378,10 +376,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, error = CreatePosixSpawnFileAction(*action, &file_actions); if (!error.Success()) { - if (log) - log->Printf("%s(): error converting FileAction to posix_spawn " - "file action: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "%s(): error converting FileAction to posix_spawn " + "file action: %s", + __FUNCTION__, error.AsCString()); return error; } } @@ -416,10 +414,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path, if (actual_cpu_type) { *actual_cpu_type = GetCPUTypeForLocalProcess(*pid); - if (log) - log->Printf("%s(): cpu type for launched process pid=%i: " - "cpu_type=0x%8.8x", - __FUNCTION__, *pid, *actual_cpu_type); + LLDB_LOGF(log, + "%s(): cpu type for launched process pid=%i: " + "cpu_type=0x%8.8x", + __FUNCTION__, *pid, *actual_cpu_type); } return error; @@ -477,23 +475,21 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd, char resolved_path[PATH_MAX]; resolved_path[0] = '\0'; - if (log) - log->Printf("%s(): attempting to resolve given binary path: \"%s\"", - __FUNCTION__, given_path); + LLDB_LOGF(log, "%s(): attempting to resolve given binary path: \"%s\"", + __FUNCTION__, given_path); // If we fail to resolve the path to our executable, then just use what we // were given and hope for the best if (!ResolveExecutablePath(given_path, resolved_path, sizeof(resolved_path))) { - if (log) - log->Printf("%s(): failed to resolve binary path, using " - "what was given verbatim and hoping for the best", - __FUNCTION__); + LLDB_LOGF(log, + "%s(): failed to resolve binary path, using " + "what was given verbatim and hoping for the best", + __FUNCTION__); ::strncpy(resolved_path, given_path, sizeof(resolved_path)); } else { - if (log) - log->Printf("%s(): resolved given binary path to: \"%s\"", __FUNCTION__, - resolved_path); + LLDB_LOGF(log, "%s(): resolved given binary path to: \"%s\"", __FUNCTION__, + resolved_path); } char launch_err_str[PATH_MAX]; diff --git a/source/Plugins/Process/Darwin/MachException.cpp b/source/Plugins/Process/Darwin/MachException.cpp index 70ad6736a748..073ad64b300c 100644 --- a/source/Plugins/Process/Darwin/MachException.cpp +++ b/source/Plugins/Process/Darwin/MachException.cpp @@ -67,10 +67,11 @@ extern "C" kern_return_t catch_mach_exception_raise_state( // TODO change to LIBLLDB_LOG_EXCEPTION Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) { - log->Printf("::%s(exc_port = 0x%4.4x, exc_type = %d (%s), " - "exc_data = 0x%llx, exc_data_count = %d)", - __FUNCTION__, exc_port, exc_type, MachException::Name(exc_type), - (uint64_t)exc_data, exc_data_count); + LLDB_LOGF(log, + "::%s(exc_port = 0x%4.4x, exc_type = %d (%s), " + "exc_data = 0x%llx, exc_data_count = %d)", + __FUNCTION__, exc_port, exc_type, MachException::Name(exc_type), + (uint64_t)exc_data, exc_data_count); } return KERN_FAILURE; } @@ -83,13 +84,14 @@ extern "C" kern_return_t catch_mach_exception_raise_state_identity( thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) { - log->Printf("::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " - "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] = " - "{ 0x%llx, 0x%llx })", - __FUNCTION__, exc_port, thread_port, task_port, exc_type, - MachException::Name(exc_type), exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); + LLDB_LOGF(log, + "::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " + "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] = " + "{ 0x%llx, 0x%llx })", + __FUNCTION__, exc_port, thread_port, task_port, exc_type, + MachException::Name(exc_type), exc_data_count, + (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), + (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); } return KERN_FAILURE; @@ -102,13 +104,14 @@ catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port, mach_msg_type_number_t exc_data_count) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) { - log->Printf("::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " - "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] " - "= { 0x%llx, 0x%llx })", - __FUNCTION__, exc_port, thread_port, task_port, exc_type, - MachException::Name(exc_type), exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); + LLDB_LOGF(log, + "::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, " + "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] " + "= { 0x%llx, 0x%llx })", + __FUNCTION__, exc_port, thread_port, task_port, exc_type, + MachException::Name(exc_type), exc_data_count, + (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), + (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); } if (task_port == g_message->task_port) { @@ -187,15 +190,16 @@ Status MachException::Message::Receive(mach_port_t port, options & MACH_RCV_TIMEOUT ? timeout : 0; if (log && ((options & MACH_RCV_TIMEOUT) == 0)) { // Dump this log message if we have no timeout in case it never returns - log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " - "local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = 0, rcv_size = %llu, " - "rcv_name = %#x, timeout = %u, notify = %#x)", - exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, - (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout, - notify_port); + LLDB_LOGF(log, + "::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " + "local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = 0, rcv_size = %llu, " + "rcv_name = %#x, timeout = %u, notify = %#x)", + exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, + exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, + exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, + (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout, + notify_port); } mach_msg_return_t mach_err = @@ -213,15 +217,16 @@ Status MachException::Message::Receive(mach_port_t port, // Dump any errors we get if (error.Fail() && log) { - log->Printf("::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " - "local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = %u, rcv_size = %lu, rcv_name " - "= %#x, timeout = %u, notify = %#x) failed: %s", - exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, - sizeof(exc_msg.data), port, mach_msg_timeout, notify_port, - error.AsCString()); + LLDB_LOGF(log, + "::mach_msg(msg->{bits = %#x, size = %u remote_port = %#x, " + "local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = %u, rcv_size = %lu, rcv_name " + "= %#x, timeout = %u, notify = %#x) failed: %s", + exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, + exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, + exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, + sizeof(exc_msg.data), port, mach_msg_timeout, notify_port, + error.AsCString()); } return error; } @@ -264,10 +269,10 @@ bool MachException::Message::CatchExceptionRaise(task_t task) { } else { Log *log( GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("MachException::Message::%s(): mach_exc_server " - "returned zero...", - __FUNCTION__); + LLDB_LOGF(log, + "MachException::Message::%s(): mach_exc_server " + "returned zero...", + __FUNCTION__); } g_message = NULL; return success; @@ -293,10 +298,10 @@ Status MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task, auto mach_err = ::pid_for_task(state.task_port, &state_pid); if (mach_err) { error.SetError(mach_err, eErrorTypeMachKernel); - if (log) - log->Printf("MachException::Message::%s(): pid_for_task() " - "failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "MachException::Message::%s(): pid_for_task() " + "failed: %s", + __FUNCTION__, error.AsCString()); return error; } } @@ -309,25 +314,25 @@ Status MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task, error.SetError(errno, eErrorTypePOSIX); if (!error.Success()) { - if (log) - log->Printf("::ptrace(request = PT_THUPDATE, pid = " - "0x%4.4x, tid = 0x%4.4x, signal = %i)", - state_pid, state.thread_port, soft_signal); + LLDB_LOGF(log, + "::ptrace(request = PT_THUPDATE, pid = " + "0x%4.4x, tid = 0x%4.4x, signal = %i)", + state_pid, state.thread_port, soft_signal); return error; } } } - if (log) - log->Printf("::mach_msg ( msg->{bits = %#x, size = %u, remote_port " - "= %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " - "option = %#x, send_size = %u, rcv_size = %u, rcv_name " - "= %#x, timeout = %u, notify = %#x)", - reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, reply_msg.hdr.msgh_local_port, - reply_msg.hdr.msgh_reserved, reply_msg.hdr.msgh_id, - MACH_SEND_MSG | MACH_SEND_INTERRUPT, reply_msg.hdr.msgh_size, 0, - MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + LLDB_LOGF(log, + "::mach_msg ( msg->{bits = %#x, size = %u, remote_port " + "= %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = %u, rcv_size = %u, rcv_name " + "= %#x, timeout = %u, notify = %#x)", + reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, + reply_msg.hdr.msgh_remote_port, reply_msg.hdr.msgh_local_port, + reply_msg.hdr.msgh_reserved, reply_msg.hdr.msgh_id, + MACH_SEND_MSG | MACH_SEND_INTERRUPT, reply_msg.hdr.msgh_size, 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); auto mach_err = ::mach_msg(&reply_msg.hdr, MACH_SEND_MSG | MACH_SEND_INTERRUPT, @@ -342,12 +347,13 @@ Status MachException::Message::Reply(::pid_t inferior_pid, task_t inferior_task, log->PutCString("::mach_msg() - send interrupted"); // TODO: keep retrying to reply??? } else if (state.task_port == inferior_task) { - log->Printf("mach_msg(): returned an error when replying " - "to a mach exception: error = %u (%s)", - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "mach_msg(): returned an error when replying " + "to a mach exception: error = %u (%s)", + error.GetError(), error.AsCString()); } else { - log->Printf("::mach_msg() - failed (child of task): %u (%s)", - error.GetError(), error.AsCString()); + LLDB_LOGF(log, "::mach_msg() - failed (child of task): %u (%s)", + error.GetError(), error.AsCString()); } } @@ -377,9 +383,8 @@ Status MachException::PortInfo::Save(task_t task) { Status error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("MachException::PortInfo::%s(task = 0x%4.4x)", __FUNCTION__, - task); + LLDB_LOGF(log, "MachException::PortInfo::%s(task = 0x%4.4x)", __FUNCTION__, + task); // Be careful to be able to have debugserver built on a newer OS than what it // is currently running on by being able to start with all exceptions and @@ -394,13 +399,15 @@ Status MachException::PortInfo::Save(task_t task) { if (log) { if (error.Success()) { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = " - "0x%x, maskCnt => %u, ports, behaviors, flavors)", - task, mask, count); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, mask = " + "0x%x, maskCnt => %u, ports, behaviors, flavors)", + task, mask, count); } else { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = 0x%x, " - "maskCnt => %u, ports, behaviors, flavors) error: %u (%s)", - task, mask, count, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, mask = 0x%x, " + "maskCnt => %u, ports, behaviors, flavors) error: %u (%s)", + task, mask, count, error.GetError(), error.AsCString()); } } @@ -413,15 +420,17 @@ Status MachException::PortInfo::Save(task_t task) { error.SetError(mach_err, eErrorTypeMachKernel); if (log) { if (error.Success()) { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, " - "mask = 0x%x, maskCnt => %u, ports, behaviors, " - "flavors)", - task, mask, count); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, " + "mask = 0x%x, maskCnt => %u, ports, behaviors, " + "flavors)", + task, mask, count); } else { - log->Printf("::task_get_exception_ports(task = 0x%4.4x, mask = " - "0x%x, maskCnt => %u, ports, behaviors, flavors) " - "error: %u (%s)", - task, mask, count, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_get_exception_ports(task = 0x%4.4x, mask = " + "0x%x, maskCnt => %u, ports, behaviors, flavors) " + "error: %u (%s)", + task, mask, count, error.GetError(), error.AsCString()); } } } @@ -437,8 +446,7 @@ Status MachException::PortInfo::Restore(task_t task) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("MachException::PortInfo::Restore(task = 0x%4.4x)", task); + LLDB_LOGF(log, "MachException::PortInfo::Restore(task = 0x%4.4x)", task); uint32_t i = 0; if (count > 0) { @@ -449,17 +457,19 @@ Status MachException::PortInfo::Restore(task_t task) { error.SetError(mach_err, eErrorTypeMachKernel); if (log) { if (error.Success()) { - log->Printf("::task_set_exception_ports(task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " - "behavior = 0x%8.8x, new_flavor = 0x%8.8x)", - task, masks[i], ports[i], behaviors[i], flavors[i]); + LLDB_LOGF(log, + "::task_set_exception_ports(task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " + "behavior = 0x%8.8x, new_flavor = 0x%8.8x)", + task, masks[i], ports[i], behaviors[i], flavors[i]); } else { - log->Printf("::task_set_exception_ports(task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " - "behavior = 0x%8.8x, new_flavor = 0x%8.8x): " - "error %u (%s)", - task, masks[i], ports[i], behaviors[i], flavors[i], - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_set_exception_ports(task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " + "behavior = 0x%8.8x, new_flavor = 0x%8.8x): " + "error %u (%s)", + task, masks[i], ports[i], behaviors[i], flavors[i], + error.GetError(), error.AsCString()); } } diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp index fe7de27e0ee6..18dbdda9a33b 100644 --- a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp +++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp @@ -75,19 +75,19 @@ Status NativeProcessProtocol::Launch( // Handle launch failure. if (!error.Success()) { - if (log) - log->Printf("NativeProcessDarwin::%s() failed to launch process: " - "%s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() failed to launch process: " + "%s", + __FUNCTION__, error.AsCString()); return error; } // Handle failure to return a pid. if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("NativeProcessDarwin::%s() launch succeeded but no " - "pid was returned! Aborting.", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() launch succeeded but no " + "pid was returned! Aborting.", + __FUNCTION__); return error; } @@ -104,10 +104,10 @@ Status NativeProcessProtocol::Launch( // NativeProcessDarwin instance. error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop); if (!error.Success()) { - if (log) - log->Printf("NativeProcessDarwin::%s() aborting, failed to finalize" - " the launching of the process: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() aborting, failed to finalize" + " the launching of the process: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -120,9 +120,8 @@ Status NativeProcessProtocol::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__, - pid); + LLDB_LOGF(log, "NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__, + pid); // Retrieve the architecture for the running process. ArchSpec process_arch; @@ -173,10 +172,10 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor, error = StartExceptionThread(); if (!error.Success()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failure starting the " - "mach exception port monitor thread: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failure starting the " + "mach exception port monitor thread: %s", + __FUNCTION__, error.AsCString()); // Terminate the inferior process. There's nothing meaningful we can do if // we can't receive signals and exceptions. Since we launched the process, @@ -195,33 +194,31 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor, int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); if (err == 0) { // m_flags |= eMachProcessFlagsAttached; - if (log) - log->Printf("NativeProcessDarwin::%s(): successfully spawned " - "process with pid %" PRIu64, - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): successfully spawned " + "process with pid %" PRIu64, + __FUNCTION__, m_pid); } else { error.SetErrorToErrno(); SetState(eStateExited); - if (log) - log->Printf("NativeProcessDarwin::%s(): error: failed to " - "attach to spawned pid %" PRIu64 " (error=%d (%s))", - __FUNCTION__, m_pid, (int)error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): error: failed to " + "attach to spawned pid %" PRIu64 " (error=%d (%s))", + __FUNCTION__, m_pid, (int)error.GetError(), error.AsCString()); return error; } } - if (log) - log->Printf("NativeProcessDarwin::%s(): new pid is %" PRIu64 "...", - __FUNCTION__, m_pid); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): new pid is %" PRIu64 "...", + __FUNCTION__, m_pid); // Spawn a thread to reap our child inferior process... error = StartWaitpidThread(main_loop); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to start waitpid() " - "thread: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to start waitpid() " + "thread: %s", + __FUNCTION__, error.AsCString()); kill(SIGKILL, static_cast<::pid_t>(m_pid)); return error; } @@ -230,10 +227,10 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor, // We failed to get the task for our process ID which is bad. Kill our // process; otherwise, it will be stopped at the entry point and get // reparented to someone else and never go away. - if (log) - log->Printf("NativeProcessDarwin::%s(): could not get task port " - "for process, sending SIGKILL and exiting: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): could not get task port " + "for process, sending SIGKILL and exiting: %s", + __FUNCTION__, error.AsCString()); kill(SIGKILL, static_cast<::pid_t>(m_pid)); return error; } @@ -278,18 +275,17 @@ void NativeProcessDarwin::ExceptionMessageReceived( // the exception to our internal exception stack m_exception_messages.push_back(message); - if (log) - log->Printf("NativeProcessDarwin::%s(): new queued message count: %lu", - __FUNCTION__, m_exception_messages.size()); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): new queued message count: %lu", + __FUNCTION__, m_exception_messages.size()); } void *NativeProcessDarwin::ExceptionThread(void *arg) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (!arg) { - if (log) - log->Printf("NativeProcessDarwin::%s(): cannot run mach exception " - "thread, mandatory process arg was null", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): cannot run mach exception " + "thread, mandatory process arg was null", + __FUNCTION__); return nullptr; } @@ -299,9 +295,8 @@ void *NativeProcessDarwin::ExceptionThread(void *arg) { void *NativeProcessDarwin::DoExceptionThread() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("NativeProcessDarwin::%s(arg=%p) starting thread...", - __FUNCTION__, this); + LLDB_LOGF(log, "NativeProcessDarwin::%s(arg=%p) starting thread...", + __FUNCTION__, this); pthread_setname_np("exception monitoring thread"); @@ -344,20 +339,20 @@ void *NativeProcessDarwin::DoExceptionThread() { if (process->ProcessUsingSpringBoard()) { // Request a renewal for every 60 seconds if we attached using SpringBoard. watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60)); - if (log) - log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) " - "=> %p", - pid, watchdog.get()); + LLDB_LOGF(log, + "::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) " + "=> %p", + pid, watchdog.get()); if (watchdog.get()) { ::SBSWatchdogAssertionRenew(watchdog.get()); CFTimeInterval watchdogRenewalInterval = ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get()); - if (log) - log->Printf("::SBSWatchdogAssertionGetRenewalInterval(%p) => " - "%g seconds", - watchdog.get(), watchdogRenewalInterval); + LLDB_LOGF(log, + "::SBSWatchdogAssertionGetRenewalInterval(%p) => " + "%g seconds", + watchdog.get(), watchdogRenewalInterval); if (watchdogRenewalInterval > 0.0) { watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000; if (watchdog_timeout > 3000) { @@ -425,11 +420,11 @@ void *NativeProcessDarwin::DoExceptionThread() { // If we have no task port we should exit this thread, as it implies // the inferior went down. if (!IsExceptionPortValid()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): the inferior " - "exception port is no longer valid, " - "canceling exception thread...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): the inferior " + "exception port is no longer valid, " + "canceling exception thread...", + __FUNCTION__); // Should we be setting a process state here? break; } @@ -437,19 +432,19 @@ void *NativeProcessDarwin::DoExceptionThread() { // Make sure the inferior task is still valid. if (IsTaskValid()) { // Task is still ok. - if (log) - log->Printf("NativeProcessDarwin::%s(): interrupted, but " - "the inferior task iss till valid, " - "continuing...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): interrupted, but " + "the inferior task iss till valid, " + "continuing...", + __FUNCTION__); continue; } else { // The inferior task is no longer valid. Time to exit as the process // has gone away. - if (log) - log->Printf("NativeProcessDarwin::%s(): the inferior task " - "has exited, and so will we...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): the inferior task " + "has exited, and so will we...", + __FUNCTION__); // Does this race at all with our waitpid()? SetState(eStateExited); break; @@ -471,18 +466,18 @@ void *NativeProcessDarwin::DoExceptionThread() { // our task is still valid. if (IsTaskValid(task)) { // Task is still ok. - if (log) - log->Printf("NativeProcessDarwin::%s(): got a timeout, " - "continuing...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): got a timeout, " + "continuing...", + __FUNCTION__); continue; } else { // The inferior task is no longer valid. Time to exit as the // process has gone away. - if (log) - log->Printf("NativeProcessDarwin::%s(): the inferior " - "task has exited, and so will we...", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): the inferior " + "task has exited, and so will we...", + __FUNCTION__); // Does this race at all with our waitpid()? SetState(eStateExited); break; @@ -493,18 +488,17 @@ void *NativeProcessDarwin::DoExceptionThread() { if (watchdog.get()) { watchdog_elapsed += periodic_timeout; if (watchdog_elapsed >= watchdog_timeout) { - if (log) - log->Printf("SBSWatchdogAssertionRenew(%p)", watchdog.get()); + LLDB_LOGF(log, "SBSWatchdogAssertionRenew(%p)", watchdog.get()); ::SBSWatchdogAssertionRenew(watchdog.get()); watchdog_elapsed = 0; } } #endif } else { - if (log) - log->Printf("NativeProcessDarwin::%s(): continuing after " - "receiving an unexpected error: %u (%s)", - __FUNCTION__, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): continuing after " + "receiving an unexpected error: %u (%s)", + __FUNCTION__, error.GetError(), error.AsCString()); // TODO: notify of error? } } @@ -523,17 +517,15 @@ void *NativeProcessDarwin::DoExceptionThread() { } #endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - if (log) - log->Printf("NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__, - this); + LLDB_LOGF(log, "NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__, + this); return nullptr; } Status NativeProcessDarwin::StartExceptionThread() { Status error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__); + LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__); // Make sure we've looked up the inferior port. TaskPortForProcessID(error); @@ -554,11 +546,11 @@ Status NativeProcessDarwin::StartExceptionThread() { &m_exception_port); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): mach_port_allocate(" - "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, " - "&m_exception_port) failed: %u (%s)", - __FUNCTION__, task_self, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): mach_port_allocate(" + "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, " + "&m_exception_port) failed: %u (%s)", + __FUNCTION__, task_self, error.GetError(), error.AsCString()); return error; } @@ -567,23 +559,23 @@ Status NativeProcessDarwin::StartExceptionThread() { task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): mach_port_insert_right(" - "task_self=0x%4.4x, m_exception_port=0x%4.4x, " - "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) " - "failed: %u (%s)", - __FUNCTION__, task_self, m_exception_port, m_exception_port, - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): mach_port_insert_right(" + "task_self=0x%4.4x, m_exception_port=0x%4.4x, " + "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) " + "failed: %u (%s)", + __FUNCTION__, task_self, m_exception_port, m_exception_port, + error.GetError(), error.AsCString()); return error; } // Save the original state of the exception ports for our child process. error = SaveExceptionPortInfo(); if (error.Fail() || (m_exc_port_info.mask == 0)) { - if (log) - log->Printf("NativeProcessDarwin::%s(): SaveExceptionPortInfo() " - "failed, cannot install exception handler: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): SaveExceptionPortInfo() " + "failed, cannot install exception handler: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -593,14 +585,14 @@ Status NativeProcessDarwin::StartExceptionThread() { EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("::task_set_exception_ports (task = 0x%4.4x, " - "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " - "behavior = 0x%8.8x, new_flavor = 0x%8.8x) failed: " - "%u (%s)", - m_task, m_exc_port_info.mask, m_exception_port, - (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE, - error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_set_exception_ports (task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " + "behavior = 0x%8.8x, new_flavor = 0x%8.8x) failed: " + "%u (%s)", + m_task, m_exc_port_info.mask, m_exception_port, + (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE, + error.GetError(), error.AsCString()); return error; } @@ -609,10 +601,10 @@ Status NativeProcessDarwin::StartExceptionThread() { ::pthread_create(&m_exception_thread, nullptr, ExceptionThread, this); error.SetError(pthread_err, eErrorTypePOSIX); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to create Mach " - "exception-handling thread: %u (%s)", - __FUNCTION__, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to create Mach " + "exception-handling thread: %u (%s)", + __FUNCTION__, error.GetError(), error.AsCString()); } return error; @@ -677,10 +669,10 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex); - if (log) - log->Printf("NativeProcessDarwin::%s(): processing %lu exception " - "messages.", - __FUNCTION__, m_exception_messages.size()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): processing %lu exception " + "messages.", + __FUNCTION__, m_exception_messages.size()); if (m_exception_messages.empty()) { // Not particularly useful... @@ -733,18 +725,18 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { const bool force_update = true; const task_t new_task = TaskPortForProcessID(error, force_update); if (old_task != new_task) { - if (log) - log->Printf("exec: inferior task port changed " - "from 0x%4.4x to 0x%4.4x", - old_task, new_task); + LLDB_LOGF(log, + "exec: inferior task port changed " + "from 0x%4.4x to 0x%4.4x", + old_task, new_task); } } } else { - if (log) - log->Printf("NativeProcessDarwin::%s() warning: " - "failed to read all_image_infos." - "infoArrayCount from 0x%8.8llx", - __FUNCTION__, info_array_count_addr); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() warning: " + "failed to read all_image_infos." + "infoArrayCount from 0x%8.8llx", + __FUNCTION__, info_array_count_addr); } } else if ((m_sent_interrupt_signo != 0) && (signo == m_sent_interrupt_signo)) { @@ -756,10 +748,10 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { if (m_did_exec) { cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_pid); if (m_cpu_type != process_cpu_type) { - if (log) - log->Printf("NativeProcessDarwin::%s(): arch changed from " - "0x%8.8x to 0x%8.8x", - __FUNCTION__, m_cpu_type, process_cpu_type); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): arch changed from " + "0x%8.8x to 0x%8.8x", + __FUNCTION__, m_cpu_type, process_cpu_type); m_cpu_type = process_cpu_type; // TODO figure out if we need to do something here. // DNBArchProtocol::SetArchitecture (process_cpu_type); @@ -772,10 +764,10 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { if (m_sent_interrupt_signo != 0) { if (received_interrupt) { - if (log) - log->Printf("NativeProcessDarwin::%s(): process " - "successfully interrupted with signal %i", - __FUNCTION__, m_sent_interrupt_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): process " + "successfully interrupted with signal %i", + __FUNCTION__, m_sent_interrupt_signo); // Mark that we received the interrupt signal m_sent_interrupt_signo = 0; @@ -792,19 +784,19 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() { // Only auto_resume if we stopped with _only_ the interrupt signal. if (num_task_exceptions == 1) { auto_resume = true; - if (log) - log->Printf("NativeProcessDarwin::%s(): auto " - "resuming due to unhandled interrupt " - "signal %i", - __FUNCTION__, m_auto_resume_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): auto " + "resuming due to unhandled interrupt " + "signal %i", + __FUNCTION__, m_auto_resume_signo); } m_auto_resume_signo = 0; } } else { - if (log) - log->Printf("NativeProcessDarwin::%s(): didn't get signal " - "%i after MachProcess::Interrupt()", - __FUNCTION__, m_sent_interrupt_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): didn't get signal " + "%i after MachProcess::Interrupt()", + __FUNCTION__, m_sent_interrupt_signo); } } } @@ -878,10 +870,10 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { const bool child_inherits = false; error = m_waitpid_pipe.CreateNew(child_inherits); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to create waitpid " - "communication pipe: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to create waitpid " + "communication pipe: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -889,8 +881,8 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { // TODO make PipePOSIX derive from IOObject. This is goofy here. const bool transfer_ownership = false; - auto io_sp = IOObjectSP( - new File(m_waitpid_pipe.GetReadFileDescriptor(), transfer_ownership)); + auto io_sp = IOObjectSP(new NativeFile(m_waitpid_pipe.GetReadFileDescriptor(), + transfer_ownership)); m_waitpid_reader_handle = main_loop.RegisterReadObject( io_sp, [this](MainLoopBase &) { HandleWaitpidResult(); }, error); @@ -899,10 +891,10 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { ::pthread_create(&m_waitpid_thread, nullptr, WaitpidThread, this); error.SetError(pthread_err, eErrorTypePOSIX); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to create waitpid " - "handling thread: %u (%s)", - __FUNCTION__, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to create waitpid " + "handling thread: %u (%s)", + __FUNCTION__, error.GetError(), error.AsCString()); return error; } @@ -912,10 +904,10 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) { void *NativeProcessDarwin::WaitpidThread(void *arg) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (!arg) { - if (log) - log->Printf("NativeProcessDarwin::%s(): cannot run waitpid " - "thread, mandatory process arg was null", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): cannot run waitpid " + "thread, mandatory process arg was null", + __FUNCTION__); return nullptr; } @@ -938,10 +930,10 @@ void *NativeProcessDarwin::DoWaitpidThread() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (m_pid == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("NativeProcessDarwin::%s(): inferior process ID is " - "not set, cannot waitpid on it", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): inferior process ID is " + "not set, cannot waitpid on it", + __FUNCTION__); return nullptr; } @@ -962,41 +954,41 @@ void *NativeProcessDarwin::DoWaitpidThread() { if (error.Fail()) { if (error.GetError() == EINTR) { // This is okay, we can keep going. - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) interrupted, continuing", - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ", &status, 0) interrupted, continuing", + __FUNCTION__, m_pid); continue; } // This error is not okay, abort. - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) aborting due to error: %u (%s)", - __FUNCTION__, m_pid, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ", &status, 0) aborting due to error: %u (%s)", + __FUNCTION__, m_pid, error.GetError(), error.AsCString()); break; } // Log the successful result. - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ", &status, 0) => %i, status = %i", - __FUNCTION__, m_pid, child_pid, status); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ", &status, 0) => %i, status = %i", + __FUNCTION__, m_pid, child_pid, status); // Handle the result. if (WIFSTOPPED(status)) { - if (log) - log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 - ") received a stop, continuing waitpid() loop", - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64 + ") received a stop, continuing waitpid() loop", + __FUNCTION__, m_pid); continue; } else // if (WIFEXITED(status) || WIFSIGNALED(status)) { - if (log) - log->Printf("NativeProcessDarwin::%s(pid = %" PRIu64 "): " - "waitpid thread is setting exit status for pid = " - "%i to %i", - __FUNCTION__, m_pid, child_pid, status); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(pid = %" PRIu64 "): " + "waitpid thread is setting exit status for pid = " + "%i to %i", + __FUNCTION__, m_pid, child_pid, status); error = SendInferiorExitStatusToMainLoop(child_pid, status); return nullptr; @@ -1005,12 +997,11 @@ void *NativeProcessDarwin::DoWaitpidThread() { // We should never exit as long as our child process is alive. If we get // here, something completely unexpected went wrong and we should exit. - if (log) - log->Printf( - "NativeProcessDarwin::%s(): internal error: waitpid thread " - "exited out of its main loop in an unexpected way. pid = %" PRIu64 - ". Sending exit status of -1.", - __FUNCTION__, m_pid); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): internal error: waitpid thread " + "exited out of its main loop in an unexpected way. pid = %" PRIu64 + ". Sending exit status of -1.", + __FUNCTION__, m_pid); error = SendInferiorExitStatusToMainLoop((::pid_t)m_pid, -1); return nullptr; @@ -1026,11 +1017,11 @@ Status NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid, // Send the pid. error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written); if (error.Fail() || (bytes_written < sizeof(pid))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to write " - "waitpid exiting pid to the pipe. Client will not " - "hear about inferior exit status!", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to write " + "waitpid exiting pid to the pipe. Client will not " + "hear about inferior exit status!", + __FUNCTION__); return error; } @@ -1038,11 +1029,11 @@ Status NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid, bytes_written = 0; error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written); if (error.Fail() || (bytes_written < sizeof(status))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to write " - "waitpid exit result to the pipe. Client will not " - "hear about inferior exit status!", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to write " + "waitpid exit result to the pipe. Client will not " + "hear about inferior exit status!", + __FUNCTION__); } return error; } @@ -1058,11 +1049,11 @@ Status NativeProcessDarwin::HandleWaitpidResult() { size_t bytes_read = 0; error = m_waitpid_pipe.Read(&pid, sizeof(pid), bytes_read); if (error.Fail() || (bytes_read < sizeof(pid))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to read " - "waitpid exiting pid from the pipe. Will notify " - "as if parent process died with exit status -1.", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to read " + "waitpid exiting pid from the pipe. Will notify " + "as if parent process died with exit status -1.", + __FUNCTION__); SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status); return error; } @@ -1071,21 +1062,21 @@ Status NativeProcessDarwin::HandleWaitpidResult() { int status = -1; error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read); if (error.Fail() || (bytes_read < sizeof(status))) { - if (log) - log->Printf("NativeProcessDarwin::%s() - failed to read " - "waitpid exit status from the pipe. Will notify " - "as if parent process died with exit status -1.", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s() - failed to read " + "waitpid exit status from the pipe. Will notify " + "as if parent process died with exit status -1.", + __FUNCTION__); SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status); return error; } // Notify the monitor that our state has changed. - if (log) - log->Printf("NativeProcessDarwin::%s(): main loop received waitpid " - "exit status info: pid=%i (%s), status=%i", - __FUNCTION__, pid, - (pid == m_pid) ? "the inferior" : "not the inferior", status); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): main loop received waitpid " + "exit status info: pid=%i (%s), status=%i", + __FUNCTION__, pid, + (pid == m_pid) ? "the inferior" : "not the inferior", status); SetExitStatus(WaitStatus::Decode(status), notify_status); return error; @@ -1096,10 +1087,10 @@ task_t NativeProcessDarwin::TaskPortForProcessID(Status &error, if ((m_task == TASK_NULL) || force) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (m_pid == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("NativeProcessDarwin::%s(): cannot get task due " - "to invalid pid", - __FUNCTION__); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): cannot get task due " + "to invalid pid", + __FUNCTION__); return TASK_NULL; } @@ -1115,19 +1106,21 @@ task_t NativeProcessDarwin::TaskPortForProcessID(Status &error, // Succeeded. Save and return it. error.Clear(); m_task = task; - log->Printf("NativeProcessDarwin::%s(): ::task_for_pid(" - "stub_port = 0x%4.4x, pid = %llu, &task) " - "succeeded: inferior task port = 0x%4.4x", - __FUNCTION__, task_self, m_pid, m_task); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): ::task_for_pid(" + "stub_port = 0x%4.4x, pid = %llu, &task) " + "succeeded: inferior task port = 0x%4.4x", + __FUNCTION__, task_self, m_pid, m_task); return m_task; } else { // Failed to get the task for the inferior process. error.SetError(err, eErrorTypeMachKernel); if (log) { - log->Printf("NativeProcessDarwin::%s(): ::task_for_pid(" - "stub_port = 0x%4.4x, pid = %llu, &task) " - "failed, err = 0x%8.8x (%s)", - __FUNCTION__, task_self, m_pid, err, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): ::task_for_pid(" + "stub_port = 0x%4.4x, pid = %llu, &task) " + "failed, err = 0x%8.8x (%s)", + __FUNCTION__, task_self, m_pid, err, error.AsCString()); } } @@ -1156,20 +1149,21 @@ Status NativeProcessDarwin::PrivateResume() { if (log) { if (m_auto_resume_signo) - log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming (with " - "unhandled interrupt signal %i)...", - __FUNCTION__, m_task, m_auto_resume_signo); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): task 0x%x resuming (with " + "unhandled interrupt signal %i)...", + __FUNCTION__, m_task, m_auto_resume_signo); else - log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming...", - __FUNCTION__, m_task); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): task 0x%x resuming...", + __FUNCTION__, m_task); } error = ReplyToAllExceptions(); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): aborting, failed to " - "reply to exceptions: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): aborting, failed to " + "reply to exceptions: %s", + __FUNCTION__, error.AsCString()); return error; } // bool stepOverBreakInstruction = step; @@ -1196,9 +1190,8 @@ Status NativeProcessDarwin::ReplyToAllExceptions() { TaskPortForProcessID(error); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): no task port, aborting", - __FUNCTION__); + LLDB_LOGF(log, "NativeProcessDarwin::%s(): no task port, aborting", + __FUNCTION__); return error; } @@ -1211,9 +1204,10 @@ Status NativeProcessDarwin::ReplyToAllExceptions() { size_t index = 0; for (auto &message : m_exception_messages) { if (log) { - log->Printf("NativeProcessDarwin::%s(): replying to exception " - "%zu...", - __FUNCTION__, index++); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): replying to exception " + "%zu...", + __FUNCTION__, index++); } int thread_reply_signal = 0; @@ -1234,9 +1228,10 @@ Status NativeProcessDarwin::ReplyToAllExceptions() { if (error.Fail() && log) { // We log any error here, but we don't stop the exception response // handling. - log->Printf("NativeProcessDarwin::%s(): failed to reply to " - "exception: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to reply to " + "exception: %s", + __FUNCTION__, error.AsCString()); error.Clear(); } } @@ -1253,10 +1248,10 @@ Status NativeProcessDarwin::ResumeTask() { TaskPortForProcessID(error); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to get task port " - "for process when attempting to resume: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to get task port " + "for process when attempting to resume: %s", + __FUNCTION__, error.AsCString()); return error; } if (m_task == TASK_NULL) { @@ -1265,20 +1260,20 @@ Status NativeProcessDarwin::ResumeTask() { return error; } - if (log) - log->Printf("NativeProcessDarwin::%s(): requesting resume of task " - "0x%4.4x", - __FUNCTION__, m_task); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): requesting resume of task " + "0x%4.4x", + __FUNCTION__, m_task); // Get the BasicInfo struct to verify that we're suspended before we try to // resume the task. struct task_basic_info task_info; error = GetTaskBasicInfo(m_task, &task_info); if (error.Fail()) { - if (log) - log->Printf("NativeProcessDarwin::%s(): failed to get task " - "BasicInfo when attempting to resume: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): failed to get task " + "BasicInfo when attempting to resume: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -1289,16 +1284,16 @@ Status NativeProcessDarwin::ResumeTask() { error.SetError(mach_err, eErrorTypeMachKernel); if (log) { if (error.Success()) - log->Printf("::task_resume(target_task = 0x%4.4x): success", m_task); + LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x): success", m_task); else - log->Printf("::task_resume(target_task = 0x%4.4x) error: %s", m_task, - error.AsCString()); + LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x) error: %s", m_task, + error.AsCString()); } } else { - if (log) - log->Printf("::task_resume(target_task = 0x%4.4x): ignored, " - "already running", - m_task); + LLDB_LOGF(log, + "::task_resume(target_task = 0x%4.4x): ignored, " + "already running", + m_task); } return error; @@ -1353,11 +1348,11 @@ NativeProcessDarwin::GetTaskBasicInfo(task_t task, auto err = ::task_info(m_task, TASK_BASIC_INFO, (task_info_t)info, &count); error.SetError(err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("::task_info(target_task = 0x%4.4x, " - "flavor = TASK_BASIC_INFO, task_info_out => %p, " - "task_info_outCnt => %u) failed: %u (%s)", - m_task, info, count, error.GetError(), error.AsCString()); + LLDB_LOGF(log, + "::task_info(target_task = 0x%4.4x, " + "flavor = TASK_BASIC_INFO, task_info_out => %p, " + "task_info_outCnt => %u) failed: %u (%s)", + m_task, info, count, error.GetError(), error.AsCString()); return error; } @@ -1368,11 +1363,12 @@ NativeProcessDarwin::GetTaskBasicInfo(task_t task, (float)info->user_time.microseconds / 1000000.0f; float system = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f; - verbose_log->Printf("task_basic_info = { suspend_count = %i, " - "virtual_size = 0x%8.8llx, resident_size = " - "0x%8.8llx, user_time = %f, system_time = %f }", - info->suspend_count, (uint64_t)info->virtual_size, - (uint64_t)info->resident_size, user, system); + verbose_LLDB_LOGF(log, + "task_basic_info = { suspend_count = %i, " + "virtual_size = 0x%8.8llx, resident_size = " + "0x%8.8llx, user_time = %f, system_time = %f }", + info->suspend_count, (uint64_t)info->virtual_size, + (uint64_t)info->resident_size, user, system); } return error; } @@ -1383,16 +1379,15 @@ Status NativeProcessDarwin::SuspendTask() { if (m_task == TASK_NULL) { error.SetErrorString("task port is null, cannot suspend task"); - if (log) - log->Printf("NativeProcessDarwin::%s() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "NativeProcessDarwin::%s() failed: %s", __FUNCTION__, + error.AsCString()); return error; } auto mach_err = ::task_suspend(m_task); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail() && log) - log->Printf("::task_suspend(target_task = 0x%4.4x)", m_task); + LLDB_LOGF(log, "::task_suspend(target_task = 0x%4.4x)", m_task); return error; } @@ -1401,8 +1396,7 @@ Status NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) { Status error; Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__); + LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__); if (CanResume()) { m_thread_actions = resume_actions; @@ -1412,10 +1406,10 @@ Status NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) { auto state = GetState(); if (state == eStateRunning) { - if (log) - log->Printf("NativeProcessDarwin::%s(): task 0x%x is already " - "running, ignoring...", - __FUNCTION__, TaskPortForProcessID(error)); + LLDB_LOGF(log, + "NativeProcessDarwin::%s(): task 0x%x is already " + "running, ignoring...", + __FUNCTION__, TaskPortForProcessID(error)); return error; } diff --git a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp index 89de92a6df4d..1faa5b219cbc 100644 --- a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp +++ b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp @@ -301,10 +301,10 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); std::lock_guard<std::recursive_mutex> locker(m_threads_mutex); - if (log) - log->Printf("NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = " - "%u) process stop count = %u", - __FUNCTION__, process.GetID(), update, process.GetStopID()); + LLDB_LOGF(log, + "NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = " + "%u) process stop count = %u", + __FUNCTION__, process.GetID(), update, process.GetStopID()); if (process.GetStopID() == 0) { // On our first stop, we'll record details like 32/64 bitness and select @@ -346,11 +346,11 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process, auto mach_err = ::task_threads(task, &thread_list, &thread_list_count); error.SetError(mach_err, eErrorTypeMachKernel); if (error.Fail()) { - if (log) - log->Printf("::task_threads(task = 0x%4.4x, thread_list => %p, " - "thread_list_count => %u) failed: %u (%s)", - task, thread_list, thread_list_count, error.GetError(), - error.AsCString()); + LLDB_LOGF(log, + "::task_threads(task = 0x%4.4x, thread_list => %p, " + "thread_list_count => %u) failed: %u (%s)", + task, thread_list, thread_list_count, error.GetError(), + error.AsCString()); return 0; } diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index 749835531279..0a49f96f54a1 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -288,9 +288,8 @@ void FreeBSDThread::DidStop() { void FreeBSDThread::WillResume(lldb::StateType resume_state) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("tid %lu resume_state = %s", GetID(), - lldb_private::StateAsCString(resume_state)); + LLDB_LOGF(log, "tid %lu resume_state = %s", GetID(), + lldb_private::StateAsCString(resume_state)); ProcessSP process_sp(GetProcess()); ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get()); int signo = GetResumeSignal(); @@ -322,9 +321,8 @@ bool FreeBSDThread::Resume() { bool status; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, - StateAsCString(resume_state)); + LLDB_LOGF(log, "FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, + StateAsCString(resume_state)); switch (resume_state) { default: @@ -352,9 +350,8 @@ bool FreeBSDThread::Resume() { void FreeBSDThread::Notify(const ProcessMessage &message) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, - __FUNCTION__, message.PrintKind(), GetID()); + LLDB_LOGF(log, "FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, + __FUNCTION__, message.PrintKind(), GetID()); switch (message.GetKind()) { default: @@ -457,8 +454,7 @@ void FreeBSDThread::BreakNotify(const ProcessMessage &message) { // corresponding to our current PC. assert(GetRegisterContext()); lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); + LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); lldb::BreakpointSiteSP bp_site( GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); @@ -490,10 +486,9 @@ void FreeBSDThread::WatchNotify(const ProcessMessage &message) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); lldb::addr_t halt_addr = message.GetHWAddress(); - if (log) - log->Printf( - "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64, - __FUNCTION__, halt_addr); + LLDB_LOGF(log, + "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64, + __FUNCTION__, halt_addr); POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol(); if (reg_ctx) { @@ -527,8 +522,7 @@ void FreeBSDThread::TraceNotify(const ProcessMessage &message) { // Try to resolve the breakpoint object corresponding to the current PC. assert(GetRegisterContext()); lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); + LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); lldb::BreakpointSiteSP bp_site( GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 770794569f72..32e3320150f8 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -154,9 +154,8 @@ Status ProcessFreeBSD::DoResume() { do_step = true; } - if (log) - log->Printf("process %" PRIu64 " resuming (%s)", GetID(), - do_step ? "step" : "continue"); + LLDB_LOGF(log, "process %" PRIu64 " resuming (%s)", GetID(), + do_step ? "step" : "continue"); if (do_step && !software_single_step) m_monitor->SingleStep(GetID(), m_resume_signo); else @@ -168,9 +167,8 @@ Status ProcessFreeBSD::DoResume() { bool ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - if (log) - log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, - GetID()); + LLDB_LOGF(log, "ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, + GetID()); std::vector<lldb::pid_t> tds; if (!GetMonitor().GetCurrentThreadIDs(tds)) { @@ -183,20 +181,18 @@ bool ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadSP thread_sp(old_thread_list_copy.RemoveThreadByID(tid, false)); if (!thread_sp) { thread_sp.reset(new FreeBSDThread(*this, tid)); - if (log) - log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid); + LLDB_LOGF(log, "ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, + tid); } else { - if (log) - log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, - tid); + LLDB_LOGF(log, "ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, + tid); } new_thread_list.AddThread(thread_sp); } for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) { ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); if (old_thread_sp) { - if (log) - log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__); + LLDB_LOGF(log, "ProcessFreeBSD::%s remove tid", __FUNCTION__); } } @@ -698,14 +694,13 @@ Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) { user_id_t watchID = wp->GetID(); addr_t addr = wp->GetLoadAddress(); Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); + LLDB_LOGF(log, "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); if (wp->IsEnabled()) { - if (log) - log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", + watchID, (uint64_t)addr); return error; } @@ -753,14 +748,13 @@ Status ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) { user_id_t watchID = wp->GetID(); addr_t addr = wp->GetLoadAddress(); Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", - watchID); + LLDB_LOGF(log, "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", + watchID); if (!wp->IsEnabled()) { - if (log) - log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", + watchID, (uint64_t)addr); // This is needed (for now) to keep watchpoints disabled correctly wp->SetEnabled(false, notify); return error; @@ -970,8 +964,9 @@ Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (log) { - log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr); - log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + LLDB_LOGF(log, "SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, + addr); } // Validate the address. @@ -982,11 +977,10 @@ Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, Breakpoint *const sw_step_break = m_process->GetTarget().CreateBreakpoint(addr, true, false).get(); sw_step_break->SetCallback(SingleStepBreakpointHit, this, true); - sw_step_break->SetBreakpointKind("software-signle-step"); + sw_step_break->SetBreakpointKind("software-single-step"); - if (log) - log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS", - __FUNCTION__, addr); + LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS", + __FUNCTION__, addr); m_threads_stepping_with_breakpoint.insert({tid, sw_step_break->GetID()}); return Status(); diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 4b9225db5e39..ff3fb0a75e2d 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -37,9 +37,6 @@ using namespace lldb; using namespace lldb_private; -// We disable the tracing of ptrace calls for integration builds to avoid the -// additional indirection and checks. -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION // Wrapper for ptrace to catch errors and log calls. const char *Get_PT_IO_OP(int op) { @@ -66,13 +63,14 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (log) { - log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", - reqName, pid, addr, data, file, line); + LLDB_LOGF(log, + "ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", + reqName, pid, addr, data, file, line); if (req == PT_IO) { struct ptrace_io_desc *pi = (struct ptrace_io_desc *)addr; - log->Printf("PT_IO: op=%s offs=%zx size=%zu", Get_PT_IO_OP(pi->piod_op), - (size_t)pi->piod_offs, pi->piod_len); + LLDB_LOGF(log, "PT_IO: op=%s offs=%zx size=%zu", + Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len); } } @@ -101,7 +99,7 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, default: str = "<unknown>"; } - log->Printf("ptrace() failed; errno=%d (%s)", errno, str); + LLDB_LOGF(log, "ptrace() failed; errno=%d (%s)", errno, str); } if (log) { @@ -109,15 +107,15 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, if (req == PT_GETREGS) { struct reg *r = (struct reg *)addr; - log->Printf("PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", - r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); + LLDB_LOGF(log, "PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", + r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); } if (req == PT_GETDBREGS || req == PT_SETDBREGS) { struct dbreg *r = (struct dbreg *)addr; char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; for (int i = 0; i <= 7; i++) - log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); + LLDB_LOGF(log, "PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); } #endif } @@ -136,9 +134,6 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) { #define PTRACE(req, pid, addr, data) \ PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) -#else -PtraceWrapper((req), (pid), (addr), (data)) -#endif // Static implementations of ProcessMonitor::ReadMemory and // ProcessMonitor::WriteMemory. This enables mutual recursion between these @@ -708,7 +703,7 @@ ProcessMonitor::ProcessMonitor( const lldb_private::ProcessLaunchInfo & /* launch_info */, lldb_private::Status &error) : m_process(static_cast<ProcessFreeBSD *>(process)), - m_operation_thread(nullptr), m_monitor_thread(nullptr), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) { + m_operation_thread(), m_monitor_thread(), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) { using namespace std::placeholders; std::unique_ptr<LaunchArgs> args( @@ -735,20 +730,22 @@ ProcessMonitor::ProcessMonitor( } // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( + llvm::Expected<lldb_private::HostThread> monitor_thread = + Host::StartMonitoringChildProcess( std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); - if (!m_monitor_thread->IsJoinable()) { + if (!monitor_thread || !monitor_thread->IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process launch failed."); return; } + m_monitor_thread = *monitor_thread; } ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, lldb_private::Status &error) : m_process(static_cast<ProcessFreeBSD *>(process)), - m_operation_thread(nullptr), m_monitor_thread(nullptr), m_pid(pid), m_terminal_fd(-1), m_operation(0) { + m_operation_thread(), m_monitor_thread(), m_pid(pid), m_terminal_fd(-1), m_operation(0) { using namespace std::placeholders; sem_init(&m_operation_pending, 0, 0); @@ -773,14 +770,16 @@ ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, } // Finally, start monitoring the child process for change in state. - m_monitor_thread = Host::StartMonitoringChildProcess( + llvm::Expected<lldb_private::HostThread> monitor_thread = + Host::StartMonitoringChildProcess( std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); - if (!m_monitor_thread->IsJoinable()) { + if (!monitor_thread || !monitor_thread->IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process attach failed."); return; } + m_monitor_thread = *monitor_thread; } ProcessMonitor::~ProcessMonitor() { StopMonitor(); } @@ -789,13 +788,15 @@ ProcessMonitor::~ProcessMonitor() { StopMonitor(); } void ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Status &error) { static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (m_operation_thread->IsJoinable()) + if (m_operation_thread && m_operation_thread->IsJoinable()) return; - m_operation_thread = - ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args); - if (!m_operation_thread) - error = m_operation_thread.takeError(); + llvm::Expected<lldb_private::HostThread> operation_thread = + ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args); + if (operation_thread) + m_operation_thread = *operation_thread; + else + error = operation_thread.takeError(); } void *ProcessMonitor::LaunchOpThread(void *arg) { @@ -957,14 +958,15 @@ void ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Status &error) { static const char *g_thread_name = "lldb.process.freebsd.operation"; - if (m_operation_thread->IsJoinable()) + if (m_operation_thread && m_operation_thread->IsJoinable()) return; - m_operation_thread = - ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args); - - if (!m_operation_thread) - error = m_operation_thread.takeError(); + llvm::Expected<lldb_private::HostThread> operation_thread = + ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args); + if (operation_thread) + m_operation_thread = *operation_thread; + else + error = operation_thread.takeError(); } void *ProcessMonitor::AttachOpThread(void *arg) { @@ -1037,9 +1039,8 @@ bool ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (exited) { - if (log) - log->Printf("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, - __FUNCTION__, pid); + LLDB_LOGF(log, "ProcessMonitor::%s() got exit signal, tid = %" PRIu64, + __FUNCTION__, pid); message = ProcessMessage::Exit(pid, status); process->SendMessage(message); return pid == process->GetID(); @@ -1087,10 +1088,10 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, unsigned long data = 0; if (!monitor->GetEventMessage(tid, &data)) data = -1; - if (log) - log->Printf("ProcessMonitor::%s() received exit? event, data = %lx, tid " - "= %" PRIu64, - __FUNCTION__, data, tid); + LLDB_LOGF(log, + "ProcessMonitor::%s() received exit? event, data = %lx, tid " + "= %" PRIu64, + __FUNCTION__, data, tid); message = ProcessMessage::Limbo(tid, (data >> 8)); break; } @@ -1101,26 +1102,25 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, // Map TRAP_CAP to a trace trap in the absense of a more specific handler. case TRAP_CAP: #endif - if (log) - log->Printf("ProcessMonitor::%s() received trace event, tid = %" PRIu64 - " : si_code = %d", - __FUNCTION__, tid, info->si_code); + LLDB_LOGF(log, + "ProcessMonitor::%s() received trace event, tid = %" PRIu64 + " : si_code = %d", + __FUNCTION__, tid, info->si_code); message = ProcessMessage::Trace(tid); break; case SI_KERNEL: case TRAP_BRKPT: if (monitor->m_process->IsSoftwareStepBreakpoint(tid)) { - if (log) - log->Printf("ProcessMonitor::%s() received sw single step breakpoint " - "event, tid = %" PRIu64, - __FUNCTION__, tid); + LLDB_LOGF(log, + "ProcessMonitor::%s() received sw single step breakpoint " + "event, tid = %" PRIu64, + __FUNCTION__, tid); message = ProcessMessage::Trace(tid); } else { - if (log) - log->Printf( - "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, - __FUNCTION__, tid); + LLDB_LOGF( + log, "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, + __FUNCTION__, tid); message = ProcessMessage::Break(tid); } break; @@ -1146,22 +1146,19 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, // // Similarly, ACK signals generated by this monitor. if (info->si_code == SI_USER) { - if (log) - log->Printf( - "ProcessMonitor::%s() received signal %s with code %s, pid = %d", - __FUNCTION__, - monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo), - "SI_USER", info->si_pid); + LLDB_LOGF(log, + "ProcessMonitor::%s() received signal %s with code %s, pid = %d", + __FUNCTION__, + monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo), + "SI_USER", info->si_pid); if (info->si_pid == getpid()) return ProcessMessage::SignalDelivered(tid, signo); else return ProcessMessage::Signal(tid, signo); } - if (log) - log->Printf( - "ProcessMonitor::%s() received signal %s", __FUNCTION__, - monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo)); + LLDB_LOGF(log, "ProcessMonitor::%s() received signal %s", __FUNCTION__, + monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo)); switch (signo) { case SIGSEGV: @@ -1313,14 +1310,14 @@ bool ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) { m_process->GetUnixSignals()->GetSignalAsCString(signo); if (signame == nullptr) signame = "<none>"; - log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", - __FUNCTION__, GetPID(), signame); + LLDB_LOGF(log, + "ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", + __FUNCTION__, GetPID(), signame); } ResumeOperation op(signo, result); DoOperation(&op); - if (log) - log->Printf("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, - result ? "true" : "false"); + LLDB_LOGF(log, "ProcessMonitor::%s() resuming result = %s", __FUNCTION__, + result ? "true" : "false"); return result; } @@ -1384,7 +1381,7 @@ bool ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, } void ProcessMonitor::StopMonitoringChildProcess() { - if (m_monitor_thread->IsJoinable()) { + if (m_monitor_thread && m_monitor_thread->IsJoinable()) { m_monitor_thread->Cancel(); m_monitor_thread->Join(nullptr); m_monitor_thread->Reset(); @@ -1422,10 +1419,9 @@ void ProcessMonitor::StopMonitor() { bool ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) { return true; } void ProcessMonitor::StopOpThread() { - if (!m_operation_thread->IsJoinable()) - return; - - m_operation_thread->Cancel(); - m_operation_thread->Join(nullptr); - m_operation_thread->Reset(); + if (m_operation_thread && m_operation_thread->IsJoinable()) { + m_operation_thread->Cancel(); + m_operation_thread->Join(nullptr); + m_operation_thread->Reset(); + } } diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 2adcc449c5c6..c5edfc0be95a 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -183,8 +183,8 @@ public: private: ProcessFreeBSD *m_process; - llvm::Expected<lldb_private::HostThread> m_operation_thread; - llvm::Expected<lldb_private::HostThread> m_monitor_thread; + llvm::Optional<lldb_private::HostThread> m_operation_thread; + llvm::Optional<lldb_private::HostThread> m_monitor_thread; lldb::pid_t m_pid; int m_terminal_fd; diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 32d20d2b1215..8b6f9fbc33c3 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -140,7 +140,7 @@ NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, const ArchSpec &arch, MainLoop &mainloop) - : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) { if (m_terminal_fd != -1) { Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); assert(status.Success()); @@ -195,6 +195,7 @@ void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { SIGSTOP, &info.psi_siginfo); } } + SetState(StateType::eStateStopped, true); } } @@ -339,12 +340,14 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { } Status error; + int signal = + action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0; switch (action->state) { case eStateRunning: { // Run the thread, possibly feeding it the signal. error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1, - action->signal); + signal); if (!error.Success()) return error; for (const auto &thread : m_threads) @@ -355,7 +358,7 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { case eStateStepping: // Run the thread, possibly feeding it the signal. error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1, - action->signal); + signal); if (!error.Success()) return error; for (const auto &thread : m_threads) @@ -658,7 +661,7 @@ NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { if (m_threads.empty()) SetCurrentThreadID(thread_id); - m_threads.push_back(llvm::make_unique<NativeThreadNetBSD>(*this, thread_id)); + m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*this, thread_id)); return static_cast<NativeThreadNetBSD &>(*m_threads.back()); } diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index e85ca3b7a925..4e7f0a1c13ab 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -9,12 +9,12 @@ #ifndef liblldb_NativeProcessNetBSD_H_ #define liblldb_NativeProcessNetBSD_H_ +#include "Plugins/Process/POSIX/NativeProcessELF.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "NativeThreadNetBSD.h" -#include "lldb/Host/common/NativeProcessProtocol.h" namespace lldb_private { namespace process_netbsd { @@ -25,7 +25,7 @@ namespace process_netbsd { /// for debugging. /// /// Changes in the inferior process state are broadcasted. -class NativeProcessNetBSD : public NativeProcessProtocol { +class NativeProcessNetBSD : public NativeProcessELF { public: class Factory : public NativeProcessProtocol::Factory { public: diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index a7cd637bf826..6cc2810fa235 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -906,8 +906,8 @@ uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint( return wp_index; } if (error.Fail() && log) { - log->Printf("NativeRegisterContextNetBSD_x86_64::%s Error: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, "NativeRegisterContextNetBSD_x86_64::%s Error: %s", + __FUNCTION__, error.AsCString()); } } return LLDB_INVALID_INDEX32; diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp index 70c2687e3b8c..9678e48436e7 100644 --- a/source/Plugins/Process/POSIX/CrashReason.cpp +++ b/source/Plugins/Process/POSIX/CrashReason.cpp @@ -229,11 +229,6 @@ std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) { } const char *CrashReasonAsString(CrashReason reason) { -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in ascii for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else const char *str = nullptr; switch (reason) { @@ -315,8 +310,6 @@ const char *CrashReasonAsString(CrashReason reason) { str = "eFloatSubscriptRange"; break; } -#endif - return str; } diff --git a/source/Plugins/Process/POSIX/NativeProcessELF.cpp b/source/Plugins/Process/POSIX/NativeProcessELF.cpp index 559b16c8fd69..058dc5ae2338 100644 --- a/source/Plugins/Process/POSIX/NativeProcessELF.cpp +++ b/source/Plugins/Process/POSIX/NativeProcessELF.cpp @@ -21,7 +21,7 @@ NativeProcessELF::GetAuxValue(enum AuxVector::EntryType type) { DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(), buffer_or_error.get()->getBufferSize(), GetByteOrder(), GetAddressByteSize()); - m_aux_vector = llvm::make_unique<AuxVector>(auxv_data); + m_aux_vector = std::make_unique<AuxVector>(auxv_data); } return m_aux_vector->GetAuxValue(type); @@ -107,4 +107,72 @@ lldb::addr_t NativeProcessELF::GetELFImageInfoAddress() { return LLDB_INVALID_ADDRESS; } -} // namespace lldb_private
\ No newline at end of file +template <typename T> +llvm::Expected<SVR4LibraryInfo> +NativeProcessELF::ReadSVR4LibraryInfo(lldb::addr_t link_map_addr) { + ELFLinkMap<T> link_map; + size_t bytes_read; + auto error = + ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read); + if (!error.Success()) + return error.ToError(); + + char name_buffer[PATH_MAX]; + llvm::Expected<llvm::StringRef> string_or_error = ReadCStringFromMemory( + link_map.l_name, &name_buffer[0], sizeof(name_buffer), bytes_read); + if (!string_or_error) + return string_or_error.takeError(); + + SVR4LibraryInfo info; + info.name = string_or_error->str(); + info.link_map = link_map_addr; + info.base_addr = link_map.l_addr; + info.ld_addr = link_map.l_ld; + info.next = link_map.l_next; + + return info; +} + +llvm::Expected<std::vector<SVR4LibraryInfo>> +NativeProcessELF::GetLoadedSVR4Libraries() { + // Address of DT_DEBUG.d_ptr which points to r_debug + lldb::addr_t info_address = GetSharedLibraryInfoAddress(); + if (info_address == LLDB_INVALID_ADDRESS) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid shared library info address"); + // Address of r_debug + lldb::addr_t address = 0; + size_t bytes_read; + auto status = + ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read); + if (!status.Success()) + return status.ToError(); + if (address == 0) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid r_debug address"); + // Read r_debug.r_map + lldb::addr_t link_map = 0; + status = ReadMemory(address + GetAddressByteSize(), &link_map, + GetAddressByteSize(), bytes_read); + if (!status.Success()) + return status.ToError(); + if (address == 0) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid link_map address"); + + std::vector<SVR4LibraryInfo> library_list; + while (link_map) { + llvm::Expected<SVR4LibraryInfo> info = + GetAddressByteSize() == 8 ? ReadSVR4LibraryInfo<uint64_t>(link_map) + : ReadSVR4LibraryInfo<uint32_t>(link_map); + if (!info) + return info.takeError(); + if (!info->name.empty() && info->base_addr != 0) + library_list.push_back(*info); + link_map = info->next; + } + + return library_list; +} + +} // namespace lldb_private diff --git a/source/Plugins/Process/POSIX/NativeProcessELF.h b/source/Plugins/Process/POSIX/NativeProcessELF.h index 84dc8d08a340..4fb513baebf0 100644 --- a/source/Plugins/Process/POSIX/NativeProcessELF.h +++ b/source/Plugins/Process/POSIX/NativeProcessELF.h @@ -37,6 +37,13 @@ protected: template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> lldb::addr_t GetELFImageInfoAddress(); + llvm::Expected<std::vector<SVR4LibraryInfo>> + GetLoadedSVR4Libraries() override; + + template <typename T> + llvm::Expected<SVR4LibraryInfo> + ReadSVR4LibraryInfo(lldb::addr_t link_map_addr); + std::unique_ptr<AuxVector> m_aux_vector; llvm::Optional<lldb::addr_t> m_shared_library_info_addr; }; diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp index aa8449131a68..66286dd3d9e3 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -15,11 +15,6 @@ const char *ProcessMessage::PrintCrashReason() const { } const char *ProcessMessage::PrintKind(Kind kind) { -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in ascii for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else const char *str = nullptr; switch (kind) { @@ -60,8 +55,6 @@ const char *ProcessMessage::PrintKind(Kind kind) { str = "eExecMessage"; break; } -#endif - return str; } diff --git a/source/Plugins/Process/Utility/AuxVector.cpp b/source/Plugins/Process/Utility/AuxVector.cpp index aab164ff93a6..25a1d0b5af06 100644 --- a/source/Plugins/Process/Utility/AuxVector.cpp +++ b/source/Plugins/Process/Utility/AuxVector.cpp @@ -43,9 +43,9 @@ void AuxVector::DumpToLog(lldb_private::Log *log) const { log->PutCString("AuxVector: "); for (auto entry : m_auxv_entries) { - log->Printf(" %s [%" PRIu64 "]: %" PRIx64, - GetEntryName(static_cast<EntryType>(entry.first)), entry.first, - entry.second); + LLDB_LOGF(log, " %s [%" PRIu64 "]: %" PRIx64, + GetEntryName(static_cast<EntryType>(entry.first)), entry.first, + entry.second); } } diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 1afe4d920599..a86880af2260 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -137,76 +137,67 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, // ends at static RegularExpression g_bitfield_regex( llvm::StringRef("([A-Za-z_][A-Za-z0-9_]*)\\[([0-9]+):([0-9]+)\\]")); - RegularExpression::Match regex_match(3); - if (g_bitfield_regex.Execute(slice_str, ®ex_match)) { - llvm::StringRef reg_name_str; - std::string msbit_str; - std::string lsbit_str; - if (regex_match.GetMatchAtIndex(slice_str, 1, reg_name_str) && - regex_match.GetMatchAtIndex(slice_str, 2, msbit_str) && - regex_match.GetMatchAtIndex(slice_str, 3, lsbit_str)) { - const uint32_t msbit = - StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); - const uint32_t lsbit = - StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); - if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { - if (msbit > lsbit) { - const uint32_t msbyte = msbit / 8; - const uint32_t lsbyte = lsbit / 8; - - ConstString containing_reg_name(reg_name_str); - - const RegisterInfo *containing_reg_info = - GetRegisterInfo(containing_reg_name); - if (containing_reg_info) { - const uint32_t max_bit = containing_reg_info->byte_size * 8; - if (msbit < max_bit && lsbit < max_bit) { - m_invalidate_regs_map[containing_reg_info - ->kinds[eRegisterKindLLDB]] - .push_back(i); - m_value_regs_map[i].push_back( - containing_reg_info->kinds[eRegisterKindLLDB]); - m_invalidate_regs_map[i].push_back( - containing_reg_info->kinds[eRegisterKindLLDB]); - - if (byte_order == eByteOrderLittle) { - success = true; - reg_info.byte_offset = - containing_reg_info->byte_offset + lsbyte; - } else if (byte_order == eByteOrderBig) { - success = true; - reg_info.byte_offset = - containing_reg_info->byte_offset + msbyte; - } else { - llvm_unreachable("Invalid byte order"); - } + llvm::SmallVector<llvm::StringRef, 4> matches; + if (g_bitfield_regex.Execute(slice_str, &matches)) { + std::string reg_name_str = matches[1].str(); + std::string msbit_str = matches[2].str(); + std::string lsbit_str = matches[3].str(); + const uint32_t msbit = + StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); + const uint32_t lsbit = + StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); + if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { + if (msbit > lsbit) { + const uint32_t msbyte = msbit / 8; + const uint32_t lsbyte = lsbit / 8; + + ConstString containing_reg_name(reg_name_str); + + const RegisterInfo *containing_reg_info = + GetRegisterInfo(containing_reg_name); + if (containing_reg_info) { + const uint32_t max_bit = containing_reg_info->byte_size * 8; + if (msbit < max_bit && lsbit < max_bit) { + m_invalidate_regs_map[containing_reg_info + ->kinds[eRegisterKindLLDB]] + .push_back(i); + m_value_regs_map[i].push_back( + containing_reg_info->kinds[eRegisterKindLLDB]); + m_invalidate_regs_map[i].push_back( + containing_reg_info->kinds[eRegisterKindLLDB]); + + if (byte_order == eByteOrderLittle) { + success = true; + reg_info.byte_offset = + containing_reg_info->byte_offset + lsbyte; + } else if (byte_order == eByteOrderBig) { + success = true; + reg_info.byte_offset = + containing_reg_info->byte_offset + msbyte; } else { - if (msbit > max_bit) - printf("error: msbit (%u) must be less than the bitsize " - "of the register (%u)\n", - msbit, max_bit); - else - printf("error: lsbit (%u) must be less than the bitsize " - "of the register (%u)\n", - lsbit, max_bit); + llvm_unreachable("Invalid byte order"); } } else { - printf("error: invalid concrete register \"%s\"\n", - containing_reg_name.GetCString()); + if (msbit > max_bit) + printf("error: msbit (%u) must be less than the bitsize " + "of the register (%u)\n", + msbit, max_bit); + else + printf("error: lsbit (%u) must be less than the bitsize " + "of the register (%u)\n", + lsbit, max_bit); } } else { - printf("error: msbit (%u) must be greater than lsbit (%u)\n", - msbit, lsbit); + printf("error: invalid concrete register \"%s\"\n", + containing_reg_name.GetCString()); } } else { - printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, - lsbit); + printf("error: msbit (%u) must be greater than lsbit (%u)\n", + msbit, lsbit); } } else { - // TODO: print error invalid slice string that doesn't follow the - // format - printf("error: failed to extract regex matches for parsing the " - "register bitfield regex\n"); + printf("error: msbit (%u) and lsbit (%u) must be valid\n", msbit, + lsbit); } } else { // TODO: print error invalid slice string that doesn't follow the @@ -545,6 +536,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { if (!generic_regs_specified) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::aarch64_be: for (auto ® : m_regs) { if (strcmp(reg.name, "pc") == 0) diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp index 3cb583172623..295c17e474fb 100644 --- a/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/source/Plugins/Process/Utility/HistoryThread.cpp @@ -32,17 +32,15 @@ HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid, m_queue_id(LLDB_INVALID_QUEUE_ID) { m_unwinder_up.reset(new HistoryUnwind(*this, pcs)); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p HistoryThread::HistoryThread", static_cast<void *>(this)); + LLDB_LOGF(log, "%p HistoryThread::HistoryThread", static_cast<void *>(this)); } // Destructor HistoryThread::~HistoryThread() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", - static_cast<void *>(this), GetID()); + LLDB_LOGF(log, "%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", + static_cast<void *>(this), GetID()); DestroyThread(); } diff --git a/source/Plugins/Process/Utility/HistoryUnwind.cpp b/source/Plugins/Process/Utility/HistoryUnwind.cpp index 7d473bff8200..83fdb011f5a1 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -51,13 +51,15 @@ HistoryUnwind::DoCreateRegisterContextForFrame(StackFrame *frame) { } bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &pc) { + lldb::addr_t &pc, + bool &behaves_like_zeroth_frame) { // FIXME do not throw away the lock after we acquire it.. std::unique_lock<std::recursive_mutex> guard(m_unwind_mutex); guard.unlock(); if (frame_idx < m_pcs.size()) { cfa = frame_idx; pc = m_pcs[frame_idx]; + behaves_like_zeroth_frame = (frame_idx == 0); return true; } return false; diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h index 6c4522e6b35b..4d16608bd8c2 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/source/Plugins/Process/Utility/HistoryUnwind.h @@ -29,7 +29,8 @@ protected: DoCreateRegisterContextForFrame(StackFrame *frame) override; bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &pc) override; + lldb::addr_t &pc, + bool &behaves_like_zeroth_frame) override; uint32_t DoGetFrameCount() override; private: diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 9beaf2fc7ac8..2ccbeacc4960 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -12,7 +12,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Host/Config.h" -#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" @@ -41,13 +41,13 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, if (thread == nullptr) return false; - const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; - const uint32_t count = process->GetTarget().GetImages().FindFunctions( + process->GetTarget().GetImages().FindFunctions( ConstString("mmap"), eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); + const uint32_t count = sc_list.GetSize(); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { @@ -79,17 +79,23 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, AddressRange mmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) { - ClangASTContext *clang_ast_context = - process->GetTarget().GetScratchClangASTContext(); - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + auto type_system_or_err = + process->GetTarget().GetScratchTypeSystemForLanguage( + eLanguageTypeC); + if (!type_system_or_err) { + llvm::consumeError(type_system_or_err.takeError()); + return false; + } + CompilerType void_ptr_type = + type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid) + .GetPointerType(); const ArchSpec arch = process->GetTarget().GetArchitecture(); MmapArgList args = process->GetTarget().GetPlatform()->GetMmapArgumentList( arch, addr, length, prot_arg, flags, fd, offset); lldb::ThreadPlanSP call_plan_sp( new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), - clang_void_ptr_type, args, options)); + void_ptr_type, args, options)); if (call_plan_sp) { DiagnosticManager diagnostics; @@ -129,13 +135,13 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, if (thread == nullptr) return false; - const bool append = true; const bool include_symbols = true; const bool include_inlines = false; SymbolContextList sc_list; - const uint32_t count = process->GetTarget().GetImages().FindFunctions( + process->GetTarget().GetImages().FindFunctions( ConstString("munmap"), eFunctionNameTypeFull, include_symbols, - include_inlines, append, sc_list); + include_inlines, sc_list); + const uint32_t count = sc_list.GetSize(); if (count > 0) { SymbolContext sc; if (sc_list.GetContextAtIndex(0, sc)) { @@ -178,60 +184,3 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, return false; } - -// FIXME: This has nothing to do with Posix, it is just a convenience function -// that calls a -// function of the form "void * (*)(void)". We should find a better place to -// put this. - -bool lldb_private::InferiorCall(Process *process, const Address *address, - addr_t &returned_func, bool trap_exceptions) { - Thread *thread = - process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == nullptr || address == nullptr) - return false; - - EvaluateExpressionOptions options; - options.SetStopOthers(true); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetTryAllThreads(true); - options.SetDebug(false); - options.SetTimeout(process->GetUtilityExpressionTimeout()); - options.SetTrapExceptions(trap_exceptions); - - ClangASTContext *clang_ast_context = - process->GetTarget().GetScratchClangASTContext(); - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::ThreadPlanSP call_plan_sp( - new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, - llvm::ArrayRef<addr_t>(), options)); - if (call_plan_sp) { - DiagnosticManager diagnostics; - - StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); - if (frame) { - ExecutionContext exe_ctx; - frame->CalculateExecutionContext(exe_ctx); - ExpressionResults result = - process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); - if (result == eExpressionCompleted) { - returned_func = - call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( - LLDB_INVALID_ADDRESS); - - if (process->GetAddressByteSize() == 4) { - if (returned_func == UINT32_MAX) - return false; - } else if (process->GetAddressByteSize() == 8) { - if (returned_func == UINT64_MAX) - return false; - } - return true; - } - } - } - - return false; -} diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/source/Plugins/Process/Utility/InferiorCallPOSIX.h index 04316801b351..2008c5fe0b91 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.h +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.h @@ -30,9 +30,6 @@ bool InferiorCallMmap(Process *proc, lldb::addr_t &allocated_addr, bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length); -bool InferiorCall(Process *proc, const Address *address, - lldb::addr_t &returned_func, bool trap_exceptions = false); - } // namespace lldb_private #endif // lldb_InferiorCallPOSIX_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index e804a4d251f7..4ca33c248c6f 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -1111,9 +1111,10 @@ int RegisterContextDarwin_arm::WriteRegisterSet(uint32_t set) { void RegisterContextDarwin_arm::LogDBGRegisters(Log *log, const DBG &dbg) { if (log) { for (uint32_t i = 0; i < 16; i++) - log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { " - "0x%8.8x, 0x%8.8x }", - i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); + LLDB_LOGF(log, + "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { " + "0x%8.8x, 0x%8.8x }", + i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); } } @@ -1514,8 +1515,6 @@ uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() { // Zero is reserved for the BRP count, so don't increment it if it is zero if (g_num_supported_hw_breakpoints > 0) g_num_supported_hw_breakpoints++; - // if (log) log->Printf ("DBGDIDR=0x%8.8x (number BRP pairs = %u)", - // register_DBGDIDR, g_num_supported_hw_breakpoints); } return g_num_supported_hw_breakpoints; #else @@ -1642,8 +1641,6 @@ uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() { uint32_t register_DBGDIDR; asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); g_num_supported_hw_watchpoints = Bits32(register_DBGDIDR, 31, 28) + 1; - // if (log) log->Printf ("DBGDIDR=0x%8.8x (number WRP pairs = %u)", - // register_DBGDIDR, g_num_supported_hw_watchpoints); } return g_num_supported_hw_watchpoints; #else @@ -1656,10 +1653,6 @@ uint32_t RegisterContextDarwin_arm::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) { - // if (log) log->Printf - // ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size - // = %u, read = %u, write = %u)", addr, size, read, write); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); // Can't watch zero bytes diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 85d518a487bf..b3ec24d8905d 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -25,6 +25,11 @@ #include <memory> +#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) +#include <sys/types.h> +#include <sys/sysctl.h> +#endif + // Support building against older versions of LLVM, this macro was added // recently. #ifndef LLVM_EXTENSION @@ -285,10 +290,11 @@ int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) { void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) { if (log) { for (uint32_t i = 0; i < 16; i++) - log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 - " } WVR%-2u/WCR%-2u " - "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }", - i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); + LLDB_LOGF(log, + "BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 + " } WVR%-2u/WCR%-2u " + "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }", + i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]); } } @@ -423,7 +429,7 @@ bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - value.SetBytes(fpu.v[reg - fpu_v0].bytes.buffer, reg_info->byte_size, + value.SetBytes(fpu.v[reg - fpu_v0].bytes, reg_info->byte_size, endian::InlHostByteOrder()); break; @@ -502,7 +508,7 @@ bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info, case fpu_d31: { ProcessSP process_sp(m_thread.GetProcess()); if (process_sp.get()) { - DataExtractor regdata(&fpu.v[reg - fpu_s0], 8, process_sp->GetByteOrder(), + DataExtractor regdata(&fpu.v[reg - fpu_d0], 8, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); offset_t offset = 0; value.SetDouble(regdata.GetDouble(&offset)); @@ -615,7 +621,7 @@ bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - ::memcpy(fpu.v[reg - fpu_v0].bytes.buffer, value.GetBytes(), + ::memcpy(fpu.v[reg - fpu_v0].bytes, value.GetBytes(), value.GetByteSize()); break; diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h index 2f691c807d50..abb87e3c2348 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h @@ -73,7 +73,7 @@ public: }; struct VReg { - llvm::AlignedCharArray<16, 16> bytes; + alignas(16) char bytes[16]; }; // mirrors <mach/arm/thread_status.h> arm_neon_state64_t diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index 820d280c37f7..873713fd8373 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -496,11 +496,11 @@ int RegisterContextDarwin_i386::GetSetForNativeRegNum(int reg_num) { void RegisterContextDarwin_i386::LogGPR(Log *log, const char *title) { if (log) { if (title) - log->Printf("%s", title); + LLDB_LOGF(log, "%s", title); for (uint32_t i = 0; i < k_num_gpr_registers; i++) { uint32_t reg = gpr_eax + i; - log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, - (&gpr.eax)[reg]); + LLDB_LOGF(log, "%12s = 0x%8.8x", g_register_infos[reg].name, + (&gpr.eax)[reg]); } } } diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index 62e512adc9f7..47758ce85eb2 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -554,22 +554,6 @@ int RegisterContextDarwin_x86_64::GetSetForNativeRegNum(int reg_num) { return -1; } -void RegisterContextDarwin_x86_64::LogGPR(Log *log, const char *format, ...) { - if (log) { - if (format) { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } - for (uint32_t i = 0; i < k_num_gpr_registers; i++) { - uint32_t reg = gpr_rax + i; - log->Printf("%12s = 0x%16.16" PRIx64, g_register_infos[reg].name, - (&gpr.rax)[reg]); - } - } -} - int RegisterContextDarwin_x86_64::ReadGPR(bool force) { int set = GPRRegSet; if (force || !RegisterSetIsCached(set)) { diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 76646d8897d1..49a589f14989 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -12,12 +12,14 @@ #include "lldb/Core/Value.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ArmUnwindInfo.h" +#include "lldb/Symbol/CallFrameInfo.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" @@ -150,15 +152,8 @@ void RegisterContextLLDB::InitializeZerothFrame() { UnwindLogMsg("using architectural default unwind method"); } - // We require either a symbol or function in the symbols context to be - // successfully filled in or this context is of no use to us. - const SymbolContextItem resolve_scope = - eSymbolContextFunction | eSymbolContextSymbol; - if (pc_module_sp.get() && (pc_module_sp->ResolveSymbolContextForAddress( - m_current_pc, resolve_scope, m_sym_ctx) & - resolve_scope)) { - m_sym_ctx_valid = true; - } + AddressRange addr_range; + m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); if (m_sym_ctx.symbol) { UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", @@ -172,9 +167,6 @@ void RegisterContextLLDB::InitializeZerothFrame() { current_pc); } - AddressRange addr_range; - m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range); - if (IsTrapHandlerSymbol(process, m_sym_ctx)) { m_frame_type = eTrapHandlerFrame; } else { @@ -436,24 +428,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { return; } - bool resolve_tail_call_address = false; // m_current_pc can be one past the - // address range of the function... - // If the saved pc does not point to a function/symbol because it is beyond - // the bounds of the correct function and there's no symbol there, we do - // *not* want ResolveSymbolContextForAddress to back up the pc by 1, because - // then we might not find the correct unwind information later. Instead, let - // ResolveSymbolContextForAddress fail, and handle the case via - // decr_pc_and_recompute_addr_range below. - const SymbolContextItem resolve_scope = - eSymbolContextFunction | eSymbolContextSymbol; - uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress( - m_current_pc, resolve_scope, m_sym_ctx, resolve_tail_call_address); - - // We require either a symbol or function in the symbols context to be - // successfully filled in or this context is of no use to us. - if (resolve_scope & resolved_scope) { - m_sym_ctx_valid = true; - } + AddressRange addr_range; + m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); if (m_sym_ctx.symbol) { UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc, @@ -467,25 +443,30 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { pc); } - AddressRange addr_range; - if (!m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range)) { - m_sym_ctx_valid = false; - } + bool decr_pc_and_recompute_addr_range; - bool decr_pc_and_recompute_addr_range = false; - - // If the symbol lookup failed... - if (!m_sym_ctx_valid) + if (!m_sym_ctx_valid) { + // Always decrement and recompute if the symbol lookup failed decr_pc_and_recompute_addr_range = true; - - // Or if we're in the middle of the stack (and not "above" an asynchronous - // event like sigtramp), and our "current" pc is the start of a function... - if (GetNextFrame()->m_frame_type != eTrapHandlerFrame && - GetNextFrame()->m_frame_type != eDebuggerFrame && - (!m_sym_ctx_valid || - (addr_range.GetBaseAddress().IsValid() && - addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() && - addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()))) { + } else if (GetNextFrame()->m_frame_type == eTrapHandlerFrame || + GetNextFrame()->m_frame_type == eDebuggerFrame) { + // Don't decrement if we're "above" an asynchronous event like + // sigtramp. + decr_pc_and_recompute_addr_range = false; + } else if (!addr_range.GetBaseAddress().IsValid() || + addr_range.GetBaseAddress().GetSection() != m_current_pc.GetSection() || + addr_range.GetBaseAddress().GetOffset() != m_current_pc.GetOffset()) { + // If our "current" pc isn't the start of a function, no need + // to decrement and recompute. + decr_pc_and_recompute_addr_range = false; + } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) { + // Signal dispatch may set the return address of the handler it calls to + // point to the first byte of a return trampoline (like __kernel_rt_sigreturn), + // so do not decrement and recompute if the symbol we already found is a trap + // handler. + decr_pc_and_recompute_addr_range = false; + } else { + // Decrement to find the function containing the call. decr_pc_and_recompute_addr_range = true; } @@ -502,18 +483,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { Address temporary_pc; temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget()); m_sym_ctx.Clear(false); - m_sym_ctx_valid = false; - SymbolContextItem resolve_scope = - eSymbolContextFunction | eSymbolContextSymbol; - - ModuleSP temporary_module_sp = temporary_pc.GetModule(); - if (temporary_module_sp && - temporary_module_sp->ResolveSymbolContextForAddress( - temporary_pc, resolve_scope, m_sym_ctx) & - resolve_scope) { - if (m_sym_ctx.GetAddressRange(resolve_scope, 0, false, addr_range)) - m_sym_ctx_valid = true; - } + m_sym_ctx_valid = temporary_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); + UnwindLogMsg("Symbol is now %s", GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); } @@ -563,6 +534,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind(); + PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp); if (active_row.get() && log) { StreamString active_row_strm; active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, @@ -575,6 +547,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) { active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(valid_offset); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind(); + PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); if (active_row.get() && log) { StreamString active_row_strm; active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), @@ -812,6 +785,16 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { unwind_plan_sp.reset(); } + CallFrameInfo *object_file_unwind = + pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo(); + if (object_file_unwind) { + unwind_plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric); + if (object_file_unwind->GetUnwindPlan(m_current_pc, *unwind_plan_sp)) + return unwind_plan_sp; + else + unwind_plan_sp.reset(); + } + return arch_default_unwind_plan_sp; } @@ -824,6 +807,9 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { m_fast_unwind_plan_sp.reset(); unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); + if (!unwind_plan_sp) + unwind_plan_sp = + func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { return unwind_plan_sp; @@ -846,6 +832,9 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { // intend) or compact unwind (this won't work) unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget()); + if (!unwind_plan_sp) + unwind_plan_sp = + func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget()); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because the " "DynamicLoader suggested we prefer it", @@ -1512,8 +1501,7 @@ RegisterContextLLDB::SavedLocationForRegister( process->GetByteOrder(), process->GetAddressByteSize()); ModuleSP opcode_ctx; - DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, - unwindplan_regloc.GetDWARFExpressionLength()); + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); dwarfexpr.SetRegisterKind(unwindplan_registerkind); Value cfa_val = Scalar(m_cfa); cfa_val.SetValueType(Value::eValueTypeLoadAddress); @@ -1698,6 +1686,7 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() { // We've copied the fallback unwind plan into the full - now clear the // fallback. m_fallback_unwind_plan_sp.reset(); + PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); } return true; @@ -1741,6 +1730,8 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() { m_cfa = new_cfa; + PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp); + UnwindLogMsg("switched unconditionally to the fallback unwindplan %s", m_full_unwind_plan_sp->GetSourceName().GetCString()); return true; @@ -1748,6 +1739,53 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() { return false; } +void RegisterContextLLDB::PropagateTrapHandlerFlagFromUnwindPlan( + lldb::UnwindPlanSP unwind_plan) { + if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) { + // Unwind plan does not indicate trap handler. Do nothing. We may + // already be flagged as trap handler flag due to the symbol being + // in the trap handler symbol list, and that should take precedence. + return; + } else if (m_frame_type != eNormalFrame) { + // If this is already a trap handler frame, nothing to do. + // If this is a skip or debug or invalid frame, don't override that. + return; + } + + m_frame_type = eTrapHandlerFrame; + + if (m_current_offset_backed_up_one != m_current_offset) { + // We backed up the pc by 1 to compute the symbol context, but + // now need to undo that because the pc of the trap handler + // frame may in fact be the first instruction of a signal return + // trampoline, rather than the instruction after a call. This + // happens on systems where the signal handler dispatch code, rather + // than calling the handler and being returned to, jumps to the + // handler after pushing the address of a return trampoline on the + // stack -- on these systems, when the handler returns, control will + // be transferred to the return trampoline, so that's the best + // symbol we can present in the callstack. + UnwindLogMsg("Resetting current offset and re-doing symbol lookup; " + "old symbol was %s", + GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + m_current_offset_backed_up_one = m_current_offset; + + AddressRange addr_range; + m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx, &addr_range); + + UnwindLogMsg("Symbol is now %s", + GetSymbolOrFunctionName(m_sym_ctx).AsCString("")); + + ExecutionContext exe_ctx(m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + Target *target = &process->GetTarget(); + + m_start_pc = addr_range.GetBaseAddress(); + m_current_offset = + m_current_pc.GetLoadAddress(target) - m_start_pc.GetLoadAddress(target); + } +} + bool RegisterContextLLDB::ReadFrameAddress( lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa, addr_t &address) { @@ -1816,8 +1854,7 @@ bool RegisterContextLLDB::ReadFrameAddress( process->GetByteOrder(), process->GetAddressByteSize()); ModuleSP opcode_ctx; - DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0, - fa.GetDWARFExpressionLength()); + DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr); dwarfexpr.SetRegisterKind(row_register_kind); Value result; Status error; @@ -1833,12 +1870,66 @@ bool RegisterContextLLDB::ReadFrameAddress( error.AsCString()); break; } + case UnwindPlan::Row::FAValue::isRaSearch: { + Process &process = *m_thread.GetProcess(); + lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset()); + if (return_address_hint == LLDB_INVALID_ADDRESS) + return false; + const unsigned max_iterations = 256; + for (unsigned i = 0; i < max_iterations; ++i) { + Status st; + lldb::addr_t candidate_addr = + return_address_hint + i * process.GetAddressByteSize(); + lldb::addr_t candidate = + process.ReadPointerFromMemory(candidate_addr, st); + if (st.Fail()) { + UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr, + st.AsCString()); + return false; + } + Address addr; + uint32_t permissions; + if (process.GetLoadAddressPermissions(candidate, permissions) && + permissions & lldb::ePermissionsExecutable) { + address = candidate_addr; + UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address); + return true; + } + } + UnwindLogMsg("No suitable CFA found"); + break; + } default: return false; } return false; } +lldb::addr_t RegisterContextLLDB::GetReturnAddressHint(int32_t plan_offset) { + addr_t hint; + if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint)) + return LLDB_INVALID_ADDRESS; + if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol) + return LLDB_INVALID_ADDRESS; + + hint += plan_offset; + + if (auto next = GetNextFrame()) { + if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol) + return LLDB_INVALID_ADDRESS; + if (auto expected_size = + next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize( + *next->m_sym_ctx.symbol)) + hint += *expected_size; + else { + UnwindLogMsgVerbose("Could not retrieve parameter size: %s", + llvm::toString(expected_size.takeError()).c_str()); + return LLDB_INVALID_ADDRESS; + } + } + return hint; +} + // Retrieve a general purpose register value for THIS frame, as saved by the // NEXT frame, i.e. the frame that // this frame called. e.g. @@ -2077,8 +2168,9 @@ void RegisterContextLLDB::UnwindLogMsg(const char *fmt, ...) { } va_end(args); - log->Printf("%*sth%d/fr%u %s", m_frame_number < 100 ? m_frame_number : 100, - "", m_thread.GetIndexID(), m_frame_number, logmsg); + LLDB_LOGF(log, "%*sth%d/fr%u %s", + m_frame_number < 100 ? m_frame_number : 100, "", + m_thread.GetIndexID(), m_frame_number, logmsg); free(logmsg); } } @@ -2098,8 +2190,9 @@ void RegisterContextLLDB::UnwindLogMsgVerbose(const char *fmt, ...) { } va_end(args); - log->Printf("%*sth%d/fr%u %s", m_frame_number < 100 ? m_frame_number : 100, - "", m_thread.GetIndexID(), m_frame_number, logmsg); + LLDB_LOGF(log, "%*sth%d/fr%u %s", + m_frame_number < 100 ? m_frame_number : 100, "", + m_thread.GetIndexID(), m_frame_number, logmsg); free(logmsg); } } diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h index 64dd394d233b..114ac35591e7 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -120,6 +120,10 @@ private: bool IsTrapHandlerSymbol(lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const; + /// Check if the given unwind plan indicates a signal trap handler, and + /// update frame type and symbol context if so. + void PropagateTrapHandlerFlagFromUnwindPlan(lldb::UnwindPlanSP unwind_plan); + // Provide a location for where THIS function saved the CALLER's register // value // Or a frame "below" this one saved it, i.e. a function called by this one, @@ -197,6 +201,8 @@ private: bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset); + lldb::addr_t GetReturnAddressHint(int32_t plan_offset); + lldb_private::Thread &m_thread; /// diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index 99b897d441b5..db1aa1b8b093 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -109,6 +109,7 @@ RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( switch (register_info->m_target_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: m_reg_info.num_registers = k_num_registers_arm64; m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; @@ -184,6 +185,7 @@ RegisterContextPOSIX_arm64::GetRegisterSet(size_t set) { if (IsRegisterSetAvailable(set)) { switch (m_register_info_up->m_target_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: return &g_reg_sets_arm64[set]; default: assert(false && "Unhandled target architecture."); diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp b/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp new file mode 100644 index 000000000000..916d3233cde5 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_i386.cpp @@ -0,0 +1,89 @@ +//===-- RegisterContextWindows_i386.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 "RegisterContextWindows_i386.h" +#include "RegisterContext_x86.h" +#include "lldb-x86-register-enums.h" + +using namespace lldb_private; +using namespace lldb; + +namespace { +// Declare our g_register_infos structure. +typedef struct _GPR { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t eip; + uint32_t eflags; + uint32_t cs; + uint32_t fs; + uint32_t gs; + uint32_t ss; + uint32_t ds; + uint32_t es; +} GPR; + +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) + +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ +#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, \ + {kind1, kind2, kind3, kind4, lldb_##reg##_i386 }, nullptr, nullptr, \ + nullptr, 0 \ + } + +// clang-format off +static RegisterInfo g_register_infos_i386[] = { +// General purpose registers EH_Frame DWARF Generic Process Plugin +// =========================== ================== ================ ========================= ==================== + DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +}; +// clang-format on +} // namespace + +RegisterContextWindows_i386::RegisterContextWindows_i386( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch) { + assert(target_arch.GetMachine() == llvm::Triple::x86); +} + +const RegisterInfo *RegisterContextWindows_i386::GetRegisterInfo() const { + return g_register_infos_i386; +} + +uint32_t RegisterContextWindows_i386::GetRegisterCount() const { + return llvm::array_lengthof(g_register_infos_i386); +} + +uint32_t RegisterContextWindows_i386::GetUserRegisterCount() const { + return llvm::array_lengthof(g_register_infos_i386); +} + +size_t RegisterContextWindows_i386::GetGPRSize() const { return sizeof(GPR); } diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_i386.h b/source/Plugins/Process/Utility/RegisterContextWindows_i386.h new file mode 100644 index 000000000000..7779cc357526 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_i386.h @@ -0,0 +1,27 @@ +//===-- RegisterContextWindows_i386.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 liblldb_RegisterContextWindows_i386_H_ +#define liblldb_RegisterContextWindows_i386_H_ + +#include "RegisterInfoInterface.h" + +class RegisterContextWindows_i386 : public lldb_private::RegisterInfoInterface { +public: + RegisterContextWindows_i386(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + + uint32_t GetUserRegisterCount() const override; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp new file mode 100644 index 000000000000..e90584de1a44 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.cpp @@ -0,0 +1,152 @@ +//===-- RegisterContextWindows_x86_64.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 "RegisterContextWindows_x86_64.h" +#include "RegisterContext_x86.h" +#include "lldb-x86-register-enums.h" + +#include <vector> + +using namespace lldb_private; +using namespace lldb; + +namespace { +typedef struct _GPR { + uint64_t rax; + uint64_t rcx; + uint64_t rdx; + uint64_t rbx; + uint64_t rsp; + uint64_t rbp; + uint64_t rsi; + uint64_t rdi; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + uint64_t rflags; + uint16_t cs; + uint16_t fs; + uint16_t gs; + uint16_t ss; + uint16_t ds; + uint16_t es; +} GPR; + +#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { \ +#reg, alt, sizeof(((GPR *)nullptr)->reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, \ + {kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, nullptr, nullptr, \ + nullptr, 0 \ + } + +typedef struct _FPReg { + XMMReg xmm0; + XMMReg xmm1; + XMMReg xmm2; + XMMReg xmm3; + XMMReg xmm4; + XMMReg xmm5; + XMMReg xmm6; + XMMReg xmm7; + XMMReg xmm8; + XMMReg xmm9; + XMMReg xmm10; + XMMReg xmm11; + XMMReg xmm12; + XMMReg xmm13; + XMMReg xmm14; + XMMReg xmm15; +} FPReg; + +#define FPR_OFFSET(regname) \ + (sizeof(GPR) + LLVM_EXTENSION offsetof(FPReg, regname)) + +#define DEFINE_XMM(reg) \ + { \ +#reg, NULL, sizeof(((FPReg *)nullptr)->reg), FPR_OFFSET(reg), \ + eEncodingUint, eFormatVectorOfUInt64, \ + {dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_##reg##_x86_64 }, \ + nullptr, nullptr, nullptr, 0 \ + } + +// clang-format off +static RegisterInfo g_register_infos_x86_64[] = { +// General purpose registers EH_Frame DWARF Generic Process Plugin +// =========================== ================== ================ ========================= ==================== + DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), + DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), + DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_XMM(xmm0), + DEFINE_XMM(xmm1), + DEFINE_XMM(xmm2), + DEFINE_XMM(xmm3), + DEFINE_XMM(xmm4), + DEFINE_XMM(xmm5), + DEFINE_XMM(xmm6), + DEFINE_XMM(xmm7), + DEFINE_XMM(xmm8), + DEFINE_XMM(xmm9), + DEFINE_XMM(xmm10), + DEFINE_XMM(xmm11), + DEFINE_XMM(xmm12), + DEFINE_XMM(xmm13), + DEFINE_XMM(xmm14), + DEFINE_XMM(xmm15) +}; +// clang-format on +} // namespace + +RegisterContextWindows_x86_64::RegisterContextWindows_x86_64( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch) { + assert(target_arch.GetMachine() == llvm::Triple::x86_64); +} + +const RegisterInfo *RegisterContextWindows_x86_64::GetRegisterInfo() const { + return g_register_infos_x86_64; +} + +uint32_t RegisterContextWindows_x86_64::GetRegisterCount() const { + return llvm::array_lengthof(g_register_infos_x86_64); +} + +uint32_t RegisterContextWindows_x86_64::GetUserRegisterCount() const { + return llvm::array_lengthof(g_register_infos_x86_64); +} + +size_t RegisterContextWindows_x86_64::GetGPRSize() const { return sizeof(GPR); } diff --git a/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h new file mode 100644 index 000000000000..18198b5b25b3 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextWindows_x86_64.h @@ -0,0 +1,28 @@ +//===-- RegisterContextWindows_x86_64.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 liblldb_RegisterContextWindows_x86_64_H_ +#define liblldb_RegisterContextWindows_x86_64_H_ + +#include "RegisterInfoInterface.h" + +class RegisterContextWindows_x86_64 + : public lldb_private::RegisterInfoInterface { +public: + RegisterContextWindows_x86_64(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + + uint32_t GetUserRegisterCount() const override; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index f7471526d054..8b367bdc6448 100644 --- a/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -57,6 +57,7 @@ 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."); @@ -68,6 +69,7 @@ static uint32_t GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { 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])); default: diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h index 4ee0b528f229..68c12aa6e529 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -456,188 +456,265 @@ static uint32_t g_d29_invalidates[] = {fpu_v29, fpu_s29, LLDB_INVALID_REGNUM}; static uint32_t g_d30_invalidates[] = {fpu_v30, fpu_s30, LLDB_INVALID_REGNUM}; static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; +// Generates register kinds array for 64-bit general purpose registers +#define GPR64_KIND(reg, generic_kind) \ + { \ + arm64_ehframe::reg, arm64_dwarf::reg, generic_kind, LLDB_INVALID_REGNUM, \ + gpr_##reg \ + } + +// Generates register kinds array for registers with lldb kind +#define MISC_KIND(lldb_kind) \ + { \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, lldb_kind \ + } + +// Generates register kinds array for vector registers +#define VREG_KIND(reg) \ + { \ + LLDB_INVALID_REGNUM, arm64_dwarf::reg, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, fpu_##reg \ + } + +// Generates register kinds array for cpsr +#define CPSR_KIND(lldb_kind) \ + { \ + arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, \ + LLDB_INVALID_REGNUM, lldb_kind \ + } + +#define MISC_GPR_KIND(lldb_kind) CPSR_KIND(lldb_kind) +#define MISC_FPU_KIND(lldb_kind) MISC_KIND(lldb_kind) +#define MISC_EXC_KIND(lldb_kind) MISC_KIND(lldb_kind) + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64(reg, generic_kind) \ + { \ + #reg, nullptr, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint, \ + lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr, \ + nullptr, 0 \ + } + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64_ALT(reg, alt, generic_kind) \ + { \ + #reg, #alt, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint, \ + lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr, \ + nullptr, 0 \ + } + +// Defines a 32-bit general purpose pseudo register +#define DEFINE_GPR32(wreg, xreg) \ + { \ + #wreg, nullptr, 4, \ + GPR_OFFSET(gpr_##xreg) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, \ + lldb::eEncodingUint, lldb::eFormatHex, MISC_KIND(gpr_##wreg), \ + g_contained_##xreg, g_##wreg##_invalidates, nullptr, 0 \ + } + +// Defines a vector register with 16-byte size +#define DEFINE_VREG(reg) \ + { \ + #reg, nullptr, 16, FPU_OFFSET(fpu_##reg - fpu_v0), lldb::eEncodingVector, \ + lldb::eFormatVectorOfUInt8, VREG_KIND(reg), nullptr, nullptr, nullptr, \ + 0 \ + } + +// Defines S and D pseudo registers mapping over correspondig vector register +#define DEFINE_FPU_PSEUDO(reg, size, offset, vreg) \ + { \ + #reg, nullptr, size, FPU_OFFSET(fpu_##vreg - fpu_v0) + offset, \ + lldb::eEncodingIEEE754, lldb::eFormatFloat, MISC_KIND(fpu_##reg), \ + g_contained_##vreg, g_##reg##_invalidates, nullptr, 0 \ + } + +// Defines miscellaneous status and control registers like cpsr, fpsr etc +#define DEFINE_MISC_REGS(reg, size, TYPE, lldb_kind) \ + { \ + #reg, nullptr, size, TYPE##_OFFSET_NAME(reg), lldb::eEncodingUint, \ + lldb::eFormatHex, MISC_##TYPE##_KIND(lldb_kind), nullptr, nullptr, \ + nullptr, 0 \ + } + static lldb_private::RegisterInfo g_register_infos_arm64_le[] = { - // clang-format off - // General purpose registers - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVAL DYNEXPR SZ - // ===== ======= == ============= =================== ================ ================= =============== ======================== =================== ====== ============== ======= ======= == - {"x0", nullptr, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_x0}, nullptr, nullptr, nullptr, 0}, - {"x1", nullptr, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_x1}, nullptr, nullptr, nullptr, 0}, - {"x2", nullptr, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_x2}, nullptr, nullptr, nullptr, 0}, - {"x3", nullptr, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_x3}, nullptr, nullptr, nullptr, 0}, - {"x4", nullptr, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, gpr_x4}, nullptr, nullptr, nullptr, 0}, - {"x5", nullptr, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, gpr_x5}, nullptr, nullptr, nullptr, 0}, - {"x6", nullptr, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, gpr_x6}, nullptr, nullptr, nullptr, 0}, - {"x7", nullptr, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, gpr_x7}, nullptr, nullptr, nullptr, 0}, - {"x8", nullptr, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x8}, nullptr, nullptr, nullptr, 0}, - {"x9", nullptr, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x9}, nullptr, nullptr, nullptr, 0}, - {"x10", nullptr, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x10}, nullptr, nullptr, nullptr, 0}, - {"x11", nullptr, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x11}, nullptr, nullptr, nullptr, 0}, - {"x12", nullptr, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x12}, nullptr, nullptr, nullptr, 0}, - {"x13", nullptr, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x13}, nullptr, nullptr, nullptr, 0}, - {"x14", nullptr, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x14}, nullptr, nullptr, nullptr, 0}, - {"x15", nullptr, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x15}, nullptr, nullptr, nullptr, 0}, - {"x16", nullptr, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x16}, nullptr, nullptr, nullptr, 0}, - {"x17", nullptr, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x17}, nullptr, nullptr, nullptr, 0}, - {"x18", nullptr, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x18}, nullptr, nullptr, nullptr, 0}, - {"x19", nullptr, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x19}, nullptr, nullptr, nullptr, 0}, - {"x20", nullptr, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x20}, nullptr, nullptr, nullptr, 0}, - {"x21", nullptr, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x21}, nullptr, nullptr, nullptr, 0}, - {"x22", nullptr, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x22}, nullptr, nullptr, nullptr, 0}, - {"x23", nullptr, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x23}, nullptr, nullptr, nullptr, 0}, - {"x24", nullptr, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x24}, nullptr, nullptr, nullptr, 0}, - {"x25", nullptr, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x25}, nullptr, nullptr, nullptr, 0}, - {"x26", nullptr, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x26}, nullptr, nullptr, nullptr, 0}, - {"x27", nullptr, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x27}, nullptr, nullptr, nullptr, 0}, - {"x28", nullptr, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x28}, nullptr, nullptr, nullptr, 0}, - {"fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_fp}, nullptr, nullptr, nullptr, 0}, - {"lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr}, nullptr, nullptr, nullptr, 0}, - {"sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp}, nullptr, nullptr, nullptr, 0}, - {"pc", nullptr, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc}, nullptr, nullptr, nullptr, 0}, - - {"cpsr",nullptr, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, {arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr}, nullptr, nullptr, nullptr, 0}, - - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE INVALIDATES DYNEXPR SZ - // ===== ======= == ============================================== =================== ================ ================= =============== =================== =================== ====== =============== ================= ======= == - {"w0", nullptr, 4, GPR_OFFSET(0) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w0}, g_contained_x0, g_w0_invalidates, nullptr, 0}, - {"w1", nullptr, 4, GPR_OFFSET(1) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w1}, g_contained_x1, g_w1_invalidates, nullptr, 0}, - {"w2", nullptr, 4, GPR_OFFSET(2) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w2}, g_contained_x2, g_w2_invalidates, nullptr, 0}, - {"w3", nullptr, 4, GPR_OFFSET(3) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w3}, g_contained_x3, g_w3_invalidates, nullptr, 0}, - {"w4", nullptr, 4, GPR_OFFSET(4) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w4}, g_contained_x4, g_w4_invalidates, nullptr, 0}, - {"w5", nullptr, 4, GPR_OFFSET(5) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w5}, g_contained_x5, g_w5_invalidates, nullptr, 0}, - {"w6", nullptr, 4, GPR_OFFSET(6) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w6}, g_contained_x6, g_w6_invalidates, nullptr, 0}, - {"w7", nullptr, 4, GPR_OFFSET(7) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w7}, g_contained_x7, g_w7_invalidates, nullptr, 0}, - {"w8", nullptr, 4, GPR_OFFSET(8) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w8}, g_contained_x8, g_w8_invalidates, nullptr, 0}, - {"w9", nullptr, 4, GPR_OFFSET(9) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w9}, g_contained_x9, g_w9_invalidates, nullptr, 0}, - {"w10", nullptr, 4, GPR_OFFSET(10) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w10}, g_contained_x10, g_w10_invalidates, nullptr, 0}, - {"w11", nullptr, 4, GPR_OFFSET(11) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w11}, g_contained_x11, g_w11_invalidates, nullptr, 0}, - {"w12", nullptr, 4, GPR_OFFSET(12) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w12}, g_contained_x12, g_w12_invalidates, nullptr, 0}, - {"w13", nullptr, 4, GPR_OFFSET(13) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w13}, g_contained_x13, g_w13_invalidates, nullptr, 0}, - {"w14", nullptr, 4, GPR_OFFSET(14) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w14}, g_contained_x14, g_w14_invalidates, nullptr, 0}, - {"w15", nullptr, 4, GPR_OFFSET(15) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w15}, g_contained_x15, g_w15_invalidates, nullptr, 0}, - {"w16", nullptr, 4, GPR_OFFSET(16) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w16}, g_contained_x16, g_w16_invalidates, nullptr, 0}, - {"w17", nullptr, 4, GPR_OFFSET(17) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w17}, g_contained_x17, g_w17_invalidates, nullptr, 0}, - {"w18", nullptr, 4, GPR_OFFSET(18) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w18}, g_contained_x18, g_w18_invalidates, nullptr, 0}, - {"w19", nullptr, 4, GPR_OFFSET(19) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w19}, g_contained_x19, g_w19_invalidates, nullptr, 0}, - {"w20", nullptr, 4, GPR_OFFSET(20) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w20}, g_contained_x20, g_w20_invalidates, nullptr, 0}, - {"w21", nullptr, 4, GPR_OFFSET(21) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w21}, g_contained_x21, g_w21_invalidates, nullptr, 0}, - {"w22", nullptr, 4, GPR_OFFSET(22) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w22}, g_contained_x22, g_w22_invalidates, nullptr, 0}, - {"w23", nullptr, 4, GPR_OFFSET(23) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w23}, g_contained_x23, g_w23_invalidates, nullptr, 0}, - {"w24", nullptr, 4, GPR_OFFSET(24) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w24}, g_contained_x24, g_w24_invalidates, nullptr, 0}, - {"w25", nullptr, 4, GPR_OFFSET(25) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w25}, g_contained_x25, g_w25_invalidates, nullptr, 0}, - {"w26", nullptr, 4, GPR_OFFSET(26) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w26}, g_contained_x26, g_w26_invalidates, nullptr, 0}, - {"w27", nullptr, 4, GPR_OFFSET(27) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w27}, g_contained_x27, g_w27_invalidates, nullptr, 0}, - {"w28", nullptr, 4, GPR_OFFSET(28) + GPR_W_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_w28}, g_contained_x28, g_w28_invalidates, nullptr, 0}, - - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVAL DYNEXPR SZ - // ===== ======= == ============= =================== ================ ================= =============== =================== =================== ====== ============== ======= ======= == - {"v0", nullptr, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v0}, nullptr, nullptr, nullptr, 0}, - {"v1", nullptr, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v1}, nullptr, nullptr, nullptr, 0}, - {"v2", nullptr, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v2}, nullptr, nullptr, nullptr, 0}, - {"v3", nullptr, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v3}, nullptr, nullptr, nullptr, 0}, - {"v4", nullptr, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v4}, nullptr, nullptr, nullptr, 0}, - {"v5", nullptr, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v5}, nullptr, nullptr, nullptr, 0}, - {"v6", nullptr, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v6}, nullptr, nullptr, nullptr, 0}, - {"v7", nullptr, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v7}, nullptr, nullptr, nullptr, 0}, - {"v8", nullptr, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v8}, nullptr, nullptr, nullptr, 0}, - {"v9", nullptr, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v9}, nullptr, nullptr, nullptr, 0}, - {"v10", nullptr, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v10}, nullptr, nullptr, nullptr, 0}, - {"v11", nullptr, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v11}, nullptr, nullptr, nullptr, 0}, - {"v12", nullptr, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v12}, nullptr, nullptr, nullptr, 0}, - {"v13", nullptr, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v13}, nullptr, nullptr, nullptr, 0}, - {"v14", nullptr, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v14}, nullptr, nullptr, nullptr, 0}, - {"v15", nullptr, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v15}, nullptr, nullptr, nullptr, 0}, - {"v16", nullptr, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v16}, nullptr, nullptr, nullptr, 0}, - {"v17", nullptr, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v17}, nullptr, nullptr, nullptr, 0}, - {"v18", nullptr, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v18}, nullptr, nullptr, nullptr, 0}, - {"v19", nullptr, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v19}, nullptr, nullptr, nullptr, 0}, - {"v20", nullptr, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v20}, nullptr, nullptr, nullptr, 0}, - {"v21", nullptr, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v21}, nullptr, nullptr, nullptr, 0}, - {"v22", nullptr, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v22}, nullptr, nullptr, nullptr, 0}, - {"v23", nullptr, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v23}, nullptr, nullptr, nullptr, 0}, - {"v24", nullptr, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v24}, nullptr, nullptr, nullptr, 0}, - {"v25", nullptr, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v25}, nullptr, nullptr, nullptr, 0}, - {"v26", nullptr, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v26}, nullptr, nullptr, nullptr, 0}, - {"v27", nullptr, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v27}, nullptr, nullptr, nullptr, 0}, - {"v28", nullptr, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v28}, nullptr, nullptr, nullptr, 0}, - {"v29", nullptr, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v29}, nullptr, nullptr, nullptr, 0}, - {"v30", nullptr, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v30}, nullptr, nullptr, nullptr, 0}, - {"v31", nullptr, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, {LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v31}, nullptr, nullptr, nullptr, 0}, - - // NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATES DYNEXPR SZ - // ===== ======= == ============================================== =================== ================ ================= =============== =================== =================== ====== =============== ================= ======= == - {"s0", nullptr, 4, FPU_OFFSET(0) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0}, g_contained_v0, g_s0_invalidates, nullptr, 0}, - {"s1", nullptr, 4, FPU_OFFSET(1) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1}, g_contained_v1, g_s1_invalidates, nullptr, 0}, - {"s2", nullptr, 4, FPU_OFFSET(2) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2}, g_contained_v2, g_s2_invalidates, nullptr, 0}, - {"s3", nullptr, 4, FPU_OFFSET(3) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3}, g_contained_v3, g_s3_invalidates, nullptr, 0}, - {"s4", nullptr, 4, FPU_OFFSET(4) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4}, g_contained_v4, g_s4_invalidates, nullptr, 0}, - {"s5", nullptr, 4, FPU_OFFSET(5) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5}, g_contained_v5, g_s5_invalidates, nullptr, 0}, - {"s6", nullptr, 4, FPU_OFFSET(6) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6}, g_contained_v6, g_s6_invalidates, nullptr, 0}, - {"s7", nullptr, 4, FPU_OFFSET(7) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7}, g_contained_v7, g_s7_invalidates, nullptr, 0}, - {"s8", nullptr, 4, FPU_OFFSET(8) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8}, g_contained_v8, g_s8_invalidates, nullptr, 0}, - {"s9", nullptr, 4, FPU_OFFSET(9) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9}, g_contained_v9, g_s9_invalidates, nullptr, 0}, - {"s10", nullptr, 4, FPU_OFFSET(10) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10}, g_contained_v10, g_s10_invalidates, nullptr, 0}, - {"s11", nullptr, 4, FPU_OFFSET(11) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11}, g_contained_v11, g_s11_invalidates, nullptr, 0}, - {"s12", nullptr, 4, FPU_OFFSET(12) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12}, g_contained_v12, g_s12_invalidates, nullptr, 0}, - {"s13", nullptr, 4, FPU_OFFSET(13) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13}, g_contained_v13, g_s13_invalidates, nullptr, 0}, - {"s14", nullptr, 4, FPU_OFFSET(14) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14}, g_contained_v14, g_s14_invalidates, nullptr, 0}, - {"s15", nullptr, 4, FPU_OFFSET(15) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15}, g_contained_v15, g_s15_invalidates, nullptr, 0}, - {"s16", nullptr, 4, FPU_OFFSET(16) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16}, g_contained_v16, g_s16_invalidates, nullptr, 0}, - {"s17", nullptr, 4, FPU_OFFSET(17) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17}, g_contained_v17, g_s17_invalidates, nullptr, 0}, - {"s18", nullptr, 4, FPU_OFFSET(18) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18}, g_contained_v18, g_s18_invalidates, nullptr, 0}, - {"s19", nullptr, 4, FPU_OFFSET(19) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19}, g_contained_v19, g_s19_invalidates, nullptr, 0}, - {"s20", nullptr, 4, FPU_OFFSET(20) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20}, g_contained_v20, g_s20_invalidates, nullptr, 0}, - {"s21", nullptr, 4, FPU_OFFSET(21) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21}, g_contained_v21, g_s21_invalidates, nullptr, 0}, - {"s22", nullptr, 4, FPU_OFFSET(22) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22}, g_contained_v22, g_s22_invalidates, nullptr, 0}, - {"s23", nullptr, 4, FPU_OFFSET(23) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23}, g_contained_v23, g_s23_invalidates, nullptr, 0}, - {"s24", nullptr, 4, FPU_OFFSET(24) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24}, g_contained_v24, g_s24_invalidates, nullptr, 0}, - {"s25", nullptr, 4, FPU_OFFSET(25) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25}, g_contained_v25, g_s25_invalidates, nullptr, 0}, - {"s26", nullptr, 4, FPU_OFFSET(26) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26}, g_contained_v26, g_s26_invalidates, nullptr, 0}, - {"s27", nullptr, 4, FPU_OFFSET(27) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27}, g_contained_v27, g_s27_invalidates, nullptr, 0}, - {"s28", nullptr, 4, FPU_OFFSET(28) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28}, g_contained_v28, g_s28_invalidates, nullptr, 0}, - {"s29", nullptr, 4, FPU_OFFSET(29) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29}, g_contained_v29, g_s29_invalidates, nullptr, 0}, - {"s30", nullptr, 4, FPU_OFFSET(30) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30}, g_contained_v30, g_s30_invalidates, nullptr, 0}, - {"s31", nullptr, 4, FPU_OFFSET(31) + FPU_S_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31}, g_contained_v31, g_s31_invalidates, nullptr, 0}, - - {"d0", nullptr, 8, FPU_OFFSET(0) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d0}, g_contained_v0, g_d0_invalidates, nullptr, 0}, - {"d1", nullptr, 8, FPU_OFFSET(1) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d1}, g_contained_v1, g_d1_invalidates, nullptr, 0}, - {"d2", nullptr, 8, FPU_OFFSET(2) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d2}, g_contained_v2, g_d2_invalidates, nullptr, 0}, - {"d3", nullptr, 8, FPU_OFFSET(3) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d3}, g_contained_v3, g_d3_invalidates, nullptr, 0}, - {"d4", nullptr, 8, FPU_OFFSET(4) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d4}, g_contained_v4, g_d4_invalidates, nullptr, 0}, - {"d5", nullptr, 8, FPU_OFFSET(5) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d5}, g_contained_v5, g_d5_invalidates, nullptr, 0}, - {"d6", nullptr, 8, FPU_OFFSET(6) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d6}, g_contained_v6, g_d6_invalidates, nullptr, 0}, - {"d7", nullptr, 8, FPU_OFFSET(7) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d7}, g_contained_v7, g_d7_invalidates, nullptr, 0}, - {"d8", nullptr, 8, FPU_OFFSET(8) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d8}, g_contained_v8, g_d8_invalidates, nullptr, 0}, - {"d9", nullptr, 8, FPU_OFFSET(9) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d9}, g_contained_v9, g_d9_invalidates, nullptr, 0}, - {"d10", nullptr, 8, FPU_OFFSET(10) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d10}, g_contained_v10, g_d10_invalidates, nullptr, 0}, - {"d11", nullptr, 8, FPU_OFFSET(11) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d11}, g_contained_v11, g_d11_invalidates, nullptr, 0}, - {"d12", nullptr, 8, FPU_OFFSET(12) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d12}, g_contained_v12, g_d12_invalidates, nullptr, 0}, - {"d13", nullptr, 8, FPU_OFFSET(13) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d13}, g_contained_v13, g_d13_invalidates, nullptr, 0}, - {"d14", nullptr, 8, FPU_OFFSET(14) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d14}, g_contained_v14, g_d14_invalidates, nullptr, 0}, - {"d15", nullptr, 8, FPU_OFFSET(15) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d15}, g_contained_v15, g_d15_invalidates, nullptr, 0}, - {"d16", nullptr, 8, FPU_OFFSET(16) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d16}, g_contained_v16, g_d16_invalidates, nullptr, 0}, - {"d17", nullptr, 8, FPU_OFFSET(17) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d17}, g_contained_v17, g_d17_invalidates, nullptr, 0}, - {"d18", nullptr, 8, FPU_OFFSET(18) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d18}, g_contained_v18, g_d18_invalidates, nullptr, 0}, - {"d19", nullptr, 8, FPU_OFFSET(19) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d19}, g_contained_v19, g_d19_invalidates, nullptr, 0}, - {"d20", nullptr, 8, FPU_OFFSET(20) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d20}, g_contained_v20, g_d20_invalidates, nullptr, 0}, - {"d21", nullptr, 8, FPU_OFFSET(21) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d21}, g_contained_v21, g_d21_invalidates, nullptr, 0}, - {"d22", nullptr, 8, FPU_OFFSET(22) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d22}, g_contained_v22, g_d22_invalidates, nullptr, 0}, - {"d23", nullptr, 8, FPU_OFFSET(23) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d23}, g_contained_v23, g_d23_invalidates, nullptr, 0}, - {"d24", nullptr, 8, FPU_OFFSET(24) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d24}, g_contained_v24, g_d24_invalidates, nullptr, 0}, - {"d25", nullptr, 8, FPU_OFFSET(25) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d25}, g_contained_v25, g_d25_invalidates, nullptr, 0}, - {"d26", nullptr, 8, FPU_OFFSET(26) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d26}, g_contained_v26, g_d26_invalidates, nullptr, 0}, - {"d27", nullptr, 8, FPU_OFFSET(27) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d27}, g_contained_v27, g_d27_invalidates, nullptr, 0}, - {"d28", nullptr, 8, FPU_OFFSET(28) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d28}, g_contained_v28, g_d28_invalidates, nullptr, 0}, - {"d29", nullptr, 8, FPU_OFFSET(29) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d29}, g_contained_v29, g_d29_invalidates, nullptr, 0}, - {"d30", nullptr, 8, FPU_OFFSET(30) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d30}, g_contained_v30, g_d30_invalidates, nullptr, 0}, - {"d31", nullptr, 8, FPU_OFFSET(31) + FPU_D_PSEUDO_REG_ENDIAN_OFFSET, lldb::eEncodingIEEE754, lldb::eFormatFloat, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d31}, g_contained_v31, g_d31_invalidates, nullptr, 0}, - - {"fpsr", nullptr, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr}, nullptr, nullptr, nullptr, 0}, - {"fpcr", nullptr, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr}, nullptr, nullptr, nullptr, 0}, - - {"far", nullptr, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far}, nullptr, nullptr, nullptr, 0}, - {"esr", nullptr, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr}, nullptr, nullptr, nullptr, 0}, - {"exception", nullptr, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception}, nullptr, nullptr, nullptr, 0}, + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR64(x1, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR64(x2, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR64(x3, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR64(x4, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR64(x5, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GPR64(x6, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GPR64(x7, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_GPR64(x8, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x9, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x10, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x11, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x12, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x13, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x14, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x15, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x16, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x17, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x18, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x19, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x20, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x21, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x22, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x23, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x24, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x25, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x26, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x27, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x28, LLDB_INVALID_REGNUM), + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64_ALT(fp, x29, LLDB_REGNUM_GENERIC_FP), + DEFINE_GPR64_ALT(lr, x30, LLDB_REGNUM_GENERIC_RA), + DEFINE_GPR64_ALT(sp, x31, LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC), + + // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) + DEFINE_MISC_REGS(cpsr, 4, GPR, gpr_cpsr), + + // DEFINE_GPR32(name, parent name) + DEFINE_GPR32(w0, x0), + DEFINE_GPR32(w1, x1), + DEFINE_GPR32(w2, x2), + DEFINE_GPR32(w3, x3), + DEFINE_GPR32(w4, x4), + DEFINE_GPR32(w5, x5), + DEFINE_GPR32(w6, x6), + DEFINE_GPR32(w7, x7), + DEFINE_GPR32(w8, x8), + DEFINE_GPR32(w9, x9), + DEFINE_GPR32(w10, x10), + DEFINE_GPR32(w11, x11), + DEFINE_GPR32(w12, x12), + DEFINE_GPR32(w13, x13), + DEFINE_GPR32(w14, x14), + DEFINE_GPR32(w15, x15), + DEFINE_GPR32(w16, x16), + DEFINE_GPR32(w17, x17), + DEFINE_GPR32(w18, x18), + DEFINE_GPR32(w19, x19), + DEFINE_GPR32(w20, x20), + DEFINE_GPR32(w21, x21), + DEFINE_GPR32(w22, x22), + DEFINE_GPR32(w23, x23), + DEFINE_GPR32(w24, x24), + DEFINE_GPR32(w25, x25), + DEFINE_GPR32(w26, x26), + DEFINE_GPR32(w27, x27), + DEFINE_GPR32(w28, x28), + + // DEFINE_VREG(name) + DEFINE_VREG(v0), + DEFINE_VREG(v1), + DEFINE_VREG(v2), + DEFINE_VREG(v3), + DEFINE_VREG(v4), + DEFINE_VREG(v5), + DEFINE_VREG(v6), + DEFINE_VREG(v7), + DEFINE_VREG(v8), + DEFINE_VREG(v9), + DEFINE_VREG(v10), + DEFINE_VREG(v11), + DEFINE_VREG(v12), + DEFINE_VREG(v13), + DEFINE_VREG(v14), + DEFINE_VREG(v15), + DEFINE_VREG(v16), + DEFINE_VREG(v17), + DEFINE_VREG(v18), + DEFINE_VREG(v19), + DEFINE_VREG(v20), + DEFINE_VREG(v21), + DEFINE_VREG(v22), + DEFINE_VREG(v23), + DEFINE_VREG(v24), + DEFINE_VREG(v25), + DEFINE_VREG(v26), + DEFINE_VREG(v27), + DEFINE_VREG(v28), + DEFINE_VREG(v29), + DEFINE_VREG(v30), + DEFINE_VREG(v31), + + // DEFINE_FPU_PSEUDO(name, size, ENDIAN OFFSET, parent register) + DEFINE_FPU_PSEUDO(s0, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v0), + DEFINE_FPU_PSEUDO(s1, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v1), + DEFINE_FPU_PSEUDO(s2, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v2), + DEFINE_FPU_PSEUDO(s3, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v3), + DEFINE_FPU_PSEUDO(s4, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v4), + DEFINE_FPU_PSEUDO(s5, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v5), + DEFINE_FPU_PSEUDO(s6, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v6), + DEFINE_FPU_PSEUDO(s7, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v7), + DEFINE_FPU_PSEUDO(s8, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v8), + DEFINE_FPU_PSEUDO(s9, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v9), + DEFINE_FPU_PSEUDO(s10, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v10), + DEFINE_FPU_PSEUDO(s11, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v11), + DEFINE_FPU_PSEUDO(s12, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v12), + DEFINE_FPU_PSEUDO(s13, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v13), + DEFINE_FPU_PSEUDO(s14, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v14), + DEFINE_FPU_PSEUDO(s15, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v15), + DEFINE_FPU_PSEUDO(s16, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v16), + DEFINE_FPU_PSEUDO(s17, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v17), + DEFINE_FPU_PSEUDO(s18, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v18), + DEFINE_FPU_PSEUDO(s19, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v19), + DEFINE_FPU_PSEUDO(s20, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v20), + DEFINE_FPU_PSEUDO(s21, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v21), + DEFINE_FPU_PSEUDO(s22, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v22), + DEFINE_FPU_PSEUDO(s23, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v23), + DEFINE_FPU_PSEUDO(s24, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v24), + DEFINE_FPU_PSEUDO(s25, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v25), + DEFINE_FPU_PSEUDO(s26, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v26), + DEFINE_FPU_PSEUDO(s27, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v27), + DEFINE_FPU_PSEUDO(s28, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v28), + DEFINE_FPU_PSEUDO(s29, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v29), + DEFINE_FPU_PSEUDO(s30, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v30), + DEFINE_FPU_PSEUDO(s31, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v31), + + DEFINE_FPU_PSEUDO(d0, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v0), + DEFINE_FPU_PSEUDO(d1, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v1), + DEFINE_FPU_PSEUDO(d2, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v2), + DEFINE_FPU_PSEUDO(d3, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v3), + DEFINE_FPU_PSEUDO(d4, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v4), + DEFINE_FPU_PSEUDO(d5, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v5), + DEFINE_FPU_PSEUDO(d6, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v6), + DEFINE_FPU_PSEUDO(d7, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v7), + DEFINE_FPU_PSEUDO(d8, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v8), + DEFINE_FPU_PSEUDO(d9, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v9), + DEFINE_FPU_PSEUDO(d10, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v10), + DEFINE_FPU_PSEUDO(d11, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v11), + DEFINE_FPU_PSEUDO(d12, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v12), + DEFINE_FPU_PSEUDO(d13, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v13), + DEFINE_FPU_PSEUDO(d14, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v14), + DEFINE_FPU_PSEUDO(d15, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v15), + DEFINE_FPU_PSEUDO(d16, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v16), + DEFINE_FPU_PSEUDO(d17, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v17), + DEFINE_FPU_PSEUDO(d18, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v18), + DEFINE_FPU_PSEUDO(d19, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v19), + DEFINE_FPU_PSEUDO(d20, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v20), + DEFINE_FPU_PSEUDO(d21, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v21), + DEFINE_FPU_PSEUDO(d22, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v22), + DEFINE_FPU_PSEUDO(d23, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v23), + DEFINE_FPU_PSEUDO(d24, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v24), + DEFINE_FPU_PSEUDO(d25, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v25), + DEFINE_FPU_PSEUDO(d26, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v26), + DEFINE_FPU_PSEUDO(d27, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v27), + DEFINE_FPU_PSEUDO(d28, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v28), + DEFINE_FPU_PSEUDO(d29, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v29), + DEFINE_FPU_PSEUDO(d30, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v30), + DEFINE_FPU_PSEUDO(d31, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v31), + + // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) + DEFINE_MISC_REGS(fpsr, 4, FPU, fpu_fpsr), + DEFINE_MISC_REGS(fpcr, 4, FPU, fpu_fpcr), + DEFINE_MISC_REGS(far, 8, EXC, exc_far), + DEFINE_MISC_REGS(esr, 4, EXC, exc_esr), + DEFINE_MISC_REGS(exception, 4, EXC, exc_exception), {DEFINE_DBG(bvr, 0)}, {DEFINE_DBG(bvr, 1)}, diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 588015a51ef1..6d03bd534f37 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -30,331 +30,266 @@ using namespace lldb; using namespace lldb_private; const char *StopInfoMachException::GetDescription() { - if (m_description.empty() && m_value != 0) { - ExecutionContext exe_ctx(m_thread_wp.lock()); - Target *target = exe_ctx.GetTargetPtr(); - const llvm::Triple::ArchType cpu = - target ? target->GetArchitecture().GetMachine() - : llvm::Triple::UnknownArch; - - const char *exc_desc = nullptr; - const char *code_label = "code"; - const char *code_desc = nullptr; - const char *subcode_label = "subcode"; - const char *subcode_desc = nullptr; + if (!m_description.empty()) + return m_description.c_str(); + if (GetValue() == eStopReasonInvalid) + return "invalid stop reason!"; + + ExecutionContext exe_ctx(m_thread_wp.lock()); + Target *target = exe_ctx.GetTargetPtr(); + const llvm::Triple::ArchType cpu = + target ? target->GetArchitecture().GetMachine() + : llvm::Triple::UnknownArch; + + const char *exc_desc = nullptr; + const char *code_label = "code"; + const char *code_desc = nullptr; + const char *subcode_label = "subcode"; + const char *subcode_desc = nullptr; #if defined(__APPLE__) - char code_desc_buf[32]; - char subcode_desc_buf[32]; + char code_desc_buf[32]; + char subcode_desc_buf[32]; #endif - switch (m_value) { - case 1: // EXC_BAD_ACCESS - exc_desc = "EXC_BAD_ACCESS"; - subcode_label = "address"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) { - case 0xd: - code_desc = "EXC_I386_GPFLT"; - m_exc_data_count = 1; - break; - } - break; - case llvm::Triple::arm: - case llvm::Triple::thumb: - switch (m_exc_code) { - case 0x101: - code_desc = "EXC_ARM_DA_ALIGN"; - break; - case 0x102: - code_desc = "EXC_ARM_DA_DEBUG"; - break; - } + switch (m_value) { + case 1: // EXC_BAD_ACCESS + exc_desc = "EXC_BAD_ACCESS"; + subcode_label = "address"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 0xd: + code_desc = "EXC_I386_GPFLT"; + m_exc_data_count = 1; break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 0x101: - code_desc = "EXC_PPC_VM_PROT_READ"; - break; - case 0x102: - code_desc = "EXC_PPC_BADSPACE"; - break; - case 0x103: - code_desc = "EXC_PPC_UNALIGNED"; - break; - } + } + break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + switch (m_exc_code) { + case 0x101: + code_desc = "EXC_ARM_DA_ALIGN"; break; - - default: + case 0x102: + code_desc = "EXC_ARM_DA_DEBUG"; break; } break; - case 2: // EXC_BAD_INSTRUCTION - exc_desc = "EXC_BAD_INSTRUCTION"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (m_exc_code == 1) - code_desc = "EXC_I386_INVOP"; - break; + default: + break; + } + break; + + case 2: // EXC_BAD_INSTRUCTION + exc_desc = "EXC_BAD_INSTRUCTION"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (m_exc_code == 1) + code_desc = "EXC_I386_INVOP"; + break; - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_PPC_INVALID_SYSCALL"; - break; - case 2: - code_desc = "EXC_PPC_UNIPL_INST"; - break; - case 3: - code_desc = "EXC_PPC_PRIVINST"; - break; - case 4: - code_desc = "EXC_PPC_PRIVREG"; - break; - case 5: - code_desc = "EXC_PPC_TRACE"; - break; - case 6: - code_desc = "EXC_PPC_PERFMON"; - break; - } - break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (m_exc_code == 1) + code_desc = "EXC_ARM_UNDEFINED"; + break; - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (m_exc_code == 1) - code_desc = "EXC_ARM_UNDEFINED"; + default: + break; + } + break; + + case 3: // EXC_ARITHMETIC + exc_desc = "EXC_ARITHMETIC"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_I386_DIV"; break; - - default: + case 2: + code_desc = "EXC_I386_INTO"; break; - } - break; - - case 3: // EXC_ARITHMETIC - exc_desc = "EXC_ARITHMETIC"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_I386_DIV"; - break; - case 2: - code_desc = "EXC_I386_INTO"; - break; - case 3: - code_desc = "EXC_I386_NOEXT"; - break; - case 4: - code_desc = "EXC_I386_EXTOVR"; - break; - case 5: - code_desc = "EXC_I386_EXTERR"; - break; - case 6: - code_desc = "EXC_I386_EMERR"; - break; - case 7: - code_desc = "EXC_I386_BOUND"; - break; - case 8: - code_desc = "EXC_I386_SSEEXTERR"; - break; - } + case 3: + code_desc = "EXC_I386_NOEXT"; break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_PPC_OVERFLOW"; - break; - case 2: - code_desc = "EXC_PPC_ZERO_DIVIDE"; - break; - case 3: - code_desc = "EXC_PPC_FLT_INEXACT"; - break; - case 4: - code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; - break; - case 5: - code_desc = "EXC_PPC_FLT_UNDERFLOW"; - break; - case 6: - code_desc = "EXC_PPC_FLT_OVERFLOW"; - break; - case 7: - code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; - break; - } + case 4: + code_desc = "EXC_I386_EXTOVR"; break; - - default: + case 5: + code_desc = "EXC_I386_EXTERR"; + break; + case 6: + code_desc = "EXC_I386_EMERR"; + break; + case 7: + code_desc = "EXC_I386_BOUND"; + break; + case 8: + code_desc = "EXC_I386_SSEEXTERR"; break; } break; - case 4: // EXC_EMULATION - exc_desc = "EXC_EMULATION"; + default: break; + } + break; - case 5: // EXC_SOFTWARE - exc_desc = "EXC_SOFTWARE"; - if (m_exc_code == 0x10003) { - subcode_desc = "EXC_SOFT_SIGNAL"; - subcode_label = "signo"; + case 4: // EXC_EMULATION + exc_desc = "EXC_EMULATION"; + break; + + case 5: // EXC_SOFTWARE + exc_desc = "EXC_SOFTWARE"; + if (m_exc_code == 0x10003) { + subcode_desc = "EXC_SOFT_SIGNAL"; + subcode_label = "signo"; + } + break; + + case 6: // EXC_BREAKPOINT + { + exc_desc = "EXC_BREAKPOINT"; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + switch (m_exc_code) { + case 1: + code_desc = "EXC_I386_SGL"; + break; + case 2: + code_desc = "EXC_I386_BPT"; + break; } break; - case 6: // EXC_BREAKPOINT - { - exc_desc = "EXC_BREAKPOINT"; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_I386_SGL"; - break; - case 2: - code_desc = "EXC_I386_BPT"; - break; - } + case llvm::Triple::arm: + case llvm::Triple::thumb: + switch (m_exc_code) { + case 0x101: + code_desc = "EXC_ARM_DA_ALIGN"; break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (m_exc_code) { - case 1: - code_desc = "EXC_PPC_BREAKPOINT"; - break; - } + case 0x102: + code_desc = "EXC_ARM_DA_DEBUG"; break; - - case llvm::Triple::arm: - case llvm::Triple::thumb: - switch (m_exc_code) { - case 0x101: - code_desc = "EXC_ARM_DA_ALIGN"; - break; - case 0x102: - code_desc = "EXC_ARM_DA_DEBUG"; - break; - case 1: - code_desc = "EXC_ARM_BREAKPOINT"; - break; - // FIXME temporary workaround, exc_code 0 does not really mean - // EXC_ARM_BREAKPOINT - case 0: - code_desc = "EXC_ARM_BREAKPOINT"; - break; - } + case 1: + code_desc = "EXC_ARM_BREAKPOINT"; break; - - default: + // FIXME temporary workaround, exc_code 0 does not really mean + // EXC_ARM_BREAKPOINT + case 0: + code_desc = "EXC_ARM_BREAKPOINT"; break; } - } break; - - case 7: - exc_desc = "EXC_SYSCALL"; break; - case 8: - exc_desc = "EXC_MACH_SYSCALL"; + default: break; + } + } break; - case 9: - exc_desc = "EXC_RPC_ALERT"; - break; + case 7: + exc_desc = "EXC_SYSCALL"; + break; - case 10: - exc_desc = "EXC_CRASH"; - break; - case 11: - exc_desc = "EXC_RESOURCE"; + case 8: + exc_desc = "EXC_MACH_SYSCALL"; + break; + + case 9: + exc_desc = "EXC_RPC_ALERT"; + break; + + case 10: + exc_desc = "EXC_CRASH"; + break; + case 11: + exc_desc = "EXC_RESOURCE"; #if defined(__APPLE__) - { - int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code); - - code_label = "limit"; - code_desc = code_desc_buf; - subcode_label = "observed"; - subcode_desc = subcode_desc_buf; - - switch (resource_type) { - case RESOURCE_TYPE_CPU: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%", - (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code)); - snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%", - (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(m_exc_subcode)); - break; - case RESOURCE_TYPE_WAKEUPS: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d w/s", + { + int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code); + + code_label = "limit"; + code_desc = code_desc_buf; + subcode_label = "observed"; + subcode_desc = subcode_desc_buf; + + switch (resource_type) { + case RESOURCE_TYPE_CPU: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU"; + snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%", + (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code)); + snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%", + (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED( + m_exc_subcode)); + break; + case RESOURCE_TYPE_WAKEUPS: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS"; + snprintf( + code_desc_buf, sizeof(code_desc_buf), "%d w/s", (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code)); - snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s", - (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(m_exc_subcode)); - break; - case RESOURCE_TYPE_MEMORY: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", - (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code)); - subcode_desc = nullptr; - subcode_label = "unused"; - break; - case RESOURCE_TYPE_IO: - exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO"; - snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", - (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code)); - snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB", - (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));; - break; - } - } + snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s", + (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED( + m_exc_subcode)); + break; + case RESOURCE_TYPE_MEMORY: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY"; + snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", + (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code)); + subcode_desc = nullptr; + subcode_label = "unused"; + break; +#if defined(RESOURCE_TYPE_IO) + // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12. + case RESOURCE_TYPE_IO: + exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO"; + snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", + (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code)); + snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB", + (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode)); + ; + break; #endif - break; - case 12: - exc_desc = "EXC_GUARD"; - break; + } } +#endif + break; + case 12: + exc_desc = "EXC_GUARD"; + break; + } - StreamString strm; + StreamString strm; - if (exc_desc) - strm.PutCString(exc_desc); - else - strm.Printf("EXC_??? (%" PRIu64 ")", m_value); + if (exc_desc) + strm.PutCString(exc_desc); + else + strm.Printf("EXC_??? (%" PRIu64 ")", m_value); - if (m_exc_data_count >= 1) { - if (code_desc) - strm.Printf(" (%s=%s", code_label, code_desc); - else - strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); - } + if (m_exc_data_count >= 1) { + if (code_desc) + strm.Printf(" (%s=%s", code_label, code_desc); + else + strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); + } - if (m_exc_data_count >= 2) { - if (subcode_desc) - strm.Printf(", %s=%s", subcode_label, subcode_desc); - else - strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); - } + if (m_exc_data_count >= 2) { + if (subcode_desc) + strm.Printf(", %s=%s", subcode_label, subcode_desc); + else + strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); + } - if (m_exc_data_count > 0) - strm.PutChar(')'); + if (m_exc_data_count > 0) + strm.PutChar(')'); - m_description = strm.GetString(); - } + m_description = strm.GetString(); return m_description.c_str(); } @@ -362,141 +297,62 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( Thread &thread, uint32_t exc_type, uint32_t exc_data_count, uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, bool pc_already_adjusted, bool adjust_pc_if_needed) { - if (exc_type != 0) { - uint32_t pc_decrement = 0; - ExecutionContext exe_ctx(thread.shared_from_this()); - Target *target = exe_ctx.GetTargetPtr(); - const llvm::Triple::ArchType cpu = - target ? target->GetArchitecture().GetMachine() - : llvm::Triple::UnknownArch; - - switch (exc_type) { - case 1: // EXC_BAD_ACCESS - break; - - case 2: // EXC_BAD_INSTRUCTION - switch (cpu) { - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - switch (exc_code) { - case 1: // EXC_PPC_INVALID_SYSCALL - case 2: // EXC_PPC_UNIPL_INST - case 3: // EXC_PPC_PRIVINST - case 4: // EXC_PPC_PRIVREG - break; - case 5: // EXC_PPC_TRACE - return StopInfo::CreateStopReasonToTrace(thread); - case 6: // EXC_PPC_PERFMON - break; - } - break; - - default: - break; - } - break; - - case 3: // EXC_ARITHMETIC - case 4: // EXC_EMULATION - break; - - case 5: // EXC_SOFTWARE - if (exc_code == 0x10003) // EXC_SOFT_SIGNAL - { - if (exc_sub_code == 5) { - // On MacOSX, a SIGTRAP can signify that a process has called exec, - // so we should check with our dynamic loader to verify. - ProcessSP process_sp(thread.GetProcess()); - if (process_sp) { - DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); - if (dynamic_loader && dynamic_loader->ProcessDidExec()) { - // The program was re-exec'ed - return StopInfo::CreateStopReasonWithExec(thread); - } - // if (!process_did_exec) - // { - // // We have a SIGTRAP, make sure we - // didn't exec by checking - // // for the PC being at - // "_dyld_start"... - // lldb::StackFrameSP frame_sp - // (thread.GetStackFrameAtIndex(0)); - // if (frame_sp) - // { - // const Symbol *symbol = - // frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; - // if (symbol) - // { - // if (symbol->GetName() == - // ConstString("_dyld_start")) - // process_did_exec = true; - // } - // } - // } + if (exc_type == 0) + return StopInfoSP(); + + uint32_t pc_decrement = 0; + ExecutionContext exe_ctx(thread.shared_from_this()); + Target *target = exe_ctx.GetTargetPtr(); + const llvm::Triple::ArchType cpu = + target ? target->GetArchitecture().GetMachine() + : llvm::Triple::UnknownArch; + + switch (exc_type) { + case 1: // EXC_BAD_ACCESS + case 2: // EXC_BAD_INSTRUCTION + case 3: // EXC_ARITHMETIC + case 4: // EXC_EMULATION + break; + + case 5: // EXC_SOFTWARE + if (exc_code == 0x10003) // EXC_SOFT_SIGNAL + { + if (exc_sub_code == 5) { + // On MacOSX, a SIGTRAP can signify that a process has called exec, + // so we should check with our dynamic loader to verify. + ProcessSP process_sp(thread.GetProcess()); + if (process_sp) { + DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); + if (dynamic_loader && dynamic_loader->ProcessDidExec()) { + // The program was re-exec'ed + return StopInfo::CreateStopReasonWithExec(thread); } } - return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code); } - break; - - case 6: // EXC_BREAKPOINT - { - bool is_actual_breakpoint = false; - bool is_trace_if_actual_breakpoint_missing = false; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (exc_code == 1) // EXC_I386_SGL - { - if (!exc_sub_code) { - // This looks like a plain trap. - // Have to check if there is a breakpoint here as well. When you - // single-step onto a trap, the single step stops you not to trap. - // Since we also do that check below, let's just use that logic. - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } else { - - // It's a watchpoint, then. - // The exc_sub_code indicates the data break address. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress( - (lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired - // watchpoint in the exception data. Set the hardware index if - // that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, - wp_sp->GetID()); - } - } - } else if (exc_code == 2 || // EXC_I386_BPT - exc_code == 3) // EXC_I386_BPTFLT - { - // KDP returns EXC_I386_BPTFLT for trace breakpoints - if (exc_code == 3) - is_trace_if_actual_breakpoint_missing = true; - + return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code); + } + break; + + case 6: // EXC_BREAKPOINT + { + bool is_actual_breakpoint = false; + bool is_trace_if_actual_breakpoint_missing = false; + switch (cpu) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (exc_code == 1) // EXC_I386_SGL + { + if (!exc_sub_code) { + // This looks like a plain trap. + // Have to check if there is a breakpoint here as well. When you + // single-step onto a trap, the single step stops you not to trap. + // Since we also do that check below, let's just use that logic. is_actual_breakpoint = true; - if (!pc_already_adjusted) - pc_decrement = 1; - } - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT - break; + is_trace_if_actual_breakpoint_missing = true; + } else { - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // It's a watchpoint, then, if the exc_sub_code indicates a - // known/enabled data break address from our watchpoint list. + // It's a watchpoint, then. + // The exc_sub_code indicates the data break address. lldb::WatchpointSP wp_sp; if (target) wp_sp = target->GetWatchpointList().FindByAddress( @@ -509,116 +365,148 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); - } else { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; } - } else if (exc_code == 1) // EXC_ARM_BREAKPOINT - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel - // is currently returning this so accept it - // as indicating a breakpoint until the - // kernel is fixed - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; } - break; + } else if (exc_code == 2 || // EXC_I386_BPT + exc_code == 3) // EXC_I386_BPTFLT + { + // KDP returns EXC_I386_BPTFLT for trace breakpoints + if (exc_code == 3) + is_trace_if_actual_breakpoint_missing = true; - case llvm::Triple::aarch64: { - if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT - { - // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 - // is set - is_actual_breakpoint = false; + is_actual_breakpoint = true; + if (!pc_already_adjusted) + pc_decrement = 1; + } + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (exc_code == 0x102) // EXC_ARM_DA_DEBUG + { + // It's a watchpoint, then, if the exc_sub_code indicates a + // known/enabled data break address from our watchpoint list. + lldb::WatchpointSP wp_sp; + if (target) + wp_sp = target->GetWatchpointList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired + // watchpoint in the exception data. Set the hardware index if + // that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, + wp_sp->GetID()); + } else { + is_actual_breakpoint = true; is_trace_if_actual_breakpoint_missing = true; } - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // It's a watchpoint, then, if the exc_sub_code indicates a - // known/enabled data break address from our watchpoint list. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress( - (lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) { - // Debugserver may piggyback the hardware index of the fired - // watchpoint in the exception data. Set the hardware index if - // that's the case. - if (exc_data_count >= 3) - wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); - return StopInfo::CreateStopReasonWithWatchpointID(thread, - wp_sp->GetID()); - } - // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as - // EXC_BAD_ACCESS - if (thread.GetTemporaryResumeState() == eStateStepping) - return StopInfo::CreateStopReasonToTrace(thread); - } - // It looks like exc_sub_code has the 4 bytes of the instruction that - // triggered the exception, i.e. our breakpoint opcode - is_actual_breakpoint = exc_code == 1; - break; + } else if (exc_code == 1) // EXC_ARM_BREAKPOINT + { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; + } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel + // is currently returning this so accept it + // as indicating a breakpoint until the + // kernel is fixed + { + is_actual_breakpoint = true; + is_trace_if_actual_breakpoint_missing = true; } + break; - default: - break; + case llvm::Triple::aarch64_32: + case llvm::Triple::aarch64: { + if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT + { + // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 + // is set + is_actual_breakpoint = false; + is_trace_if_actual_breakpoint_missing = true; } - - if (is_actual_breakpoint) { - RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); - addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; - - ProcessSP process_sp(thread.CalculateProcess()); - - lldb::BreakpointSiteSP bp_site_sp; - if (process_sp) - bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp && bp_site_sp->IsEnabled()) { - // Update the PC if we were asked to do so, but only do so if we find - // a breakpoint that we know about cause this could be a trap - // instruction in the code - if (pc_decrement > 0 && adjust_pc_if_needed) - reg_ctx_sp->SetPC(pc); - - // If the breakpoint is for this thread, then we'll report the hit, - // but if it is for another thread, we can just report no 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 we have an operating system - // plug-in, we might have set a thread specific breakpoint using the - // 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) || - thread.GetProcess()->GetOperatingSystem() != nullptr) - return StopInfo::CreateStopReasonWithBreakpointSiteID( - thread, bp_site_sp->GetID()); - else if (is_trace_if_actual_breakpoint_missing) - return StopInfo::CreateStopReasonToTrace(thread); - else - return StopInfoSP(); + if (exc_code == 0x102) // EXC_ARM_DA_DEBUG + { + // It's a watchpoint, then, if the exc_sub_code indicates a + // known/enabled data break address from our watchpoint list. + lldb::WatchpointSP wp_sp; + if (target) + wp_sp = target->GetWatchpointList().FindByAddress( + (lldb::addr_t)exc_sub_code); + if (wp_sp && wp_sp->IsEnabled()) { + // Debugserver may piggyback the hardware index of the fired + // watchpoint in the exception data. Set the hardware index if + // that's the case. + if (exc_data_count >= 3) + wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); + return StopInfo::CreateStopReasonWithWatchpointID(thread, + wp_sp->GetID()); } - - // Don't call this a trace if we weren't single stepping this thread. - if (is_trace_if_actual_breakpoint_missing && - thread.GetTemporaryResumeState() == eStateStepping) { + // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as + // EXC_BAD_ACCESS + if (thread.GetTemporaryResumeState() == eStateStepping) return StopInfo::CreateStopReasonToTrace(thread); - } } - } break; + // It looks like exc_sub_code has the 4 bytes of the instruction that + // triggered the exception, i.e. our breakpoint opcode + is_actual_breakpoint = exc_code == 1; + break; + } - case 7: // EXC_SYSCALL - case 8: // EXC_MACH_SYSCALL - case 9: // EXC_RPC_ALERT - case 10: // EXC_CRASH + default: break; } - return StopInfoSP(new StopInfoMachException( - thread, exc_type, exc_data_count, exc_code, exc_sub_code)); + if (is_actual_breakpoint) { + RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); + addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; + + ProcessSP process_sp(thread.CalculateProcess()); + + lldb::BreakpointSiteSP bp_site_sp; + if (process_sp) + bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); + if (bp_site_sp && bp_site_sp->IsEnabled()) { + // Update the PC if we were asked to do so, but only do so if we find + // a breakpoint that we know about cause this could be a trap + // instruction in the code + if (pc_decrement > 0 && adjust_pc_if_needed) + reg_ctx_sp->SetPC(pc); + + // If the breakpoint is for this thread, then we'll report the hit, + // but if it is for another thread, we can just report no 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 we have an operating system + // plug-in, we might have set a thread specific breakpoint using the + // 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) || + thread.GetProcess()->GetOperatingSystem() != nullptr) + return StopInfo::CreateStopReasonWithBreakpointSiteID( + thread, bp_site_sp->GetID()); + else if (is_trace_if_actual_breakpoint_missing) + return StopInfo::CreateStopReasonToTrace(thread); + else + return StopInfoSP(); + } + + // Don't call this a trace if we weren't single stepping this thread. + if (is_trace_if_actual_breakpoint_missing && + thread.GetTemporaryResumeState() == eStateStepping) { + return StopInfo::CreateStopReasonToTrace(thread); + } + } + } break; + + case 7: // EXC_SYSCALL + case 8: // EXC_MACH_SYSCALL + case 9: // EXC_RPC_ALERT + case 10: // EXC_CRASH + break; } - return StopInfoSP(); + + return StopInfoSP(new StopInfoMachException(thread, exc_type, exc_data_count, + exc_code, exc_sub_code)); } diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp index 38209fb24948..74fc90e88547 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -104,8 +104,8 @@ bool UnwindLLDB::AddFirstFrame() { unwind_done: Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); if (log) { - log->Printf("th%d Unwind of this thread is complete.", - m_thread.GetIndexID()); + LLDB_LOGF(log, "th%d Unwind of this thread is complete.", + m_thread.GetIndexID()); } m_unwind_complete = true; return false; @@ -140,10 +140,10 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { // is going to blow out the stack space. If we're still unwinding at that // point, we're probably never going to finish. if (cur_idx >= max_stack_depth) { - if (log) - log->Printf("%*sFrame %d unwound too many frames, assuming unwind has " - "gone astray, stopping.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d unwound too many frames, assuming unwind has " + "gone astray, stopping.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } @@ -161,9 +161,8 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d did not get a RegisterContext, stopping.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, "%*sFrame %d did not get a RegisterContext, stopping.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } @@ -181,10 +180,10 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d invalid RegisterContext for this frame, " - "stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d invalid RegisterContext for this frame, " + "stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } if (!reg_ctx_sp->GetCFA(cursor_sp->cfa)) { @@ -201,10 +200,9 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf( - "%*sFrame %d did not get CFA for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d did not get CFA for this frame, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa)) { @@ -230,17 +228,17 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d did not get a valid CFA for this frame, " - "stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d did not get a valid CFA for this frame, " + "stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } else { - if (log) - log->Printf("%*sFrame %d had a bad CFA value but we switched the " - "UnwindPlan being used and got one that looks more " - "realistic.", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d had a bad CFA value but we switched the " + "UnwindPlan being used and got one that looks more " + "realistic.", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); } } } @@ -258,10 +256,9 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf( - "%*sFrame %d did not get PC for this frame, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, + "%*sFrame %d did not get PC for this frame, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc)) { @@ -278,18 +275,17 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return GetOneMoreFrame(abi); } - if (log) - log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", - cur_idx < 100 ? cur_idx : 100, "", cur_idx); + LLDB_LOGF(log, "%*sFrame %d did not get a valid PC, stopping stack walk", + cur_idx < 100 ? cur_idx : 100, "", cur_idx); return nullptr; } // Infinite loop where the current cursor is the same as the previous one... if (prev_frame->start_pc == cursor_sp->start_pc && prev_frame->cfa == cursor_sp->cfa) { - if (log) - log->Printf("th%d pc of this frame is the same as the previous frame and " - "CFAs for both frames are identical -- stopping unwind", - m_thread.GetIndexID()); + LLDB_LOGF(log, + "th%d pc of this frame is the same as the previous frame and " + "CFAs for both frames are identical -- stopping unwind", + m_thread.GetIndexID()); return nullptr; } @@ -337,9 +333,8 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) { new_frame = GetOneMoreFrame(abi); if (new_frame == nullptr) { - if (log) - log->Printf("th%d Unwind of this thread is complete.", - m_thread.GetIndexID()); + LLDB_LOGF(log, "th%d Unwind of this thread is complete.", + m_thread.GetIndexID()); m_unwind_complete = true; return false; } @@ -395,7 +390,8 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) { return true; } -bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc) { +bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc, + bool &behaves_like_zeroth_frame) { if (m_frames.size() == 0) { if (!AddFirstFrame()) return false; @@ -410,6 +406,24 @@ bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc) { if (idx < m_frames.size()) { cfa = m_frames[idx]->cfa; pc = m_frames[idx]->start_pc; + if (idx == 0) { + // Frame zero always behaves like it. + behaves_like_zeroth_frame = true; + } else if (m_frames[idx - 1]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) { + // This could be an asynchronous signal, thus the + // pc might point to the interrupted instruction rather + // than a post-call instruction + behaves_like_zeroth_frame = true; + } else if (m_frames[idx]->reg_ctx_lldb_sp->IsTrapHandlerFrame()) { + // This frame may result from signal processing installing + // a pointer to the first byte of a signal-return trampoline + // in the return address slot of the frame below, so this + // too behaves like the zeroth frame (i.e. the pc might not + // be pointing just past a call in it) + behaves_like_zeroth_frame = true; + } else { + behaves_like_zeroth_frame = false; + } return true; } return false; diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h index c512929c185b..ff5db39730b5 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/source/Plugins/Process/Utility/UnwindLLDB.h @@ -73,7 +73,8 @@ protected: uint32_t DoGetFrameCount() override; bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &start_pc) override; + lldb::addr_t &start_pc, + bool &behaves_like_zeroth_frame) override; lldb::RegisterContextSP DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index 7dc5a5f5fdd1..558edeec1a37 100644 --- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -43,9 +43,8 @@ uint32_t UnwindMacOSXFrameBackchain::DoGetFrameCount() { return m_cursors.size(); } -bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx, - addr_t &cfa, - addr_t &pc) { +bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex( + uint32_t idx, addr_t &cfa, addr_t &pc, bool &behaves_like_zeroth_frame) { const uint32_t frame_count = GetFrameCount(); if (idx < frame_count) { if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS) @@ -55,6 +54,7 @@ bool UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex(uint32_t idx, pc = m_cursors[idx].pc; cfa = m_cursors[idx].fp; + behaves_like_zeroth_frame = (idx == 0); return true; } diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h index 2208bcc2f2e4..f0bde90a53be 100644 --- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h +++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h @@ -26,7 +26,8 @@ protected: uint32_t DoGetFrameCount() override; bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, - lldb::addr_t &pc) override; + lldb::addr_t &pc, + bool &behaves_like_zeroth_frame) override; lldb::RegisterContextSP DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 980169e16c51..ab23589ae9a9 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -33,6 +33,7 @@ #include "ThreadElfCore.h" using namespace lldb_private; +namespace ELF = llvm::ELF; ConstString ProcessElfCore::GetPluginNameStatic() { static ConstString g_name("elf-core"); @@ -117,16 +118,20 @@ lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment( FileRange file_range(header.p_offset, header.p_filesz); VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range); - VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); - if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && - last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() && - last_entry->GetByteSize() == last_entry->data.GetByteSize()) { - last_entry->SetRangeEnd(range_entry.GetRangeEnd()); - last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); - } else { - m_core_aranges.Append(range_entry); + // Only add to m_core_aranges if the file size is non zero. Some core files + // have PT_LOAD segments for all address ranges, but set f_filesz to zero for + // the .text sections since they can be retrieved from the object files. + if (header.p_filesz > 0) { + VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); + if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() && + last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() && + last_entry->GetByteSize() == last_entry->data.GetByteSize()) { + last_entry->SetRangeEnd(range_entry.GetRangeEnd()); + last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); + } else { + m_core_aranges.Append(range_entry); + } } - // Keep a separate map of permissions that that isn't coalesced so all ranges // are maintained. const uint32_t permissions = @@ -417,7 +422,7 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data, Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { if (pr_version > 1) - log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); + LLDB_LOGF(log, "FreeBSD PRSTATUS unexpected version %d", pr_version); } // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate @@ -521,8 +526,8 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { if (note.info.n_name != "FreeBSD") continue; - if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) || - (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) { + if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) { assert(thread_data.gpregset.GetByteSize() > 0); // Add the new thread to thread list m_thread_data.push_back(thread_data); @@ -532,19 +537,19 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { } switch (note.info.n_type) { - case FREEBSD::NT_PRSTATUS: + case ELF::NT_PRSTATUS: have_prstatus = true; ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture()); break; - case FREEBSD::NT_PRPSINFO: + case ELF::NT_PRPSINFO: have_prpsinfo = true; break; - case FREEBSD::NT_THRMISC: { + case ELF::NT_FREEBSD_THRMISC: { lldb::offset_t offset = 0; thread_data.name = note.data.GetCStr(&offset, 20); break; } - case FREEBSD::NT_PROCSTAT_AUXV: + case ELF::NT_FREEBSD_PROCSTAT_AUXV: // FIXME: FreeBSD sticks an int at the beginning of the note m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4); break; @@ -771,8 +776,8 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { if (note.info.n_name != "CORE" && note.info.n_name != "LINUX") continue; - if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) || - (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) { + if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) { assert(thread_data.gpregset.GetByteSize() > 0); // Add the new thread to thread list m_thread_data.push_back(thread_data); @@ -782,7 +787,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { } switch (note.info.n_type) { - case LINUX::NT_PRSTATUS: { + case ELF::NT_PRSTATUS: { have_prstatus = true; ELFLinuxPrStatus prstatus; Status status = prstatus.Parse(note.data, arch); @@ -795,7 +800,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { thread_data.gpregset = DataExtractor(note.data, header_size, len); break; } - case LINUX::NT_PRPSINFO: { + case ELF::NT_PRPSINFO: { have_prpsinfo = true; ELFLinuxPrPsInfo prpsinfo; Status status = prpsinfo.Parse(note.data, arch); @@ -805,7 +810,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { SetID(prpsinfo.pr_pid); break; } - case LINUX::NT_SIGINFO: { + case ELF::NT_SIGINFO: { ELFLinuxSigInfo siginfo; Status status = siginfo.Parse(note.data, arch); if (status.Fail()) @@ -813,7 +818,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { thread_data.signo = siginfo.si_signo; break; } - case LINUX::NT_FILE: { + case ELF::NT_FILE: { m_nt_file_entries.clear(); lldb::offset_t offset = 0; const uint64_t count = note.data.GetAddress(&offset); @@ -832,7 +837,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { } break; } - case LINUX::NT_AUXV: + case ELF::NT_AUXV: m_auxv = note.data; break; default: diff --git a/source/Plugins/Process/elf-core/RegisterUtilities.h b/source/Plugins/Process/elf-core/RegisterUtilities.h index d3b3373150f8..49ad425db445 100644 --- a/source/Plugins/Process/elf-core/RegisterUtilities.h +++ b/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -11,21 +11,11 @@ #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "lldb/Utility/DataExtractor.h" +#include "llvm/BinaryFormat/ELF.h" namespace lldb_private { /// Core files PT_NOTE segment descriptor types -namespace FREEBSD { -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16, - NT_PPC_VMX = 0x100 -}; -} - namespace NETBSD { enum { NT_PROCINFO = 1, NT_AUXV = 2 }; @@ -76,22 +66,6 @@ enum { }; } -namespace LINUX { -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_TASKSTRUCT, - NT_PLATFORM, - NT_AUXV, - NT_FILE = 0x46494c45, - NT_SIGINFO = 0x53494749, - NT_PPC_VMX = 0x100, - NT_PPC_VSX = 0x102, - NT_PRXFPREG = 0x46e62b7f, -}; -} - struct CoreNote { ELFNote info; DataExtractor data; @@ -122,24 +96,24 @@ DataExtractor getRegset(llvm::ArrayRef<CoreNote> Notes, llvm::ArrayRef<RegsetDesc> RegsetDescs); constexpr RegsetDesc FPR_Desc[] = { - {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_FPREGSET}, + {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. // The result from FXSAVE is in NT_PRXFPREG for i386 core files - {llvm::Triple::Linux, llvm::Triple::x86, LINUX::NT_PRXFPREG}, - {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_FPREGSET}, + {llvm::Triple::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_64, NETBSD::AMD64::NT_FPREGS}, {llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS}, }; constexpr RegsetDesc PPC_VMX_Desc[] = { - {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_PPC_VMX}, - {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VMX}, + {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, }; constexpr RegsetDesc PPC_VSX_Desc[] = { - {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VSX}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VSX}, }; } // namespace lldb_private diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index a5d1fc4a7bff..508c8a3108a6 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -181,9 +181,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { } if (!reg_interface) { - if (log) - log->Printf("elf-core::%s:: Architecture(%d) or OS(%d) not supported", - __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); + LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported", + __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS()); assert(false && "Architecture or OS not supported"); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index fe7ef6b3acea..064bbde8442e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -63,18 +63,16 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( case PacketResult::Success: break; default: - if (log) - log->Printf("GDBRemoteClientBase::%s () ReadPacket(...) => false", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteClientBase::%s () ReadPacket(...) => false", + __FUNCTION__); return eStateInvalid; } if (response.Empty()) return eStateInvalid; const char stop_type = response.GetChar(); - if (log) - log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, - response.GetStringRef().c_str()); + LLDB_LOGF(log, "GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, + response.GetStringRef().data()); switch (stop_type) { case 'W': @@ -84,9 +82,8 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( // ERROR return eStateInvalid; default: - if (log) - log->Printf("GDBRemoteClientBase::%s () unrecognized async packet", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteClientBase::%s () unrecognized async packet", + __FUNCTION__); return eStateInvalid; case 'O': { std::string inferior_stdout; @@ -162,10 +159,10 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse( if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) - log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), - send_async); + LLDB_LOGF(log, + "GDBRemoteClientBase::%s failed to get mutex, not sending " + "packet '%.*s' (send_async=%d)", + __FUNCTION__, int(payload.size()), payload.data(), send_async); return PacketResult::ErrorSendFailed; } @@ -181,10 +178,10 @@ GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport( if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) - log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), - send_async); + LLDB_LOGF(log, + "GDBRemoteClientBase::%s failed to get mutex, not sending " + "packet '%.*s' (send_async=%d)", + __FUNCTION__, int(payload.size()), payload.data(), send_async); return PacketResult::ErrorSendFailed; } @@ -214,13 +211,13 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock( return packet_result; // Response says it wasn't valid Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS); - if (log) - log->Printf( - "error: packet with payload \"%.*s\" got invalid response \"%s\": %s", - int(payload.size()), payload.data(), response.GetStringRef().c_str(), - (i == (max_response_retries - 1)) - ? "using invalid response and giving up" - : "ignoring response and waiting for another"); + LLDB_LOGF( + log, + "error: packet with payload \"%.*s\" got invalid response \"%s\": %s", + int(payload.size()), payload.data(), response.GetStringRef().data(), + (i == (max_response_retries - 1)) + ? "using invalid response and giving up" + : "ignoring response and waiting for another"); } return packet_result; } @@ -228,16 +225,14 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock( bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__); // we want to lock down packet sending while we continue Lock lock(*this, true); - if (log) - log->Printf( - "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", - __FUNCTION__, int(payload.size()), payload.data()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", + __FUNCTION__, int(payload.size()), payload.data()); if (SendPacketNoLock(payload) != PacketResult::Success) return false; @@ -315,18 +310,16 @@ void GDBRemoteClientBase::ContinueLock::unlock() { GDBRemoteClientBase::ContinueLock::LockResult GDBRemoteClientBase::ContinueLock::lock() { Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS); - if (log) - log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s", - __FUNCTION__, m_comm.m_continue_packet.c_str()); + LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() resuming with %s", + __FUNCTION__, m_comm.m_continue_packet.c_str()); lldbassert(!m_acquired); std::unique_lock<std::mutex> lock(m_comm.m_mutex); m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; }); if (m_comm.m_should_stop) { m_comm.m_should_stop = false; - if (log) - log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() cancelled", + __FUNCTION__); return LockResult::Cancelled; } if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) != @@ -368,9 +361,8 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, nullptr); if (bytes_written == 0) { --m_comm.m_async_count; - if (log) - log->Printf("GDBRemoteClientBase::Lock::Lock failed to send " - "interrupt packet"); + LLDB_LOGF(log, "GDBRemoteClientBase::Lock::Lock failed to send " + "interrupt packet"); return; } if (log) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index 54f69e8caac6..ea294ffcef26 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -24,12 +24,10 @@ public: virtual void HandleAsyncMisc(llvm::StringRef data) = 0; virtual void HandleStopReply() = 0; - // ========================================================================= /// Process asynchronously-received structured data. /// /// \param[in] data /// The complete data packet, expected to start with JSON-async. - // ========================================================================= virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0; }; @@ -83,42 +81,48 @@ protected: virtual void OnRunPacketSent(bool first); private: - // Variables handling synchronization between the Continue thread and any - // other threads - // wishing to send packets over the connection. Either the continue thread has - // control over - // the connection (m_is_running == true) or the connection is free for an - // arbitrary number of - // other senders to take which indicate their interest by incrementing - // m_async_count. - // Semantics of individual states: - // - m_continue_packet == false, m_async_count == 0: connection is free - // - m_continue_packet == true, m_async_count == 0: only continue thread is - // present - // - m_continue_packet == true, m_async_count > 0: continue thread has - // control, async threads - // should interrupt it and wait for it to set m_continue_packet to false - // - m_continue_packet == false, m_async_count > 0: async threads have - // control, continue - // thread needs to wait for them to finish (m_async_count goes down to 0). + /// Variables handling synchronization between the Continue thread and any + /// other threads wishing to send packets over the connection. Either the + /// continue thread has control over the connection (m_is_running == true) or + /// the connection is free for an arbitrary number of other senders to take + /// which indicate their interest by incrementing m_async_count. + /// + /// Semantics of individual states: + /// + /// - m_continue_packet == false, m_async_count == 0: + /// connection is free + /// - m_continue_packet == true, m_async_count == 0: + /// only continue thread is present + /// - m_continue_packet == true, m_async_count > 0: + /// continue thread has control, async threads should interrupt it and wait + /// for it to set m_continue_packet to false + /// - m_continue_packet == false, m_async_count > 0: + /// async threads have control, continue thread needs to wait for them to + /// finish (m_async_count goes down to 0). + /// @{ std::mutex m_mutex; std::condition_variable m_cv; - // Packet with which to resume after an async interrupt. Can be changed by an - // async thread - // e.g. to inject a signal. + + /// Packet with which to resume after an async interrupt. Can be changed by + /// an async thread e.g. to inject a signal. std::string m_continue_packet; - // When was the interrupt packet sent. Used to make sure we time out if the - // stub does not - // respond to interrupt requests. + + /// 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; + + /// Number of threads interested in sending. uint32_t m_async_count; + + /// Whether the continue thread has control. bool m_is_running; - bool m_should_stop; // Whether we should resume after a stop. - // end of continue thread synchronization block - // This handles the synchronization between individual async threads. For now - // they just use a - // simple mutex. + /// Whether we should resume after a stop. + bool m_should_stop; + /// @} + + /// This handles the synchronization between individual async threads. For + /// now they just use a simple mutex. std::recursive_mutex m_async_mutex; bool ShouldStop(const UnixSignals &signals, diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 11052eff948f..144ae103faa4 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -14,6 +14,7 @@ #include <sys/stat.h> #include "lldb/Core/StreamFile.h" +#include "lldb/Host/Config.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -38,6 +39,8 @@ #if defined(__APPLE__) #define DEBUGSERVER_BASENAME "debugserver" +#elif defined(_WIN32) +#define DEBUGSERVER_BASENAME "lldb-server.exe" #else #define DEBUGSERVER_BASENAME "lldb-server" #endif @@ -99,10 +102,8 @@ size_t GDBRemoteCommunication::SendAck() { ConnectionStatus status = eConnectionStatusSuccess; char ch = '+'; const size_t bytes_written = Write(&ch, 1, status, nullptr); - if (log) - log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); - m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, - bytes_written); + LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); + m_history.AddPacket(ch, GDBRemotePacket::ePacketTypeSend, bytes_written); return bytes_written; } @@ -111,10 +112,8 @@ size_t GDBRemoteCommunication::SendNack() { ConnectionStatus status = eConnectionStatusSuccess; char ch = '-'; const size_t bytes_written = Write(&ch, 1, status, nullptr); - if (log) - log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); - m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, - bytes_written); + LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); + m_history.AddPacket(ch, GDBRemotePacket::ePacketTypeSend, bytes_written); return bytes_written; } @@ -172,13 +171,12 @@ GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet, strm.Printf("%*s", (int)3, p); log->PutString(strm.GetString()); } else - log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, - (int)packet_length, packet_data); + LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %.*s", + (uint64_t)bytes_written, (int)packet_length, packet_data); } m_history.AddPacket(packet.str(), packet_length, - GDBRemoteCommunicationHistory::ePacketTypeSend, - bytes_written); + GDBRemotePacket::ePacketTypeSend, bytes_written); if (bytes_written == packet_length) { if (!skip_ack && GetSendAcks()) @@ -186,9 +184,8 @@ GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet, else return PacketResult::Success; } else { - if (log) - log->Printf("error: failed to send packet: %.*s", (int)packet_length, - packet_data); + LLDB_LOGF(log, "error: failed to send packet: %.*s", (int)packet_length, + packet_data); } } return PacketResult::ErrorSendFailed; @@ -332,11 +329,12 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, std::string regex_str = "^"; regex_str += echo_packet; regex_str += "$"; - response_regex.Compile(regex_str); + response_regex = RegularExpression(regex_str); } else { echo_packet_len = ::snprintf(echo_packet, sizeof(echo_packet), "qC"); - response_regex.Compile(llvm::StringRef("^QC[0-9A-Fa-f]+$")); + response_regex = + RegularExpression(llvm::StringRef("^QC[0-9A-Fa-f]+$")); } PacketResult echo_packet_result = @@ -489,11 +487,10 @@ bool GDBRemoteCommunication::DecompressPacket() { llvm::StringRef(m_bytes).substr(1, hash_mark_idx - 1)); bool success = packet_checksum == actual_checksum; if (!success) { - if (log) - log->Printf( - "error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", - (int)(pkt_size), m_bytes.c_str(), (uint8_t)packet_checksum, - (uint8_t)actual_checksum); + LLDB_LOGF(log, + "error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", + (int)(pkt_size), m_bytes.c_str(), (uint8_t)packet_checksum, + (uint8_t)actual_checksum); } // Send the ack or nack if needed if (!success) { @@ -651,8 +648,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, if (src && src_len > 0) { if (log && log->GetVerbose()) { StreamString s; - log->Printf("GDBRemoteCommunication::%s adding %u bytes: %.*s", - __FUNCTION__, (uint32_t)src_len, (uint32_t)src_len, src); + LLDB_LOGF(log, "GDBRemoteCommunication::%s adding %u bytes: %.*s", + __FUNCTION__, (uint32_t)src_len, (uint32_t)src_len, src); } m_bytes.append((const char *)src, src_len); } @@ -733,9 +730,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, break; } } - if (log) - log->Printf("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", - __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); + LLDB_LOGF(log, "GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", + __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); m_bytes.erase(0, idx - 1); } break; } @@ -752,7 +748,6 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, size_t content_end = content_start + content_length; bool success = true; - std::string &packet_str = packet.GetStringRef(); if (log) { // If logging was just enabled and we have history, then dump out what // we have to the log so we get the historical context. The Dump() call @@ -800,25 +795,23 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, log->PutString(strm.GetString()); } else { if (CompressionIsEnabled()) - log->Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s", - (uint64_t)original_packet_size, (uint64_t)total_length, - (int)(total_length), m_bytes.c_str()); + LLDB_LOGF(log, "<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s", + (uint64_t)original_packet_size, (uint64_t)total_length, + (int)(total_length), m_bytes.c_str()); else - log->Printf("<%4" PRIu64 "> read packet: %.*s", - (uint64_t)total_length, (int)(total_length), - m_bytes.c_str()); + LLDB_LOGF(log, "<%4" PRIu64 "> read packet: %.*s", + (uint64_t)total_length, (int)(total_length), + m_bytes.c_str()); } } m_history.AddPacket(m_bytes, total_length, - GDBRemoteCommunicationHistory::ePacketTypeRecv, - total_length); + GDBRemotePacket::ePacketTypeRecv, total_length); - // Clear packet_str in case there is some existing data in it. - packet_str.clear(); // Copy the packet from m_bytes to packet_str expanding the run-length // encoding in the process. Reserve enough byte for the most common case // (no RLE used) + std ::string packet_str; packet_str.reserve(m_bytes.length()); for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_end; ++c) { @@ -841,6 +834,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, packet_str.push_back(*c); } } + packet = StringExtractorGDBRemote(packet_str); if (m_bytes[0] == '$' || m_bytes[0] == '%') { assert(checksum_idx < m_bytes.size()); @@ -853,11 +847,11 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, llvm::StringRef(m_bytes).slice(content_start, content_end)); success = packet_checksum == actual_checksum; if (!success) { - if (log) - log->Printf("error: checksum mismatch: %.*s expected 0x%2.2x, " - "got 0x%2.2x", - (int)(total_length), m_bytes.c_str(), - (uint8_t)packet_checksum, (uint8_t)actual_checksum); + LLDB_LOGF(log, + "error: checksum mismatch: %.*s expected 0x%2.2x, " + "got 0x%2.2x", + (int)(total_length), m_bytes.c_str(), + (uint8_t)packet_checksum, (uint8_t)actual_checksum); } // Send the ack or nack if needed if (!success) @@ -867,9 +861,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, } } else { success = false; - if (log) - log->Printf("error: invalid checksum in packet: '%s'\n", - m_bytes.c_str()); + LLDB_LOGF(log, "error: invalid checksum in packet: '%s'\n", + m_bytes.c_str()); } } @@ -933,10 +926,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( const char *url, Platform *platform, ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args, int pass_comm_fd) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", - __FUNCTION__, url ? url : "<empty>", - port ? *port : uint16_t(0)); + LLDB_LOGF(log, "GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", + __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); Status error; // If we locate debugserver, keep that located version around @@ -953,10 +944,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (!env_debugserver_path.empty()) { debugserver_file_spec.SetFile(env_debugserver_path, FileSpec::Style::native); - if (log) - log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set " - "from environment variable: %s", - __FUNCTION__, env_debugserver_path.c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() gdb-remote stub exe path set " + "from environment variable: %s", + __FUNCTION__, env_debugserver_path.c_str()); } else debugserver_file_spec = g_debugserver_file_spec; bool debugserver_exists = @@ -968,10 +959,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess( debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME); debugserver_exists = FileSystem::Instance().Exists(debugserver_file_spec); if (debugserver_exists) { - if (log) - log->Printf( - "GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", - __FUNCTION__, debugserver_file_spec.GetPath().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", + __FUNCTION__, debugserver_file_spec.GetPath().c_str()); g_debugserver_file_spec = debugserver_file_spec; } else { @@ -985,10 +975,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( // exist debugserver_exists = true; } else { - if (log) - log->Printf("GDBRemoteCommunication::%s() could not find " - "gdb-remote stub exe '%s'", - __FUNCTION__, debugserver_file_spec.GetPath().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() could not find " + "gdb-remote stub exe '%s'", + __FUNCTION__, debugserver_file_spec.GetPath().c_str()); } // Don't cache the platform specific GDB server binary as it could // change from platform to platform @@ -1052,10 +1042,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "named pipe creation failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "named pipe creation failed: %s", + __FUNCTION__, error.AsCString()); return error; } debugserver_args.AppendArgument(llvm::StringRef("--named-pipe")); @@ -1065,10 +1055,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( // using using an unnamed pipe... error = socket_pipe.CreateNew(true); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "unnamed pipe creation failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "unnamed pipe creation failed: %s", + __FUNCTION__, error.AsCString()); return error; } pipe_t write = socket_pipe.GetWritePipe(); @@ -1081,10 +1071,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( // debugserver connect to us.. error = StartListenThread("127.0.0.1", 0); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() unable to start listen " - "thread: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() unable to start listen " + "thread: %s", + __FUNCTION__, error.AsCString()); return error; } @@ -1104,9 +1094,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( *port = port_; } else { error.SetErrorString("failed to bind to port 0 on 127.0.0.1"); - if (log) - log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "GDBRemoteCommunication::%s() failed: %s", + __FUNCTION__, error.AsCString()); return error; } } @@ -1148,10 +1137,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (has_env_var) { debugserver_args.AppendArgument(llvm::StringRef(extra_arg)); - if (log) - log->Printf("GDBRemoteCommunication::%s adding env var %s contents " - "to stub command line (%s)", - __FUNCTION__, env_var_name, extra_arg.c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s adding env var %s contents " + "to stub command line (%s)", + __FUNCTION__, env_var_name, extra_arg.c_str()); } } while (has_env_var); @@ -1177,8 +1166,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( StreamString string_stream; Platform *const platform = nullptr; launch_info.Dump(string_stream, platform); - log->Printf("launch info for gdb-remote stub:\n%s", - string_stream.GetData()); + LLDB_LOGF(log, "launch info for gdb-remote stub:\n%s", + string_stream.GetData()); } error = Host::LaunchProcess(launch_info); @@ -1188,11 +1177,10 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (named_pipe_path.size() > 0) { error = socket_pipe.OpenAsReader(named_pipe_path, false); if (error.Fail()) - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "failed to open named pipe %s for reading: %s", - __FUNCTION__, named_pipe_path.c_str(), - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "failed to open named pipe %s for reading: %s", + __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } if (socket_pipe.CanWrite()) @@ -1209,24 +1197,22 @@ Status GDBRemoteCommunication::StartDebugserverProcess( uint16_t child_port = StringConvert::ToUInt32(port_cstr, 0); if (*port == 0 || *port == child_port) { *port = child_port; - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "debugserver listens %u port", - __FUNCTION__, *port); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "debugserver listens %u port", + __FUNCTION__, *port); } else { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "debugserver listening on port " - "%d but requested port was %d", - __FUNCTION__, (uint32_t)child_port, - (uint32_t)(*port)); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "debugserver listening on port " + "%d but requested port was %d", + __FUNCTION__, (uint32_t)child_port, (uint32_t)(*port)); } } else { - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "failed to read a port value from pipe %s: %s", - __FUNCTION__, named_pipe_path.c_str(), - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s() " + "failed to read a port value from pipe %s: %s", + __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } socket_pipe.Close(); } @@ -1234,10 +1220,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess( if (named_pipe_path.size() > 0) { const auto err = socket_pipe.Delete(named_pipe_path); if (err.Fail()) { - if (log) - log->Printf( - "GDBRemoteCommunication::%s failed to delete pipe %s: %s", - __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunication::%s failed to delete pipe %s: %s", + __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); } } @@ -1249,9 +1234,8 @@ Status GDBRemoteCommunication::StartDebugserverProcess( } if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOGF(log, "GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, + error.AsCString()); } return error; @@ -1351,7 +1335,7 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes, if (type == PacketType::Notify) { // put this packet into an event - const char *pdata = packet.GetStringRef().c_str(); + const char *pdata = packet.GetStringRef().data(); // as the communication class, we are a broadcaster and the async thread // is tuned to listen to us diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 9797184026e0..feb9f0589cee 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -23,7 +23,6 @@ #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" @@ -35,17 +34,15 @@ #include "lldb/Utility/StringExtractorGDBRemote.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/JSON.h" -#if defined(__APPLE__) -#ifndef HAVE_LIBCOMPRESSION -#define HAVE_LIBCOMPRESSION -#endif +#if defined(HAVE_LIBCOMPRESSION) #include <compression.h> #endif using namespace lldb; -using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace lldb_private; using namespace std::chrono; // GDBRemoteCommunicationClient constructor @@ -342,7 +339,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { // not, we assume no limit // build the qSupported packet - std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"}; + std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc"}; StreamString packet; packet.PutCString("qSupported"); for (uint32_t i = 0; i < features.size(); ++i) { @@ -354,7 +351,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { if (SendPacketAndWaitForResponse(packet.GetString(), response, /*send_async=*/false) == PacketResult::Success) { - const char *response_cstr = response.GetStringRef().c_str(); + 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. @@ -439,8 +436,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { m_max_packet_size = UINT64_MAX; // Must have been a garbled response Log *log( ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("Garbled PacketSize spec in qSupported response"); + LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response"); } } } @@ -469,7 +465,7 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { m_supports_vCont_S = eLazyBoolNo; if (SendPacketAndWaitForResponse("vCont?", response, false) == PacketResult::Success) { - const char *response_cstr = response.GetStringRef().c_str(); + const char *response_cstr = response.GetStringRef().data(); if (::strstr(response_cstr, ";c")) m_supports_vCont_c = eLazyBoolYes; @@ -525,9 +521,10 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse( if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) - log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex " - "for %s packet.", - __FUNCTION__, payload.GetData()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex " + "for %s packet.", + __FUNCTION__, payload.GetData()); return PacketResult::ErrorNoSequenceLock; } @@ -660,10 +657,10 @@ GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses( if (!lock) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending " - "packets with prefix '%s'", - payload_prefix); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "packets with prefix '%s'", + payload_prefix); return PacketResult::ErrorNoSequenceLock; } @@ -934,6 +931,11 @@ llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() { return m_os_version; } +llvm::VersionTuple GDBRemoteCommunicationClient::GetMacCatalystVersion() { + GetHostInfo(); + return m_maccatalyst_version; +} + bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) { if (GetHostInfo()) { if (!m_os_build.empty()) { @@ -1136,6 +1138,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { uint32_t sub = 0; std::string arch_name; std::string os_name; + std::string environment; std::string vendor_name; std::string triple; std::string distribution_id; @@ -1175,7 +1178,11 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { extractor.GetHexByteString(m_os_kernel); ++num_keys_decoded; } else if (name.equals("ostype")) { - os_name = value; + if (value.equals("maccatalyst")) { + os_name = "ios"; + environment = "macabi"; + } else + os_name = value; ++num_keys_decoded; } else if (name.equals("vendor")) { vendor_name = value; @@ -1199,6 +1206,9 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { { if (!m_os_version.tryParse(value)) ++num_keys_decoded; + } else if (name.equals("maccatalyst_version")) { + if (!m_maccatalyst_version.tryParse(value)) + ++num_keys_decoded; } else if (name.equals("watchpoint_exceptions_received")) { m_watchpoints_trigger_after_instruction = llvm::StringSwitch<LazyBool>(value) @@ -1236,6 +1246,8 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { llvm::StringRef(vendor_name)); if (!os_name.empty()) m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + if (!environment.empty()) + m_host_arch.GetTriple().setEnvironmentName(environment); } } else { std::string triple; @@ -1259,6 +1271,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { host_triple.getOS() == llvm::Triple::Darwin) { switch (m_host_arch.GetMachine()) { case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: case llvm::Triple::arm: case llvm::Triple::thumb: host_triple.setOS(llvm::Triple::IOS); @@ -1284,14 +1297,15 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { assert(byte_order == m_host_arch.GetByteOrder()); } - if (log) - log->Printf("GDBRemoteCommunicationClient::%s parsed host " - "architecture as %s, triple as %s from triple text %s", - __FUNCTION__, m_host_arch.GetArchitectureName() - ? m_host_arch.GetArchitectureName() - : "<null-arch-name>", - m_host_arch.GetTriple().getTriple().c_str(), - triple.c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s parsed host " + "architecture as %s, triple as %s from triple text %s", + __FUNCTION__, + m_host_arch.GetArchitectureName() + ? m_host_arch.GetArchitectureName() + : "<null-arch-name>", + m_host_arch.GetTriple().getTriple().c_str(), + triple.c_str()); } if (!distribution_id.empty()) m_host_arch.SetDistributionId(distribution_id.c_str()); @@ -1893,7 +1907,7 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse( } else if (name.equals("euid")) { uint32_t uid = UINT32_MAX; value.getAsInteger(0, uid); - process_info.SetEffectiveGroupID(uid); + process_info.SetEffectiveUserID(uid); } else if (name.equals("gid")) { uint32_t gid = UINT32_MAX; value.getAsInteger(0, gid); @@ -1914,6 +1928,26 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse( std::string name; extractor.GetHexByteString(name); process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native); + } else if (name.equals("args")) { + llvm::StringRef encoded_args(value), hex_arg; + + bool is_arg0 = true; + while (!encoded_args.empty()) { + std::tie(hex_arg, encoded_args) = encoded_args.split('-'); + std::string arg; + StringExtractor extractor(hex_arg); + if (extractor.GetHexByteString(arg) * 2 != hex_arg.size()) { + // In case of wrong encoding, we discard all the arguments + process_info.GetArguments().Clear(); + process_info.SetArg0(""); + break; + } + if (is_arg0) + process_info.SetArg0(arg); + else + process_info.GetArguments().AppendArgument(arg); + is_arg0 = false; + } } else if (name.equals("cputype")) { value.getAsInteger(0, cpu); } else if (name.equals("cpusubtype")) { @@ -1987,6 +2021,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { uint32_t sub = 0; std::string arch_name; std::string os_name; + std::string environment; std::string vendor_name; std::string triple; std::string elf_abi; @@ -2007,7 +2042,11 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { extractor.GetHexByteString(triple); ++num_keys_decoded; } else if (name.equals("ostype")) { - os_name = value; + if (value.equals("maccatalyst")) { + os_name = "ios"; + environment = "macabi"; + } else + os_name = value; ++num_keys_decoded; } else if (name.equals("vendor")) { vendor_name = value; @@ -2048,6 +2087,8 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty()) { llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); + if (!environment.empty()) + triple.setEnvironmentName(environment); assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); assert(triple.getObjectFormat() != llvm::Triple::Wasm); @@ -2064,12 +2105,10 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { break; case llvm::Triple::Wasm: case llvm::Triple::XCOFF: - if (log) - log->Printf("error: not supported target architecture"); + LLDB_LOGF(log, "error: not supported target architecture"); return false; case llvm::Triple::UnknownObjectFormat: - if (log) - log->Printf("error: failed to determine target architecture"); + LLDB_LOGF(log, "error: failed to determine target architecture"); return false; } @@ -2081,8 +2120,10 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { } m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + m_process_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment)); m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); + m_host_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment)); } return true; } @@ -2156,8 +2197,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) packet.Printf("egid:%u;", match_info.GetProcessInfo().GetEffectiveGroupID()); - if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) - packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0); + packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0); if (match_info.GetProcessInfo().GetArchitecture().IsValid()) { const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture(); @@ -2178,8 +2218,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( if (!DecodeProcessInfoResponse(response, process_info)) break; process_infos.Append(process_info); - response.GetStringRef().clear(); - response.SetFilePos(0); + response = StringExtractorGDBRemote(); } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) == PacketResult::Success); } else { @@ -2641,9 +2680,8 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo( uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, - __FUNCTION__, insert ? "add" : "remove", addr); + LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, + __FUNCTION__, insert ? "add" : "remove", addr); // Check if the stub is known not to support this breakpoint type if (!SupportsGDBStoppointPacket(type)) @@ -2745,9 +2783,8 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( #if !defined(LLDB_CONFIGURATION_DEBUG) Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (log) - log->Printf("error: failed to get packet sequence mutex, not sending " - "packet 'qfThreadInfo'"); + LLDB_LOGF(log, "error: failed to get packet sequence mutex, not sending " + "packet 'qfThreadInfo'"); #endif sequence_mutex_unavailable = true; } @@ -2879,7 +2916,7 @@ static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, } lldb::user_id_t GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, - uint32_t flags, mode_t mode, + File::OpenOptions flags, mode_t mode, Status &error) { std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; @@ -3146,7 +3183,8 @@ bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) { if (arch.IsValid() && arch.GetTriple().getVendor() == llvm::Triple::Apple && arch.GetTriple().getOS() == llvm::Triple::IOS && - arch.GetTriple().getArch() == llvm::Triple::aarch64) { + (arch.GetTriple().getArch() == llvm::Triple::aarch64 || + arch.GetTriple().getArch() == llvm::Triple::aarch64_32)) { m_avoid_g_packets = eLazyBoolYes; uint32_t gdb_server_version = GetGDBServerProgramVersion(); if (gdb_server_version != 0) { @@ -3592,21 +3630,21 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { llvm::Optional<std::vector<ModuleSpec>> GDBRemoteCommunicationClient::GetModulesInfo( llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) { + namespace json = llvm::json; + if (!m_supports_jModulesInfo) return llvm::None; - JSONArray::SP module_array_sp = std::make_shared<JSONArray>(); + json::Array module_array; for (const FileSpec &module_file_spec : module_file_specs) { - JSONObject::SP module_sp = std::make_shared<JSONObject>(); - module_array_sp->AppendObject(module_sp); - module_sp->SetObject( - "file", std::make_shared<JSONString>(module_file_spec.GetPath(false))); - module_sp->SetObject("triple", - std::make_shared<JSONString>(triple.getTriple())); + module_array.push_back( + json::Object{{"file", module_file_spec.GetPath(false)}, + {"triple", triple.getTriple()}}); } StreamString unescaped_payload; unescaped_payload.PutCString("jModulesInfo:"); - module_array_sp->Write(unescaped_payload); + unescaped_payload.AsRawOstream() << std::move(module_array); + StreamGDBRemote payload; payload.PutEscapedBytes(unescaped_payload.GetString().data(), unescaped_payload.GetSize()); @@ -3796,8 +3834,9 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups( addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; lldb_private::SymbolContextList sc_list; - if (process->GetTarget().GetImages().FindSymbolsWithNameAndType( - ConstString(symbol_name), eSymbolTypeAny, sc_list)) { + process->GetTarget().GetImages().FindSymbolsWithNameAndType( + ConstString(symbol_name), eSymbolTypeAny, sc_list); + if (!sc_list.IsEmpty()) { const size_t num_scs = sc_list.GetSize(); for (size_t sc_idx = 0; sc_idx < num_scs && @@ -3873,9 +3912,9 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups( } else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) { - log->Printf( - "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.", + __FUNCTION__); } } } @@ -3899,26 +3938,27 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { !m_supported_async_json_packets_sp->GetAsArray()) { // We were returned something other than a JSON array. This is // invalid. Clear it out. - if (log) - log->Printf("GDBRemoteCommunicationClient::%s(): " - "QSupportedAsyncJSONPackets returned invalid " - "result: %s", - __FUNCTION__, response.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s(): " + "QSupportedAsyncJSONPackets returned invalid " + "result: %s", + __FUNCTION__, response.GetStringRef().data()); m_supported_async_json_packets_sp.reset(); } } else { - if (log) - log->Printf("GDBRemoteCommunicationClient::%s(): " - "QSupportedAsyncJSONPackets unsupported", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s(): " + "QSupportedAsyncJSONPackets unsupported", + __FUNCTION__); } if (log && m_supported_async_json_packets_sp) { StreamString stream; m_supported_async_json_packets_sp->Dump(stream); - log->Printf("GDBRemoteCommunicationClient::%s(): supported async " - "JSON packets: %s", - __FUNCTION__, stream.GetData()); + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s(): supported async " + "JSON packets: %s", + __FUNCTION__, stream.GetData()); } } @@ -3980,14 +4020,14 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( SendPacketAndWaitForResponse(stream.GetString(), response, send_async); if (result == PacketResult::Success) { // We failed if the config result comes back other than OK. - if (strcmp(response.GetStringRef().c_str(), "OK") == 0) { + if (strcmp(response.GetStringRef().data(), "OK") == 0) { // Okay! error.Clear(); } else { error.SetErrorStringWithFormat("configuring StructuredData feature " "%s failed with error %s", type_name.AsCString(), - response.GetStringRef().c_str()); + response.GetStringRef().data()); } } else { // Can we get more data here on the failure? diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index de85c9f8b67b..574cd0fd70c5 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -17,8 +17,9 @@ #include <string> #include <vector> +#include "lldb/Host/File.h" #include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/StructuredData.h" #if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" @@ -248,6 +249,8 @@ public: llvm::VersionTuple GetOSVersion(); + llvm::VersionTuple GetMacCatalystVersion(); + bool GetOSBuildString(std::string &s); bool GetOSKernelDescription(std::string &s); @@ -348,7 +351,7 @@ public: size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable); - lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags, + lldb::user_id_t OpenFile(const FileSpec &file_spec, File::OpenOptions flags, mode_t mode, Status &error); bool CloseFile(lldb::user_id_t fd, Status &error); @@ -548,6 +551,7 @@ protected: ArchSpec m_host_arch; ArchSpec m_process_arch; llvm::VersionTuple m_os_version; + llvm::VersionTuple m_maccatalyst_version; std::string m_os_build; std::string m_os_kernel; std::string m_hostname; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index bcddb4faf863..d2cc32f63f20 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -18,12 +18,6 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -void GDBRemoteCommunicationHistory::Entry::Serialize(raw_ostream &strm) const { - yaml::Output yout(strm); - yout << const_cast<GDBRemoteCommunicationHistory::Entry &>(*this); - strm.flush(); -} - GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size) : m_packets(), m_curr_idx(0), m_total_packet_count(0), m_dumped_to_log(false) { @@ -33,7 +27,8 @@ GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size) GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {} -void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType type, +void GDBRemoteCommunicationHistory::AddPacket(char packet_char, + GDBRemotePacket::Type type, uint32_t bytes_transmitted) { const size_t size = m_packets.size(); if (size == 0) @@ -50,7 +45,8 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType type, } void GDBRemoteCommunicationHistory::AddPacket(const std::string &src, - uint32_t src_len, PacketType type, + uint32_t src_len, + GDBRemotePacket::Type type, uint32_t bytes_transmitted) { const size_t size = m_packets.size(); if (size == 0) @@ -72,13 +68,12 @@ void GDBRemoteCommunicationHistory::Dump(Stream &strm) const { const uint32_t stop_idx = m_curr_idx + size; for (uint32_t i = first_idx; i < stop_idx; ++i) { const uint32_t idx = NormalizeIndex(i); - const Entry &entry = m_packets[idx]; - if (entry.type == ePacketTypeInvalid || entry.packet.data.empty()) + const GDBRemotePacket &entry = m_packets[idx]; + if (entry.type == GDBRemotePacket::ePacketTypeInvalid || + entry.packet.data.empty()) break; - strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", - entry.packet_idx, entry.tid, entry.bytes_transmitted, - (entry.type == ePacketTypeSend) ? "send" : "read", - entry.packet.data.c_str()); + strm.Printf("history[%u] ", entry.packet_idx); + entry.Dump(strm); } } @@ -92,51 +87,15 @@ void GDBRemoteCommunicationHistory::Dump(Log *log) const { const uint32_t stop_idx = m_curr_idx + size; for (uint32_t i = first_idx; i < stop_idx; ++i) { const uint32_t idx = NormalizeIndex(i); - const Entry &entry = m_packets[idx]; - if (entry.type == ePacketTypeInvalid || entry.packet.data.empty()) + const GDBRemotePacket &entry = m_packets[idx]; + if (entry.type == GDBRemotePacket::ePacketTypeInvalid || + entry.packet.data.empty()) break; - log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", - entry.packet_idx, entry.tid, entry.bytes_transmitted, - (entry.type == ePacketTypeSend) ? "send" : "read", - entry.packet.data.c_str()); + LLDB_LOGF(log, "history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", + entry.packet_idx, entry.tid, entry.bytes_transmitted, + (entry.type == GDBRemotePacket::ePacketTypeSend) ? "send" + : "read", + entry.packet.data.c_str()); } } -void yaml::ScalarEnumerationTraits<GDBRemoteCommunicationHistory::PacketType>:: - enumeration(IO &io, GDBRemoteCommunicationHistory::PacketType &value) { - io.enumCase(value, "Invalid", - GDBRemoteCommunicationHistory::ePacketTypeInvalid); - io.enumCase(value, "Send", GDBRemoteCommunicationHistory::ePacketTypeSend); - io.enumCase(value, "Recv", GDBRemoteCommunicationHistory::ePacketTypeRecv); -} - -void yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>:: - output(const GDBRemoteCommunicationHistory::Entry::BinaryData &Val, void *, - raw_ostream &Out) { - Out << toHex(Val.data); -} - -StringRef -yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>::input( - StringRef Scalar, void *, - GDBRemoteCommunicationHistory::Entry::BinaryData &Val) { - Val.data = fromHex(Scalar); - return {}; -} - -void yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::mapping( - IO &io, GDBRemoteCommunicationHistory::Entry &Entry) { - io.mapRequired("packet", Entry.packet); - io.mapRequired("type", Entry.type); - io.mapRequired("bytes", Entry.bytes_transmitted); - io.mapRequired("index", Entry.packet_idx); - io.mapRequired("tid", Entry.tid); -} - -StringRef yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::validate( - IO &io, GDBRemoteCommunicationHistory::Entry &Entry) { - if (Entry.bytes_transmitted != Entry.packet.data.size()) - return "BinaryData size doesn't match bytes transmitted"; - - return {}; -} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h index 85f112b50623..c006fbd34a4b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -12,6 +12,7 @@ #include <string> #include <vector> +#include "lldb/Utility/GDBRemote.h" #include "lldb/lldb-public.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" @@ -25,46 +26,17 @@ class GDBRemoteCommunicationHistory { public: friend llvm::yaml::MappingTraits<GDBRemoteCommunicationHistory>; - enum PacketType { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv }; - - /// Entry in the ring buffer containing the packet data, its type, size and - /// index. Entries can be serialized to file. - struct Entry { - Entry() - : packet(), type(ePacketTypeInvalid), bytes_transmitted(0), - packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {} - - void Clear() { - packet.data.clear(); - type = ePacketTypeInvalid; - bytes_transmitted = 0; - packet_idx = 0; - tid = LLDB_INVALID_THREAD_ID; - } - - struct BinaryData { - std::string data; - }; - - void Serialize(llvm::raw_ostream &strm) const; - - BinaryData packet; - PacketType type; - uint32_t bytes_transmitted; - uint32_t packet_idx; - lldb::tid_t tid; - }; - GDBRemoteCommunicationHistory(uint32_t size = 0); ~GDBRemoteCommunicationHistory(); // For single char packets for ack, nack and /x03 - void AddPacket(char packet_char, PacketType type, uint32_t bytes_transmitted); - - void AddPacket(const std::string &src, uint32_t src_len, PacketType type, + void AddPacket(char packet_char, GDBRemotePacket::Type type, uint32_t bytes_transmitted); + void AddPacket(const std::string &src, uint32_t src_len, + GDBRemotePacket::Type type, uint32_t bytes_transmitted); + void Dump(Stream &strm) const; void Dump(Log *log) const; bool DidDumpToLog() const { return m_dumped_to_log; } @@ -97,7 +69,7 @@ private: return m_packets.empty() ? 0 : i % m_packets.size(); } - std::vector<Entry> m_packets; + std::vector<GDBRemotePacket> m_packets; uint32_t m_curr_idx; uint32_t m_total_packet_count; mutable bool m_dumped_to_log; @@ -107,49 +79,4 @@ private: } // namespace process_gdb_remote } // namespace lldb_private -LLVM_YAML_IS_DOCUMENT_LIST_VECTOR( - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry) - -namespace llvm { -namespace yaml { - -template <> -struct ScalarEnumerationTraits<lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::PacketType> { - static void enumeration(IO &io, - lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::PacketType &value); -}; - -template <> -struct ScalarTraits<lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::Entry::BinaryData> { - static void output(const lldb_private::process_gdb_remote:: - GDBRemoteCommunicationHistory::Entry::BinaryData &, - void *, raw_ostream &); - - static StringRef - input(StringRef, void *, - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry:: - BinaryData &); - - static QuotingType mustQuote(StringRef S) { return QuotingType::None; } -}; - -template <> -struct MappingTraits< - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry> { - static void - mapping(IO &io, - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry - &Entry); - - static StringRef validate( - IO &io, - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry &); -}; - -} // namespace yaml -} // namespace llvm - #endif // liblldb_GDBRemoteCommunicationHistory_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp index 417f5737a30f..2d26c550dc76 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -9,6 +9,7 @@ #include <errno.h> #include "lldb/Host/Config.h" +#include "llvm/ADT/ScopeExit.h" #include "GDBRemoteCommunicationReplayServer.h" #include "ProcessGDBRemoteLog.h" @@ -127,7 +128,7 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); while (!m_packet_history.empty()) { // Pop last packet from the history. - GDBRemoteCommunicationHistory::Entry entry = m_packet_history.back(); + GDBRemotePacket entry = m_packet_history.back(); m_packet_history.pop_back(); // We've handled the handshake implicitly before. Skip the packet and move @@ -135,7 +136,7 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( if (entry.packet.data == "+") continue; - if (entry.type == GDBRemoteCommunicationHistory::ePacketTypeSend) { + if (entry.type == GDBRemotePacket::ePacketTypeSend) { if (unexpected(entry.packet.data, packet.GetStringRef())) { LLDB_LOG(log, "GDBRemoteCommunicationReplayServer expected packet: '{0}'", @@ -149,14 +150,14 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( // Ignore QEnvironment packets as they're handled earlier. if (entry.packet.data.find("QEnvironment") == 1) { assert(m_packet_history.back().type == - GDBRemoteCommunicationHistory::ePacketTypeRecv); + GDBRemotePacket::ePacketTypeRecv); m_packet_history.pop_back(); } continue; } - if (entry.type == GDBRemoteCommunicationHistory::ePacketTypeInvalid) { + if (entry.type == GDBRemotePacket::ePacketTypeInvalid) { LLDB_LOG( log, "GDBRemoteCommunicationReplayServer skipped invalid packet: '{0}'", @@ -175,10 +176,6 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( return packet_result; } -LLVM_YAML_IS_DOCUMENT_LIST_VECTOR( - std::vector< - lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry>) - llvm::Error GDBRemoteCommunicationReplayServer::LoadReplayHistory(const FileSpec &path) { auto error_or_file = MemoryBuffer::getFile(path.GetPath()); @@ -256,11 +253,10 @@ void GDBRemoteCommunicationReplayServer::ReceivePacket( thread_result_t GDBRemoteCommunicationReplayServer::AsyncThread(void *arg) { GDBRemoteCommunicationReplayServer *server = (GDBRemoteCommunicationReplayServer *)arg; - + auto D = make_scope_exit([&]() { server->Disconnect(); }); EventSP event_sp; bool done = false; - - while (true) { + while (!done) { if (server->m_async_listener_sp->GetEvent(event_sp, llvm::None)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs(&server->m_async_broadcaster)) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h index 26d65e265463..0b5e910f7c6a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h @@ -62,7 +62,7 @@ protected: static lldb::thread_result_t AsyncThread(void *arg); /// Replay history with the oldest packet at the end. - std::vector<GDBRemoteCommunicationHistory::Entry> m_packet_history; + std::vector<GDBRemotePacket> m_packet_history; /// Server thread. Broadcaster m_async_broadcaster; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 49cbeb023fd5..ac6ecffcf854 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -59,14 +59,13 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse( break; case StringExtractorGDBRemote::eServerPacketType_unimplemented: - packet_result = SendUnimplementedResponse(packet.GetStringRef().c_str()); + packet_result = SendUnimplementedResponse(packet.GetStringRef().data()); break; default: auto handler_it = m_packet_handlers.find(packet_type); if (handler_it == m_packet_handlers.end()) - packet_result = - SendUnimplementedResponse(packet.GetStringRef().c_str()); + packet_result = SendUnimplementedResponse(packet.GetStringRef().data()); else packet_result = handler_it->second(packet, error, interrupt, quit); break; @@ -139,10 +138,9 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendIllFormedResponse( const StringExtractorGDBRemote &failed_packet, const char *message) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); - if (log) - log->Printf("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", - __FUNCTION__, failed_packet.GetStringRef().c_str(), - message ? message : ""); + LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", + __FUNCTION__, failed_packet.GetStringRef().data(), + message ? message : ""); return SendErrorResponse(0x03); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index d095c7a057ad..37980d914dc2 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -29,12 +29,13 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Platform.h" #include "lldb/Utility/Endian.h" -#include "lldb/Utility/JSON.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StructuredData.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/JSON.h" #include "ProcessGDBRemoteLog.h" #include "lldb/Utility/StringExtractorGDBRemote.h" @@ -43,11 +44,10 @@ #include "lldb/Host/android/HostInfoAndroid.h" #endif -#include "llvm/ADT/StringSwitch.h" using namespace lldb; -using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace lldb_private; #ifdef __ANDROID__ const static uint32_t g_default_packet_timeout_sec = 20; // seconds @@ -231,6 +231,7 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( #else if (host_arch.GetMachine() == llvm::Triple::aarch64 || + host_arch.GetMachine() == llvm::Triple::aarch64_32 || host_arch.GetMachine() == llvm::Triple::aarch64_be || host_arch.GetMachine() == llvm::Triple::arm || host_arch.GetMachine() == llvm::Triple::armeb || host_arch.IsMIPS()) @@ -260,6 +261,15 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( response.PutChar(';'); } +#if defined(__APPLE__) + llvm::VersionTuple maccatalyst_version = HostInfo::GetMacCatalystVersion(); + if (!maccatalyst_version.empty()) { + response.Format("maccatalyst_version:{0}", + maccatalyst_version.getAsString()); + response.PutChar(';'); + } +#endif + std::string s; if (HostInfo::GetOSBuildString(s)) { response.PutCString("os_build:"); @@ -421,8 +431,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName( StringExtractorGDBRemote &packet) { #if !defined(LLDB_DISABLE_POSIX) Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); // Packet format: "qUserName:%i" where %i is the uid packet.SetFilePos(::strlen("qUserName:")); @@ -435,8 +444,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName( return SendPacketNoLock(response.GetString()); } } - if (log) - log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); #endif return SendErrorResponse(5); } @@ -500,19 +508,32 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Open( packet.GetHexByteStringTerminatedBy(path, ','); if (!path.empty()) { if (packet.GetChar() == ',') { - uint32_t flags = packet.GetHexMaxU32(false, 0); + // FIXME + // The flag values for OpenOptions do not match the values used by GDB + // * https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags + // * rdar://problem/46788934 + auto flags = File::OpenOptions(packet.GetHexMaxU32(false, 0)); if (packet.GetChar() == ',') { mode_t mode = packet.GetHexMaxU32(false, 0600); FileSpec path_spec(path); FileSystem::Instance().Resolve(path_spec); - File file; // Do not close fd. - Status error = - FileSystem::Instance().Open(file, path_spec, flags, mode, false); - const int save_errno = error.GetError(); + auto file = FileSystem::Instance().Open(path_spec, flags, mode, false); + + int save_errno = 0; + int descriptor = File::kInvalidDescriptor; + if (file) { + descriptor = file.get()->GetDescriptor(); + } else { + std::error_code code = errorToErrorCode(file.takeError()); + if (code.category() == std::system_category()) { + save_errno = code.value(); + } + } + StreamString response; response.PutChar('F'); - response.Printf("%i", file.GetDescriptor()); + response.Printf("%i", descriptor); if (save_errno) response.Printf(",%i", save_errno); return SendPacketNoLock(response.GetString()); @@ -530,7 +551,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Close( int err = -1; int save_errno = 0; if (fd >= 0) { - File file(fd, true); + NativeFile file(fd, File::OpenOptions(0), true); Status error = file.Close(); err = 0; save_errno = error.GetError(); @@ -552,16 +573,16 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( packet.SetFilePos(::strlen("vFile:pread:")); int fd = packet.GetS32(-1); if (packet.GetChar() == ',') { - size_t count = packet.GetU64(UINT64_MAX); + size_t count = packet.GetU64(SIZE_MAX); if (packet.GetChar() == ',') { off_t offset = packet.GetU64(UINT32_MAX); - if (count == UINT64_MAX) { + if (count == SIZE_MAX) { response.Printf("F-1:%i", EINVAL); return SendPacketNoLock(response.GetString()); } std::string buffer(count, 0); - File file(fd, false); + NativeFile file(fd, File::eOpenOptionRead, false); Status error = file.Read(static_cast<void *>(&buffer[0]), count, offset); const ssize_t bytes_read = error.Success() ? count : -1; const int save_errno = error.GetError(); @@ -593,7 +614,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( if (packet.GetChar() == ',') { std::string buffer; if (packet.GetEscapedBinaryData(buffer)) { - File file(fd, false); + NativeFile file(fd, File::eOpenOptionWrite, false); size_t count = buffer.size(); Status error = file.Write(static_cast<const void *>(&buffer[0]), count, offset); @@ -825,6 +846,7 @@ GDBRemoteCommunicationServerCommon::Handle_qSupported( #if defined(__linux__) || defined(__NetBSD__) response.PutCString(";QPassSignals+"); response.PutCString(";qXfer:auxv:read+"); + response.PutCString(";qXfer:libraries-svr4:read+"); #endif return SendPacketNoLock(response.GetString()); @@ -1016,9 +1038,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { m_process_launch_info.GetExecutableFile().SetFile( arg, FileSpec::Style::native); m_process_launch_info.GetArguments().AppendArgument(arg); - if (log) - log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"", - __FUNCTION__, actual_arg_index, arg.c_str()); + LLDB_LOGF(log, "LLGSPacketHandler::%s added arg %d: \"%s\"", + __FUNCTION__, actual_arg_index, arg.c_str()); ++actual_arg_index; } } @@ -1104,6 +1125,8 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( StringExtractorGDBRemote &packet) { + namespace json = llvm::json; + packet.SetFilePos(::strlen("jModulesInfo:")); StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(packet.Peek()); @@ -1114,7 +1137,7 @@ GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( if (!packet_array) return SendErrorResponse(2); - JSONArray::SP response_array_sp = std::make_shared<JSONArray>(); + json::Array response_array; for (size_t i = 0; i < packet_array->GetSize(); ++i) { StructuredData::Dictionary *query = packet_array->GetItemAtIndex(i)->GetAsDictionary(); @@ -1132,27 +1155,22 @@ GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); - if (uuid_str.empty()) continue; - - JSONObject::SP response = std::make_shared<JSONObject>(); - response_array_sp->AppendObject(response); - response->SetObject("uuid", std::make_shared<JSONString>(uuid_str)); - response->SetObject( - "triple", - std::make_shared<JSONString>( - matched_module_spec.GetArchitecture().GetTriple().getTriple())); - response->SetObject("file_path", - std::make_shared<JSONString>( - matched_module_spec.GetFileSpec().GetPath())); - response->SetObject("file_offset", - std::make_shared<JSONNumber>(file_offset)); - response->SetObject("file_size", std::make_shared<JSONNumber>(file_size)); + const auto triple_str = + matched_module_spec.GetArchitecture().GetTriple().getTriple(); + const auto file_path = matched_module_spec.GetFileSpec().GetPath(); + + json::Object response{{"uuid", uuid_str}, + {"triple", triple_str}, + {"file_path", file_path}, + {"file_offset", static_cast<int64_t>(file_offset)}, + {"file_size", static_cast<int64_t>(file_size)}}; + response_array.push_back(std::move(response)); } StreamString response; - response_array_sp->Write(response); + response.AsRawOstream() << std::move(response_array); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetString().data(), response.GetSize()); @@ -1168,6 +1186,15 @@ void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse( proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); response.PutCString("name:"); response.PutStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); + + response.PutChar(';'); + response.PutCString("args:"); + response.PutStringAsRawHex8(proc_info.GetArg0()); + for (auto &arg : proc_info.GetArguments()) { + response.PutChar('-'); + response.PutStringAsRawHex8(arg.ref()); + } + response.PutChar(';'); const ArchSpec &proc_arch = proc_info.GetArchitecture(); if (proc_arch.IsValid()) { @@ -1217,6 +1244,7 @@ void GDBRemoteCommunicationServerCommon:: case llvm::Triple::arm: case llvm::Triple::thumb: case llvm::Triple::aarch64: + case llvm::Triple::aarch64_32: ostype = "ios"; break; default: diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 196607665bba..ad1a39b57969 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -11,7 +11,7 @@ #include "lldb/Host/Config.h" #include "GDBRemoteCommunicationServerLLGS.h" -#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/GDBRemote.h" #include <chrono> #include <cstring> @@ -32,7 +32,6 @@ #include "lldb/Utility/Args.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/Endian.h" -#include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" @@ -40,6 +39,7 @@ #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UriParser.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/ScopedPrinter.h" #include "ProcessGDBRemote.h" @@ -217,8 +217,13 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); if (should_forward_stdio) { + // Temporarily relax the following for Windows until we can take advantage + // of the recently added pty support. This doesn't really affect the use of + // lldb-server on Windows. +#if !defined(_WIN32) if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection()) return Status(std::move(Err)); +#endif } { @@ -249,18 +254,18 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { // Setup stdout/stderr mapping from inferior to $O auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " - "inferior STDIO fd to %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s setting " + "inferior STDIO fd to %d", + __FUNCTION__, terminal_fd); Status status = SetSTDIOFileDescriptor(terminal_fd); if (status.Fail()) return status; } else { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " - "inferior STDIO since terminal fd reported as %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " + "inferior STDIO since terminal fd reported as %d", + __FUNCTION__, terminal_fd); } } else { LLDB_LOG(log, @@ -278,9 +283,8 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, - __FUNCTION__, pid); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, + __FUNCTION__, pid); // Before we try to attach, make sure we aren't already monitoring something // else. @@ -304,18 +308,18 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { // Setup stdout/stderr mapping from inferior. auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " - "inferior STDIO fd to %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s setting " + "inferior STDIO fd to %d", + __FUNCTION__, terminal_fd); Status status = SetSTDIOFileDescriptor(terminal_fd); if (status.Fail()) return status; } else { - if (log) - log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " - "inferior STDIO since terminal fd reported as %d", - __FUNCTION__, terminal_fd); + LLDB_LOGF(log, + "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " + "inferior STDIO since terminal fd reported as %d", + __FUNCTION__, terminal_fd); } printf("Attached to process %" PRIu64 "...\n", pid); @@ -327,10 +331,11 @@ void GDBRemoteCommunicationServerLLGS::InitializeDelegate( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " - "NativeProcessProtocol pid %" PRIu64 ", current state: %s", - __FUNCTION__, process->GetID(), - StateAsCString(process->GetState())); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s called with " + "NativeProcessProtocol pid %" PRIu64 ", current state: %s", + __FUNCTION__, process->GetID(), + StateAsCString(process->GetState())); } } @@ -397,19 +402,21 @@ static void WriteRegisterValueInHexFixedWidth( } } -static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { +static llvm::Expected<json::Object> +GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); NativeRegisterContext& reg_ctx = thread.GetRegisterContext(); - JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); + json::Object register_object; #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET // Expedite all registers in the first register set (i.e. should be GPRs) // that are not contained in other registers. const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); if (!reg_set_p) - return nullptr; + return llvm::make_error<llvm::StringError>("failed to get registers", + llvm::inconvertibleErrorCode()); for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { uint32_t reg_num = *reg_num_p; @@ -431,10 +438,9 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { const RegisterInfo *const reg_info_p = reg_ctx.GetRegisterInfoAtIndex(reg_num); if (reg_info_p == nullptr) { - if (log) - log->Printf( - "%s failed to get register info for register index %" PRIu32, - __FUNCTION__, reg_num); + LLDB_LOGF(log, + "%s failed to get register info for register index %" PRIu32, + __FUNCTION__, reg_num); continue; } @@ -445,11 +451,10 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { RegisterValue reg_value; Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { - if (log) - log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", - __FUNCTION__, - reg_info_p->name ? reg_info_p->name : "<unnamed-register>", - reg_num, error.AsCString()); + LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s", + __FUNCTION__, + reg_info_p->name ? reg_info_p->name : "<unnamed-register>", + reg_num, error.AsCString()); continue; } @@ -457,12 +462,11 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p, ®_value, lldb::eByteOrderBig); - register_object_sp->SetObject( - llvm::to_string(reg_num), - std::make_shared<JSONString>(stream.GetString())); + register_object.try_emplace(llvm::to_string(reg_num), + stream.GetString().str()); } - return register_object_sp; + return register_object; } static const char *GetStopReasonString(StopReason stop_reason) { @@ -489,11 +493,11 @@ static const char *GetStopReasonString(StopReason stop_reason) { return nullptr; } -static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, - bool abridged) { +static llvm::Expected<json::Array> +GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); + json::Array threads_array; // Ensure we can get info on the given thread. uint32_t thread_idx = 0; @@ -507,61 +511,62 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, struct ThreadStopInfo tid_stop_info; std::string description; if (!thread->GetStopReason(tid_stop_info, description)) - return nullptr; + return llvm::make_error<llvm::StringError>( + "failed to get stop reason", llvm::inconvertibleErrorCode()); const int signum = tid_stop_info.details.signal.signo; if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " tid %" PRIu64 - " got signal signo = %d, reason = %d, exc_type = %" PRIu64, - __FUNCTION__, process.GetID(), tid, signum, - tid_stop_info.reason, tid_stop_info.details.exception.type); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " tid %" PRIu64 + " got signal signo = %d, reason = %d, exc_type = %" PRIu64, + __FUNCTION__, process.GetID(), tid, signum, + tid_stop_info.reason, tid_stop_info.details.exception.type); } - JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); - threads_array_sp->AppendObject(thread_obj_sp); + json::Object thread_obj; if (!abridged) { - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread)) - thread_obj_sp->SetObject("registers", registers_sp); + if (llvm::Expected<json::Object> registers = + GetRegistersAsJSON(*thread)) { + thread_obj.try_emplace("registers", std::move(*registers)); + } else { + return registers.takeError(); + } } - thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); + thread_obj.try_emplace("tid", static_cast<int64_t>(tid)); + if (signum != 0) - thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); + thread_obj.try_emplace("signal", signum); const std::string thread_name = thread->GetName(); if (!thread_name.empty()) - thread_obj_sp->SetObject("name", - std::make_shared<JSONString>(thread_name)); + thread_obj.try_emplace("name", thread_name); - if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) - thread_obj_sp->SetObject("reason", - std::make_shared<JSONString>(stop_reason_str)); + const char *stop_reason = GetStopReasonString(tid_stop_info.reason); + if (stop_reason) + thread_obj.try_emplace("reason", stop_reason); if (!description.empty()) - thread_obj_sp->SetObject("description", - std::make_shared<JSONString>(description)); + thread_obj.try_emplace("description", description); if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { - thread_obj_sp->SetObject( - "metype", - std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); + thread_obj.try_emplace( + "metype", static_cast<int64_t>(tid_stop_info.details.exception.type)); - JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); + json::Array medata_array; for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) { - medata_array_sp->AppendObject(std::make_shared<JSONNumber>( - tid_stop_info.details.exception.data[i])); + medata_array.push_back( + static_cast<int64_t>(tid_stop_info.details.exception.data[i])); } - thread_obj_sp->SetObject("medata", medata_array_sp); + thread_obj.try_emplace("medata", std::move(medata_array)); } - - // TODO: Expedite interesting regions of inferior memory + threads_array.push_back(std::move(thread_obj)); } - - return threads_array_sp; + return threads_array; } GDBRemoteCommunication::PacketResult @@ -653,19 +658,21 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( // is hex ascii JSON that contains the thread IDs thread stop info only for // threads that have stop reasons. Only send this if we have more than one // thread otherwise this packet has all the info it needs. - if (thread_index > 0) { + if (thread_index > 1) { const bool threads_with_valid_stop_info_only = true; - JSONArray::SP threads_info_sp = GetJSONThreadsInfo( + llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo( *m_debugged_process_up, threads_with_valid_stop_info_only); - if (threads_info_sp) { + if (threads_info) { response.PutCString("jstopinfo:"); StreamString unescaped_response; - threads_info_sp->Write(unescaped_response); + unescaped_response.AsRawOstream() << std::move(*threads_info); response.PutStringAsRawHex8(unescaped_response.GetData()); response.PutChar(';'); - } else - LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}", - m_debugged_process_up->GetID()); + } else { + LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}:", + m_debugged_process_up->GetID(), + llvm::toString(threads_info.takeError())); + } } uint32_t i = 0; @@ -684,12 +691,10 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( RegisterValue reg_value; Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { - if (log) - log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", - __FUNCTION__, - reg_info_p->name ? reg_info_p->name - : "<unnamed-register>", - reg_to_read, error.AsCString()); + LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s", + __FUNCTION__, + reg_info_p->name ? reg_info_p->name : "<unnamed-register>", + reg_to_read, error.AsCString()); continue; } @@ -713,25 +718,24 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( const RegisterSet *reg_set_p; if (reg_ctx.GetRegisterSetCount() > 0 && ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " - "from set '%s' (registers set count: %zu)", - __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - reg_set_p->num_registers); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s expediting registers " + "from set '%s' (registers set count: %zu)", + __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + reg_set_p->num_registers); for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { const RegisterInfo *const reg_info_p = reg_ctx.GetRegisterInfoAtIndex(*reg_num_p); if (reg_info_p == nullptr) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " - "register info for register set '%s', register index " - "%" PRIu32, - __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - *reg_num_p); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to get " + "register info for register set '%s', register index " + "%" PRIu32, + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + *reg_num_p); } else if (reg_info_p->value_regs == nullptr) { // Only expediate registers that are not contained in other registers. RegisterValue reg_value; @@ -742,13 +746,12 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( ®_value, lldb::eByteOrderBig); response.PutChar(';'); } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " - "register '%s' index %" PRIu32 ": %s", - __FUNCTION__, - reg_info_p->name ? reg_info_p->name - : "<unnamed-register>", - *reg_num_p, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to read " + "register '%s' index %" PRIu32 ": %s", + __FUNCTION__, + reg_info_p->name ? reg_info_p->name : "<unnamed-register>", + *reg_num_p, error.AsCString()); } } } @@ -787,15 +790,14 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); PacketResult result = SendStopReasonForState(StateType::eStateExited); if (result != PacketResult::Success) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " - "notification for PID %" PRIu64 ", state: eStateExited", - __FUNCTION__, process->GetID()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to send stop " + "notification for PID %" PRIu64 ", state: eStateExited", + __FUNCTION__, process->GetID()); } // Close the pipe to the inferior terminal i/o if we launched it and set one @@ -812,8 +814,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Send the stop reason unless this is the stop after the launch or attach. switch (m_inferior_prev_state) { @@ -825,10 +826,10 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( // In all other cases, send the stop reason. PacketResult result = SendStopReasonForState(StateType::eStateStopped); if (result != PacketResult::Success) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " - "notification for PID %" PRIu64 ", state: eStateExited", - __FUNCTION__, process->GetID()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to send stop " + "notification for PID %" PRIu64 ", state: eStateExited", + __FUNCTION__, process->GetID()); } break; } @@ -839,9 +840,10 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " - "NativeProcessProtocol pid %" PRIu64 ", state: %s", - __FUNCTION__, process->GetID(), StateAsCString(state)); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s called with " + "NativeProcessProtocol pid %" PRIu64 ", state: %s", + __FUNCTION__, process->GetID(), StateAsCString(state)); } switch (state) { @@ -868,9 +870,10 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( default: if (log) { - log->Printf("GDBRemoteCommunicationServerLLGS::%s didn't handle state " - "change for pid %" PRIu64 ", new state: %s", - __FUNCTION__, process->GetID(), StateAsCString(state)); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s didn't handle state " + "change for pid %" PRIu64 ", new state: %s", + __FUNCTION__, process->GetID(), StateAsCString(state)); } break; } @@ -888,10 +891,10 @@ void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { if (!m_handshake_completed) { if (!HandshakeWithClient()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with " - "client failed, exiting", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s handshake with " + "client failed, exiting", + __FUNCTION__); m_mainloop.RequestTermination(); return; } @@ -908,10 +911,10 @@ void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { break; // No more packets in the queue if ((result != PacketResult::Success)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet " - "failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s processing a packet " + "failed: %s", + __FUNCTION__, error.AsCString()); m_mainloop.RequestTermination(); break; } @@ -982,9 +985,10 @@ void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { // Not much we can do about the failure. Log it and continue without // forwarding. if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio " - "forwarding: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio " + "forwarding: %s", + __FUNCTION__, error.AsCString()); } } @@ -1008,10 +1012,11 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { case eConnectionStatusError: case eConnectionStatusNoConnection: if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) - log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio " - "forwarding as communication returned status %d (error: " - "%s)", - __FUNCTION__, status, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s Stopping stdio " + "forwarding as communication returned status %d (error: " + "%s)", + __FUNCTION__, status, error.AsCString()); m_stdio_handle_up.reset(); return; @@ -1349,15 +1354,14 @@ GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Ensure we have a native process. if (!m_debugged_process_up) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " - "shared pointer", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s no debugged process " + "shared pointer", + __FUNCTION__); return SendErrorResponse(0x36); } @@ -1376,13 +1380,14 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { if (packet.GetBytesLeft() > 0) { // FIXME add continue at address support for $C{signo}[;{continue-address}]. if (*packet.Peek() == ';') - return SendUnimplementedResponse(packet.GetStringRef().c_str()); + return SendUnimplementedResponse(packet.GetStringRef().data()); else return SendIllFormedResponse( packet, "unexpected content after $C{signal-number}"); } - ResumeActionList resume_actions(StateType::eStateRunning, 0); + ResumeActionList resume_actions(StateType::eStateRunning, + LLDB_INVALID_SIGNAL_NUMBER); Status error; // We have two branches: what to do if a continue thread is specified (in @@ -1430,8 +1435,7 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); packet.SetFilePos(packet.GetFilePos() + ::strlen("c")); @@ -1440,20 +1444,21 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { if (has_continue_address) { LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]", packet.Peek()); - return SendUnimplementedResponse(packet.GetStringRef().c_str()); + return SendUnimplementedResponse(packet.GetStringRef().data()); } // Ensure we have a native process. if (!m_debugged_process_up) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " - "shared pointer", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s no debugged process " + "shared pointer", + __FUNCTION__); return SendErrorResponse(0x36); } // Build the ResumeActionList - ResumeActionList actions(StateType::eStateRunning, 0); + ResumeActionList actions(StateType::eStateRunning, + LLDB_INVALID_SIGNAL_NUMBER); Status error = m_debugged_process_up->Resume(actions); if (error.Fail()) { @@ -1480,17 +1485,16 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_vCont( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s handling vCont packet", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s handling vCont packet", + __FUNCTION__); packet.SetFilePos(::strlen("vCont")); if (packet.GetBytesLeft() == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s missing action from " - "vCont package", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s missing action from " + "vCont package", + __FUNCTION__); return SendIllFormedResponse(packet, "Missing action from vCont package"); } @@ -1521,7 +1525,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( ResumeAction thread_action; thread_action.tid = LLDB_INVALID_THREAD_ID; thread_action.state = eStateInvalid; - thread_action.signal = 0; + thread_action.signal = LLDB_INVALID_SIGNAL_NUMBER; const char action = packet.GetChar(); switch (action) { @@ -1958,10 +1962,10 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { const uint32_t reg_index = packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); if (reg_index == std::numeric_limits<uint32_t>::max()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " - "parse register number from request \"%s\"", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse register number from request \"%s\"", + __FUNCTION__, packet.GetStringRef().data()); return SendErrorResponse(0x15); } @@ -1978,20 +1982,19 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { // Return the end of registers response if we've iterated one past the end of // the register set. if (reg_index >= reg_context.GetUserRegisterCount()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " beyond register count %" PRIu32, - __FUNCTION__, reg_index, - reg_context.GetUserRegisterCount()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " beyond register count %" PRIu32, + __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); return SendErrorResponse(0x15); } const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " returned NULL", - __FUNCTION__, reg_index); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " returned NULL", + __FUNCTION__, reg_index); return SendErrorResponse(0x15); } @@ -2002,20 +2005,20 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { RegisterValue reg_value; Status error = reg_context.ReadRegister(reg_info, reg_value); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " - "requested register %" PRIu32 " (%s) failed: %s", - __FUNCTION__, reg_index, reg_info->name, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, read of " + "requested register %" PRIu32 " (%s) failed: %s", + __FUNCTION__, reg_index, reg_info->name, error.AsCString()); return SendErrorResponse(0x15); } const uint8_t *const data = reinterpret_cast<const uint8_t *>(reg_value.GetBytes()); if (!data) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get data " - "bytes from requested register %" PRIu32, - __FUNCTION__, reg_index); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to get data " + "bytes from requested register %" PRIu32, + __FUNCTION__, reg_index); return SendErrorResponse(0x15); } @@ -2039,10 +2042,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { const uint32_t reg_index = packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); if (reg_index == std::numeric_limits<uint32_t>::max()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " - "parse register number from request \"%s\"", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse register number from request \"%s\"", + __FUNCTION__, packet.GetStringRef().data()); return SendErrorResponse(0x29); } @@ -2058,10 +2061,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Get the thread to use. NativeThreadProtocol *thread = GetThreadFromSuffix(packet); if (!thread) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread " - "available (thread index 0)", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, no thread " + "available (thread index 0)", + __FUNCTION__); return SendErrorResponse(0x28); } @@ -2069,20 +2072,20 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { NativeRegisterContext ®_context = thread->GetRegisterContext(); const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " returned NULL", - __FUNCTION__, reg_index); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " returned NULL", + __FUNCTION__, reg_index); return SendErrorResponse(0x48); } // Return the end of registers response if we've iterated one past the end of // the register set. if (reg_index >= reg_context.GetUserRegisterCount()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " - "register %" PRIu32 " beyond register count %" PRIu32, - __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, requested " + "register %" PRIu32 " beyond register count %" PRIu32, + __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); return SendErrorResponse(0x47); } @@ -2101,10 +2104,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { m_debugged_process_up->GetArchitecture().GetByteOrder()); Status error = reg_context.WriteRegister(reg_info, reg_value); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " - "requested register %" PRIu32 " (%s) failed: %s", - __FUNCTION__, reg_index, reg_info->name, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, write of " + "requested register %" PRIu32 " (%s) failed: %s", + __FUNCTION__, reg_index, reg_info->name, error.AsCString()); return SendErrorResponse(0x32); } @@ -2118,20 +2121,20 @@ GDBRemoteCommunicationServerLLGS::Handle_H(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 (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + 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) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, H command " - "missing {g,c} variant", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, H command " + "missing {g,c} variant", + __FUNCTION__); return SendIllFormedResponse(packet, "H command missing {g,c} variant"); } @@ -2144,10 +2147,10 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { break; default: - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", - __FUNCTION__, h_variant); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", + __FUNCTION__, h_variant); return SendIllFormedResponse(packet, "H variant unsupported, should be c or g"); } @@ -2162,10 +2165,10 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); if (!thread) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 - " not found", - __FUNCTION__, tid); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 + " not found", + __FUNCTION__, tid); return SendErrorResponse(0x15); } } @@ -2196,10 +2199,10 @@ GDBRemoteCommunicationServerLLGS::Handle_I(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 (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2257,10 +2260,10 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2284,10 +2287,10 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( const uint64_t byte_count = packet.GetHexMaxU64(false, 0); if (byte_count == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to read: " - "zero-length packet", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s nothing to read: " + "zero-length packet", + __FUNCTION__); return SendOKResponse(); } @@ -2301,20 +2304,20 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( Status error = m_debugged_process_up->ReadMemoryWithoutTrap( read_addr, &buf[0], byte_count, bytes_read); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " mem 0x%" PRIx64 ": failed to read. Error: %s", - __FUNCTION__, m_debugged_process_up->GetID(), read_addr, - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " mem 0x%" PRIx64 ": failed to read. Error: %s", + __FUNCTION__, m_debugged_process_up->GetID(), read_addr, + error.AsCString()); return SendErrorResponse(0x08); } if (bytes_read == 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", - __FUNCTION__, m_debugged_process_up->GetID(), read_addr, - byte_count); + 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); return SendErrorResponse(0x08); } @@ -2338,10 +2341,10 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2426,10 +2429,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( // since we won't have a NativeProcessProtocol. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2454,10 +2457,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( // Ensure we have a process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -2703,10 +2706,10 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // Ensure we have a process. if (!m_debugged_process_up || (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x32); } @@ -2725,7 +2728,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { return SendErrorResponse(0x33); // Create the step action for the given thread. - ResumeAction action = {tid, eStateStepping, 0}; + ResumeAction action = {tid, eStateStepping, LLDB_INVALID_SIGNAL_NUMBER}; // Setup the actions list. ResumeActionList actions; @@ -2735,11 +2738,11 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); Status error = m_debugged_process_up->Resume(actions); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " tid %" PRIu64 " Resume() failed with error: %s", - __FUNCTION__, m_debugged_process_up->GetID(), tid, - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 + " tid %" PRIu64 " Resume() failed with error: %s", + __FUNCTION__, m_debugged_process_up->GetID(), tid, + error.AsCString()); return SendErrorResponse(0x49); } @@ -2765,6 +2768,24 @@ GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, return std::move(*buffer_or_error); } + if (object == "libraries-svr4") { + auto library_list = m_debugged_process_up->GetLoadedSVR4Libraries(); + if (!library_list) + return library_list.takeError(); + + StreamString response; + response.Printf("<library-list-svr4 version=\"1.0\">"); + for (auto const &library : *library_list) { + response.Printf("<library name=\"%s\" ", + XMLEncodeAttributeValue(library.name.c_str()).c_str()); + response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map); + response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr); + response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr); + } + response.Printf("</library-list-svr4>"); + return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__); + } + return llvm::make_error<PacketUnimplementedError>( "Xfer object not supported"); } @@ -2968,18 +2989,18 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach( "vAttach failed to parse the process id"); // Attempt to attach. - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to " - "pid %" PRIu64, - __FUNCTION__, pid); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s attempting to attach to " + "pid %" PRIu64, + __FUNCTION__, pid); Status error = AttachToProcess(pid); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to " - "pid %" PRIu64 ": %s\n", - __FUNCTION__, pid, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to attach to " + "pid %" PRIu64 ": %s\n", + __FUNCTION__, pid, error.AsCString()); return SendErrorResponse(error); } @@ -2996,10 +3017,10 @@ GDBRemoteCommunicationServerLLGS::Handle_D(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 (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); return SendErrorResponse(0x15); } @@ -3023,11 +3044,10 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { const Status error = m_debugged_process_up->Detach(); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from " - "pid %" PRIu64 ": %s\n", - __FUNCTION__, m_debugged_process_up->GetID(), - error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to detach from " + "pid %" PRIu64 ": %s\n", + __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString()); return SendErrorResponse(0x01); } @@ -3042,10 +3062,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( packet.SetFilePos(strlen("qThreadStopInfo")); const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); if (tid == LLDB_INVALID_THREAD_ID) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " - "parse thread id from request \"%s\"", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed, could not " + "parse thread id from request \"%s\"", + __FUNCTION__, packet.GetStringRef().data()); return SendErrorResponse(0x15); } return SendStopReplyPacketForThread(tid); @@ -3064,15 +3084,16 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( StreamString response; const bool threads_with_valid_stop_info_only = false; - JSONArray::SP threads_array_sp = GetJSONThreadsInfo( + llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo( *m_debugged_process_up, threads_with_valid_stop_info_only); - if (!threads_array_sp) { - LLDB_LOG(log, "failed to prepare a packet for pid {0}", - m_debugged_process_up->GetID()); + if (!threads_info) { + LLDB_LOG(log, "failed to prepare a packet for pid {0}: {1}", + m_debugged_process_up->GetID(), + llvm::toString(threads_info.takeError())); return SendErrorResponse(52); } - threads_array_sp->Write(response); + response.AsRawOstream() << *threads_info; StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); return SendPacketNoLock(escaped_response.GetString()); @@ -3177,15 +3198,15 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { connection->Disconnect(&error); if (error.Success()) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " - "terminal stdio - SUCCESS", - __FUNCTION__); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s disconnect process " + "terminal stdio - SUCCESS", + __FUNCTION__); } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " - "terminal stdio - FAIL: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s disconnect process " + "terminal stdio - FAIL: %s", + __FUNCTION__, error.AsCString()); } } } @@ -3215,11 +3236,11 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( // Parse out the ';'. if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " - "error: expected ';' prior to start of thread suffix: packet " - "contents = '%s'", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " + "error: expected ';' prior to start of thread suffix: packet " + "contents = '%s'", + __FUNCTION__, packet.GetStringRef().data()); return nullptr; } @@ -3228,11 +3249,11 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( // Parse out thread: portion. if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " - "error: expected 'thread:' but not found, packet contents = " - "'%s'", - __FUNCTION__, packet.GetStringRef().c_str()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " + "error: expected 'thread:' but not found, packet contents = " + "'%s'", + __FUNCTION__, packet.GetStringRef().data()); return nullptr; } packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); @@ -3283,3 +3304,28 @@ GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); } + +std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue( + llvm::StringRef value) { + std::string result; + for (const char &c : value) { + switch (c) { + case '\'': + result += "'"; + break; + case '"': + result += """; + break; + case '<': + result += "<"; + break; + case '>': + result += ">"; + break; + default: + result += c; + break; + } + } + return result; +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 068ea52caaaf..088ba92ad11a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -196,6 +196,8 @@ protected: llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> ReadXferObject(llvm::StringRef object, llvm::StringRef annex); + static std::string XMLEncodeAttributeValue(llvm::StringRef value); + private: void HandleInferiorState_Exited(NativeProcessProtocol *process); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 6deb75f2f021..25cebbba8f7b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -15,8 +15,10 @@ #include <cstring> #include <mutex> #include <sstream> +#include <thread> #include "llvm/Support/FileSystem.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/Threading.h" #include "lldb/Host/Config.h" @@ -26,9 +28,8 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Target/Platform.h" #include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/JSON.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/UriParser.h" @@ -36,8 +37,8 @@ #include "lldb/Utility/StringExtractorGDBRemote.h" using namespace lldb; -using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace lldb_private; // GDBRemoteCommunicationServerPlatform constructor GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( @@ -104,8 +105,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( hostname = "127.0.0.1"; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port); + LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(), + port); // Do not run in a new session so that it can not linger after the platform // closes. @@ -161,9 +162,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( // process... Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("GDBRemoteCommunicationServerPlatform::%s() called", - __FUNCTION__); + LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called", + __FUNCTION__); ConnectionFileDescriptor file_conn; std::string hostname; @@ -183,17 +183,17 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( Status error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); if (error.Fail()) { - if (log) - log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver " - "launch failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerPlatform::%s() debugserver " + "launch failed: %s", + __FUNCTION__, error.AsCString()); return SendErrorResponse(9); } - if (log) - log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver " - "launched successfully as pid %" PRIu64, - __FUNCTION__, debugserver_pid); + LLDB_LOGF(log, + "GDBRemoteCommunicationServerPlatform::%s() debugserver " + "launched successfully as pid %" PRIu64, + __FUNCTION__, debugserver_pid); StreamGDBRemote response; response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, @@ -215,22 +215,21 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer( StringExtractorGDBRemote &packet) { + namespace json = llvm::json; + if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(4); - JSONObject::SP server_sp = std::make_shared<JSONObject>(); - server_sp->SetObject("port", - std::make_shared<JSONNumber>(m_pending_gdb_server.port)); + json::Object server{{"port", m_pending_gdb_server.port}}; + if (!m_pending_gdb_server.socket_name.empty()) - server_sp->SetObject( - "socket_name", - std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); + server.try_emplace("socket_name", m_pending_gdb_server.socket_name); - JSONArray server_list; - server_list.AppendObject(server_sp); + json::Array server_list; + server_list.push_back(std::move(server)); StreamGDBRemote response; - server_list.Write(response); + response.AsRawOstream() << std::move(server_list); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetString().data(), @@ -281,10 +280,9 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) { return true; } } - usleep(10000); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - // check one more time after the final usleep { std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) @@ -303,10 +301,10 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) { return true; } } - usleep(10000); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - // check one more time after the final usleep Scope for locker + // check one more time after the final sleep { std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index a77e659a55fa..c06c9527708e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -206,11 +206,14 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, } else { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | GDBR_LOG_PACKETS)); - if (log) - log->Printf ("error: GDBRemoteRegisterContext::ReadRegisterBytes tried to read the " - "entire register context at once, expected at least %" PRId64 " bytes " - "but only got %" PRId64 " bytes.", m_reg_data.GetByteSize(), - buffer_sp->GetByteSize()); + LLDB_LOGF( + log, + "error: GDBRemoteRegisterContext::ReadRegisterBytes tried " + "to read the " + "entire register context at once, expected at least %" PRId64 + " bytes " + "but only got %" PRId64 " bytes.", + m_reg_data.GetByteSize(), buffer_sp->GetByteSize()); } } return false; @@ -390,13 +393,15 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, if (log->GetVerbose()) { StreamString strm; gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending " - "write register for \"%s\":\n%s", - reg_info->name, strm.GetData()); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write register for \"%s\":\n%s", + reg_info->name, strm.GetData()); } else - log->Printf("error: failed to get packet sequence mutex, not sending " - "write register for \"%s\"", - reg_info->name); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write register for \"%s\"", + reg_info->name); } } } @@ -494,12 +499,14 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( if (log->GetVerbose()) { StreamString strm; gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending " - "read all registers:\n%s", - strm.GetData()); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "read all registers:\n%s", + strm.GetData()); } else - log->Printf("error: failed to get packet sequence mutex, not sending " - "read all registers"); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "read all registers"); } } @@ -630,7 +637,9 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( if (m_thread.GetProcess().get()) { const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); - if (arch.IsValid() && arch.GetMachine() == llvm::Triple::aarch64 && + if (arch.IsValid() && + (arch.GetMachine() == llvm::Triple::aarch64 || + arch.GetMachine() == llvm::Triple::aarch64_32) && arch.GetTriple().getVendor() == llvm::Triple::Apple && arch.GetTriple().getOS() == llvm::Triple::IOS) { arm64_debugserver = true; @@ -667,12 +676,14 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( if (log->GetVerbose()) { StreamString strm; gdb_comm.DumpHistory(strm); - log->Printf("error: failed to get packet sequence mutex, not sending " - "write all registers:\n%s", - strm.GetData()); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write all registers:\n%s", + strm.GetData()); } else - log->Printf("error: failed to get packet sequence mutex, not sending " - "write all registers"); + LLDB_LOGF(log, + "error: failed to get packet sequence mutex, not sending " + "write all registers"); } } return false; diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index a6fdd8dd0707..f1762abc55f8 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -63,7 +63,6 @@ #include "lldb/Target/TargetList.h" #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Utility/Args.h" -#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Reproducer.h" #include "lldb/Utility/State.h" @@ -81,12 +80,12 @@ #include "lldb/Host/Host.h" #include "lldb/Utility/StringExtractorGDBRemote.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" #define DEBUGSERVER_BASENAME "debugserver" -using namespace llvm; using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; @@ -99,51 +98,25 @@ namespace lldb { // namespace. This allows you to attach with a debugger and call this function // and get the packet history dumped to a file. void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { - StreamFile strm; - Status error = FileSystem::Instance().Open(strm.GetFile(), FileSpec(path), - File::eOpenOptionWrite | - File::eOpenOptionCanCreate); - if (error.Success()) - ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm); + auto file = FileSystem::Instance().Open( + FileSpec(path), File::eOpenOptionWrite | File::eOpenOptionCanCreate); + if (!file) { + llvm::consumeError(file.takeError()); + return; + } + StreamFile stream(std::move(file.get())); + ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(stream); } } // namespace lldb namespace { -static constexpr PropertyDefinition g_properties[] = { - {"packet-timeout", - OptionValue::eTypeUInt64, - true, - 5 -#if defined(__has_feature) -#if __has_feature(address_sanitizer) - * 2 -#endif -#endif - , - nullptr, - {}, - "Specify the default packet timeout in seconds."}, - {"target-definition-file", - OptionValue::eTypeFileSpec, - true, - 0, - nullptr, - {}, - "The file that provides the description for remote target registers."}, - {"use-libraries-svr4", - OptionValue::eTypeBoolean, - true, - false, - nullptr, - {}, - "If true, the libraries-svr4 feature will be used to get a hold of the " - "process's loaded modules."}}; +#define LLDB_PROPERTIES_processgdbremote +#include "ProcessGDBRemoteProperties.inc" enum { - ePropertyPacketTimeout, - ePropertyTargetDefinitionFile, - ePropertyUseSVR4 +#define LLDB_PROPERTIES_processgdbremote +#include "ProcessGDBRemotePropertiesEnum.inc" }; class PluginProperties : public Properties { @@ -154,7 +127,7 @@ public: PluginProperties() : Properties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_processgdbremote_properties); } ~PluginProperties() override {} @@ -162,7 +135,7 @@ public: uint64_t GetPacketTimeout() { const uint32_t idx = ePropertyPacketTimeout; return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_processgdbremote_properties[idx].default_uint_value); } bool SetPacketTimeout(uint64_t timeout) { @@ -178,7 +151,8 @@ public: bool GetUseSVR4() const { const uint32_t idx = ePropertyUseSVR4; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, + g_processgdbremote_properties[idx].default_uint_value != 0); } }; @@ -191,45 +165,6 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { return g_settings_sp; } -class ProcessGDBRemoteProvider - : public repro::Provider<ProcessGDBRemoteProvider> { -public: - struct Info { - static const char *name; - static const char *file; - }; - - ProcessGDBRemoteProvider(const FileSpec &directory) : Provider(directory) { - } - - raw_ostream *GetHistoryStream() { - FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file); - - std::error_code EC; - m_stream_up = llvm::make_unique<raw_fd_ostream>(history_file.GetPath(), EC, - sys::fs::OpenFlags::F_Text); - return m_stream_up.get(); - } - - void SetCallback(std::function<void()> callback) { - m_callback = std::move(callback); - } - - void Keep() override { m_callback(); } - - void Discard() override { m_callback(); } - - static char ID; - -private: - std::function<void()> m_callback; - std::unique_ptr<raw_fd_ostream> m_stream_up; -}; - -char ProcessGDBRemoteProvider::ID = 0; -const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote"; -const char *ProcessGDBRemoteProvider::Info::file = "gdb-remote.yaml"; - } // namespace // TODO Randomly assigning a port is unsafe. We should get an unused @@ -339,8 +274,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, "async thread did exit"); if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) { - ProcessGDBRemoteProvider &provider = - g->GetOrCreate<ProcessGDBRemoteProvider>(); + repro::ProcessGDBRemoteProvider &provider = + g->GetOrCreate<repro::ProcessGDBRemoteProvider>(); // Set the history stream to the stream owned by the provider. m_gdb_comm.SetHistoryStream(provider.GetHistoryStream()); // Make sure to clear the stream again when we're finished. @@ -354,10 +289,10 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, if (m_async_listener_sp->StartListeningForEvents( &m_async_broadcaster, async_event_mask) != async_event_mask) { - if (log) - log->Printf("ProcessGDBRemote::%s failed to listen for " - "m_async_broadcaster events", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s failed to listen for " + "m_async_broadcaster events", + __FUNCTION__); } const uint32_t gdb_event_mask = @@ -365,9 +300,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; if (m_async_listener_sp->StartListeningForEvents( &m_gdb_comm, gdb_event_mask) != gdb_event_mask) { - if (log) - log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s failed to listen for m_gdb_comm events", + __FUNCTION__); } const uint64_t timeout_seconds = @@ -785,15 +720,15 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm, pid, remote_url.str().c_str()); } - if (log) - log->Printf("ProcessGDBRemote::%s pid %" PRIu64 - ": normalizing target architecture initial triple: %s " - "(GetTarget().GetArchitecture().IsValid() %s, " - "m_gdb_comm.GetHostArchitecture().IsValid(): %s)", - __FUNCTION__, GetID(), - GetTarget().GetArchitecture().GetTriple().getTriple().c_str(), - GetTarget().GetArchitecture().IsValid() ? "true" : "false", - m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s pid %" PRIu64 + ": normalizing target architecture initial triple: %s " + "(GetTarget().GetArchitecture().IsValid() %s, " + "m_gdb_comm.GetHostArchitecture().IsValid(): %s)", + __FUNCTION__, GetID(), + GetTarget().GetArchitecture().GetTriple().getTriple().c_str(), + GetTarget().GetArchitecture().IsValid() ? "true" : "false", + m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false"); if (error.Success() && !GetTarget().GetArchitecture().IsValid() && m_gdb_comm.GetHostArchitecture().IsValid()) { @@ -805,11 +740,11 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm, GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); } - if (log) - log->Printf("ProcessGDBRemote::%s pid %" PRIu64 - ": normalized target architecture triple: %s", - __FUNCTION__, GetID(), - GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s pid %" PRIu64 + ": normalized target architecture triple: %s", + __FUNCTION__, GetID(), + GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); if (error.Success()) { PlatformSP platform_sp = GetTarget().GetPlatform(); @@ -834,8 +769,7 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error; - if (log) - log->Printf("ProcessGDBRemote::%s() entered", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s() entered", __FUNCTION__); uint32_t launch_flags = launch_info.GetFlags().Get(); FileSpec stdin_file_spec{}; @@ -862,15 +796,17 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, if (log) { if (stdin_file_spec || stdout_file_spec || stderr_file_spec) - log->Printf("ProcessGDBRemote::%s provided with STDIO paths via " - "launch_info: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s provided with STDIO paths via " + "launch_info: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); else - log->Printf("ProcessGDBRemote::%s no STDIO paths given via launch_info", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s no STDIO paths given via launch_info", + __FUNCTION__); } const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; @@ -925,24 +861,23 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, if (!stderr_file_spec) stderr_file_spec = slave_name; } - if (log) - log->Printf( - "ProcessGDBRemote::%s adjusted STDIO paths for local platform " - "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); + LLDB_LOGF( + log, + "ProcessGDBRemote::%s adjusted STDIO paths for local platform " + "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); } - if (log) - log->Printf("ProcessGDBRemote::%s final STDIO paths after all " - "adjustments: stdin=%s, stdout=%s, stderr=%s", - __FUNCTION__, - stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", - stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", - stderr_file_spec ? stderr_file_spec.GetCString() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s final STDIO paths after all " + "adjustments: stdin=%s, stdout=%s, stderr=%s", + __FUNCTION__, + stdin_file_spec ? stdin_file_spec.GetCString() : "<null>", + stdout_file_spec ? stdout_file_spec.GetCString() : "<null>", + stderr_file_spec ? stderr_file_spec.GetCString() : "<null>"); if (stdin_file_spec) m_gdb_comm.SetSTDIN(stdin_file_spec); @@ -988,9 +923,8 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, } if (GetID() == LLDB_INVALID_PROCESS_ID) { - if (log) - log->Printf("failed to connect to debugserver: %s", - error.AsCString()); + LLDB_LOGF(log, "failed to connect to debugserver: %s", + error.AsCString()); KillDebugserverProcess(); return error; } @@ -1020,8 +954,7 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, } } } else { - if (log) - log->Printf("failed to connect to debugserver: %s", error.AsCString()); + LLDB_LOGF(log, "failed to connect to debugserver: %s", error.AsCString()); } } else { // Set our user ID to an invalid process ID. @@ -1040,9 +973,8 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (!connect_url.empty()) { - if (log) - log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, - connect_url.str().c_str()); + LLDB_LOGF(log, "ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, + connect_url.str().c_str()); std::unique_ptr<ConnectionFileDescriptor> conn_up( new ConnectionFileDescriptor()); if (conn_up) { @@ -1062,7 +994,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { if (retry_count >= max_retry_count) break; - usleep(100000); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } } @@ -1116,8 +1048,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s()", __FUNCTION__); if (GetID() != LLDB_INVALID_PROCESS_ID) { BuildDynamicRegisterInfo(false); @@ -1130,43 +1061,42 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); if (remote_process_arch.IsValid()) { process_arch = remote_process_arch; - if (log) - log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, " - "using %s %s", - __FUNCTION__, - process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", - process_arch.GetTriple().getTriple().c_str() - ? process_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s gdb-remote had process architecture, " + "using %s %s", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); } else { process_arch = m_gdb_comm.GetHostArchitecture(); - if (log) - log->Printf("ProcessGDBRemote::%s gdb-remote did not have process " - "architecture, using gdb-remote host architecture %s %s", - __FUNCTION__, - process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", - process_arch.GetTriple().getTriple().c_str() - ? process_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s gdb-remote did not have process " + "architecture, using gdb-remote host architecture %s %s", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); } if (process_arch.IsValid()) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); if (target_arch.IsValid()) { - if (log) - log->Printf( - "ProcessGDBRemote::%s analyzing target arch, currently %s %s", - __FUNCTION__, - target_arch.GetArchitectureName() - ? target_arch.GetArchitectureName() - : "<null>", - target_arch.GetTriple().getTriple().c_str() - ? target_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s analyzing target arch, currently %s %s", + __FUNCTION__, + target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", + target_arch.GetTriple().getTriple().c_str() + ? target_arch.GetTriple().getTriple().c_str() + : "<null>"); // If the remote host is ARM and we have apple as the vendor, then // ARM executables and shared libraries can have mixed ARM @@ -1180,16 +1110,16 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { process_arch.GetMachine() == llvm::Triple::thumb) && process_arch.GetTriple().getVendor() == llvm::Triple::Apple) { GetTarget().SetArchitecture(process_arch); - if (log) - log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, " - "setting target arch to %s %s", - __FUNCTION__, - process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", - process_arch.GetTriple().getTriple().c_str() - ? process_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s remote process is ARM/Apple, " + "setting target arch to %s %s", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", + process_arch.GetTriple().getTriple().c_str() + ? process_arch.GetTriple().getTriple().c_str() + : "<null>"); } else { // Fill in what is missing in the triple const llvm::Triple &remote_triple = process_arch.GetTriple(); @@ -1211,16 +1141,16 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { } } - if (log) - log->Printf("ProcessGDBRemote::%s final target arch after " - "adjustments for remote architecture: %s %s", - __FUNCTION__, - target_arch.GetArchitectureName() - ? target_arch.GetArchitectureName() - : "<null>", - target_arch.GetTriple().getTriple().c_str() - ? target_arch.GetTriple().getTriple().c_str() - : "<null>"); + LLDB_LOGF(log, + "ProcessGDBRemote::%s final target arch after " + "adjustments for remote architecture: %s %s", + __FUNCTION__, + target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", + target_arch.GetTriple().getTriple().c_str() + ? target_arch.GetTriple().getTriple().c_str() + : "<null>"); } else { // The target doesn't have a valid architecture yet, set it from the // architecture we got from the remote GDB server @@ -1247,8 +1177,7 @@ Status ProcessGDBRemote::DoAttachToProcessWithID( Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error; - if (log) - log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s()", __FUNCTION__); // Clear out and clean up from any current state Clear(); @@ -1359,8 +1288,7 @@ Status ProcessGDBRemote::WillResume() { Status ProcessGDBRemote::DoResume() { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::Resume()"); + LLDB_LOGF(log, "ProcessGDBRemote::Resume()"); ListenerSP listener_sp( Listener::MakeListener("gdb-remote.resume-packet-sent")); @@ -1547,9 +1475,8 @@ Status ProcessGDBRemote::DoResume() { EventSP event_sp; if (!m_async_thread.IsJoinable()) { error.SetErrorString("Trying to resume but the async thread is dead."); - if (log) - log->Printf("ProcessGDBRemote::DoResume: Trying to resume but the " - "async thread is dead."); + LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Trying to resume but the " + "async thread is dead."); return error; } @@ -1560,14 +1487,13 @@ Status ProcessGDBRemote::DoResume() { if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) { error.SetErrorString("Resume timed out."); - if (log) - log->Printf("ProcessGDBRemote::DoResume: Resume timed out."); + LLDB_LOGF(log, "ProcessGDBRemote::DoResume: Resume timed out."); } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) { error.SetErrorString("Broadcast continue, but the async thread was " "killed before we got an ack back."); - if (log) - log->Printf("ProcessGDBRemote::DoResume: Broadcast continue, but the " - "async thread was killed before we got an ack back."); + LLDB_LOGF(log, + "ProcessGDBRemote::DoResume: Broadcast continue, but the " + "async thread was killed before we got an ack back."); return error; } } @@ -1864,8 +1790,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( } for (const auto &pair : expedited_register_map) { - StringExtractor reg_value_extractor; - reg_value_extractor.GetStringRef() = pair.second; + StringExtractor reg_value_extractor(pair.second); DataBufferSP buffer_sp(new DataBufferHeap( reg_value_extractor.GetStringRef().size() / 2, 0)); reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); @@ -1979,8 +1904,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( if (watch_id == LLDB_INVALID_WATCH_ID) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( GDBR_LOG_WATCHPOINTS)); - if (log) - log->Printf("failed to find watchpoint"); + LLDB_LOGF(log, "failed to find watchpoint"); } thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( *thread_sp, watch_id, wp_hit_addr)); @@ -2400,7 +2324,12 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index); description = ostr.GetString(); } else if (key.compare("library") == 0) { - LoadModules(); + auto error = LoadModules(); + if (error) { + Log *log( + ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOG_ERROR(log, std::move(error), "Failed to load modules: {0}"); + } } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) { uint32_t reg = UINT32_MAX; if (!key.getAsInteger(16, reg)) @@ -2474,7 +2403,7 @@ void ProcessGDBRemote::RefreshStateAfterStop() { // Clear the thread stop stack m_stop_packet_stack.clear(); } - + // If we have queried for a default thread id if (m_initial_tid != LLDB_INVALID_THREAD_ID) { m_thread_list.SetSelectedThreadByID(m_initial_tid); @@ -2501,8 +2430,7 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) { Status ProcessGDBRemote::DoDetach(bool keep_stopped) { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); + LLDB_LOGF(log, "ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); error = m_gdb_comm.Detach(keep_stopped); if (log) { @@ -2510,8 +2438,9 @@ Status ProcessGDBRemote::DoDetach(bool keep_stopped) { log->PutCString( "ProcessGDBRemote::DoDetach() detach packet sent successfully"); else - log->Printf("ProcessGDBRemote::DoDetach() detach packet send failed: %s", - error.AsCString() ? error.AsCString() : "<unknown error>"); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDetach() detach packet send failed: %s", + error.AsCString() ? error.AsCString() : "<unknown error>"); } if (!error.Success()) @@ -2530,8 +2459,7 @@ Status ProcessGDBRemote::DoDetach(bool keep_stopped) { Status ProcessGDBRemote::DoDestroy() { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::DoDestroy()"); + LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy()"); // There is a bug in older iOS debugservers where they don't shut down the // process they are debugging properly. If the process is sitting at a @@ -2586,11 +2514,11 @@ Status ProcessGDBRemote::DoDestroy() { reason = stop_info_sp->GetStopReason(); if (reason == eStopReasonBreakpoint || reason == eStopReasonException) { - if (log) - log->Printf( - "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 - " stopped with reason: %s.", - thread_sp->GetProtocolID(), stop_info_sp->GetDescription()); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 + " stopped with reason: %s.", + thread_sp->GetProtocolID(), + stop_info_sp->GetDescription()); stop_looks_like_crash = true; break; } @@ -2622,10 +2550,10 @@ Status ProcessGDBRemote::DoDestroy() { reason = stop_info_sp->GetStopReason(); if (reason != eStopReasonBreakpoint && reason != eStopReasonException) { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy() - Suspending " - "thread: 0x%4.4" PRIx64 " before running.", - thread_sp->GetProtocolID()); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy() - Suspending " + "thread: 0x%4.4" PRIx64 " before running.", + thread_sp->GetProtocolID()); thread_sp->SetResumeState(eStateSuspended); } } @@ -2669,30 +2597,28 @@ Status ProcessGDBRemote::DoDestroy() { int status; ::pid_t reap_pid; reap_pid = waitpid(GetID(), &status, WNOHANG); - if (log) - log->Printf("Reaped pid: %d, status: %d.\n", reap_pid, status); + LLDB_LOGF(log, "Reaped pid: %d, status: %d.\n", reap_pid, status); } #endif SetLastStopPacket(response); ClearThreadIDList(); exit_status = response.GetHexU8(); } else { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response " - "to k packet: %s", - response.GetStringRef().c_str()); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy - got unexpected response " + "to k packet: %s", + response.GetStringRef().data()); exit_string.assign("got unexpected response to k packet: "); exit_string.append(response.GetStringRef()); } } else { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy - failed to send k packet"); + LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy - failed to send k packet"); exit_string.assign("failed to send the k packet"); } } else { - if (log) - log->Printf("ProcessGDBRemote::DoDestroy - killed or interrupted while " - "attaching"); + LLDB_LOGF(log, + "ProcessGDBRemote::DoDestroy - killed or interrupted while " + "attaching"); exit_string.assign("killed or interrupted while attaching."); } } else { @@ -2715,8 +2641,7 @@ void ProcessGDBRemote::SetLastStopPacket( response.GetStringRef().find(";reason:exec;") != std::string::npos; if (did_exec) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::SetLastStopPacket () - detected exec"); + LLDB_LOGF(log, "ProcessGDBRemote::SetLastStopPacket () - detected exec"); m_thread_list_real.Clear(); m_thread_list.Clear(); @@ -2756,9 +2681,13 @@ addr_t ProcessGDBRemote::GetImageInfoAddress() { // the loaded module list can also provides a link map address if (addr == LLDB_INVALID_ADDRESS) { - LoadedModuleInfoList list; - if (GetLoadedModuleList(list).Success()) - addr = list.m_link_map; + llvm::Expected<LoadedModuleInfoList> list = GetLoadedModuleList(); + if (!list) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOG_ERROR(log, list.takeError(), "Failed to read module list: {0}"); + } else { + addr = list->m_link_map; + } } return addr; @@ -2840,7 +2769,7 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, else error.SetErrorStringWithFormat( "unexpected response to GDB server memory read packet '%s': '%s'", - packet, response.GetStringRef().c_str()); + packet, response.GetStringRef().data()); } else { error.SetErrorStringWithFormat("failed to send packet: '%s'", packet); } @@ -2950,7 +2879,7 @@ Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) { else status.SetErrorStringWithFormat( "unexpected response to GDB server flash erase packet '%s': '%s'", - packet.GetData(), response.GetStringRef().c_str()); + packet.GetData(), response.GetStringRef().data()); } } else { status.SetErrorStringWithFormat("failed to send packet: '%s'", @@ -2978,7 +2907,7 @@ Status ProcessGDBRemote::FlashDone() { else status.SetErrorStringWithFormat( "unexpected response to GDB server flash done packet: '%s'", - response.GetStringRef().c_str()); + response.GetStringRef().data()); } } else { status.SetErrorStringWithFormat("failed to send flash done packet"); @@ -3041,7 +2970,7 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, else error.SetErrorStringWithFormat( "unexpected response to GDB server memory write packet '%s': '%s'", - packet.GetData(), response.GetStringRef().c_str()); + packet.GetData(), response.GetStringRef().data()); } else { error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetData()); @@ -3078,11 +3007,11 @@ lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, m_addr_to_mmap_size[allocated_addr] = size; else { allocated_addr = LLDB_INVALID_ADDRESS; - if (log) - log->Printf("ProcessGDBRemote::%s no direct stub support for memory " - "allocation, and InferiorCallMmap also failed - is stub " - "missing register context save/restore capability?", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s no direct stub support for memory " + "allocation, and InferiorCallMmap also failed - is stub " + "missing register context save/restore capability?", + __FUNCTION__); } } @@ -3173,17 +3102,17 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { const addr_t addr = bp_site->GetLoadAddress(); // Log that a breakpoint was requested - if (log) - log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 - ") address = 0x%" PRIx64, - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 + ") address = 0x%" PRIx64, + site_id, (uint64_t)addr); // Breakpoint already exists and is enabled if (bp_site->IsEnabled()) { - if (log) - log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 - ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 + ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", + site_id, (uint64_t)addr); return error; } @@ -3231,8 +3160,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { // We reach here when software breakpoints have been found to be // unsupported. For future calls to set a breakpoint, we will not attempt // to set a breakpoint with a type that is known not to be supported. - if (log) - log->Printf("Software breakpoints are unsupported"); + LLDB_LOGF(log, "Software breakpoints are unsupported"); // So we will fall through and try a hardware breakpoint } @@ -3270,8 +3198,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { // We will reach here when the stub gives an unsupported response to a // hardware breakpoint - if (log) - log->Printf("Hardware breakpoints are unsupported"); + LLDB_LOGF(log, "Hardware breakpoints are unsupported"); // Finally we will falling through to a #trap style breakpoint } @@ -3293,10 +3220,10 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { addr_t addr = bp_site->GetLoadAddress(); user_id_t site_id = bp_site->GetID(); Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); - if (log) - log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 - ") addr = 0x%8.8" PRIx64, - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 + ") addr = 0x%8.8" PRIx64, + site_id, (uint64_t)addr); if (bp_site->IsEnabled()) { const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); @@ -3328,10 +3255,10 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { if (error.Success()) bp_site->SetEnabled(false); } else { - if (log) - log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 - ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", - site_id, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 + ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", + site_id, (uint64_t)addr); return error; } @@ -3363,14 +3290,13 @@ Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { addr_t addr = wp->GetLoadAddress(); Log *log( ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); - if (log) - log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", - watchID); + LLDB_LOGF(log, "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", + watchID); if (wp->IsEnabled()) { - if (log) - log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", + watchID, (uint64_t)addr); return error; } @@ -3403,16 +3329,16 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { addr_t addr = wp->GetLoadAddress(); - if (log) - log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64, - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64, + watchID, (uint64_t)addr); if (!wp->IsEnabled()) { - if (log) - log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 - ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", - watchID, (uint64_t)addr); + LLDB_LOGF(log, + "ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 + ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", + watchID, (uint64_t)addr); // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling // attempt might come from the user-supplied actions, we'll route it in // order for the watchpoint object to intelligently process this action. @@ -3447,8 +3373,7 @@ void ProcessGDBRemote::Clear() { Status ProcessGDBRemote::DoSignal(int signo) { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::DoSignal (signal = %d)", signo); + LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo); if (!m_gdb_comm.SendAsyncSignal(signo)) error.SetErrorStringWithFormat("failed to send signal %i", signo); @@ -3460,7 +3385,8 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) { return Status("No loader provided."); // Construct replay history path. - FileSpec history_file = loader->GetFile<ProcessGDBRemoteProvider::Info>(); + FileSpec history_file = + loader->GetFile<repro::ProcessGDBRemoteProvider::Info>(); if (!history_file) return Status("No provider for gdb-remote."); @@ -3556,8 +3482,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( int our_socket = sockets[0]; int gdb_socket = sockets[1]; - CleanUp cleanup_our(close, our_socket); - CleanUp cleanup_gdb(close, gdb_socket); + auto cleanup_our = llvm::make_scope_exit([&]() { close(our_socket); }); + auto cleanup_gdb = llvm::make_scope_exit([&]() { close(gdb_socket); }); // Don't let any child processes inherit our communication socket SetCloexecFlag(our_socket); @@ -3577,7 +3503,7 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION // Our process spawned correctly, we can now set our connection to use // our end of the socket pair - cleanup_our.disable(); + cleanup_our.release(); m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket, true)); #endif StartAsyncThread(); @@ -3586,9 +3512,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( if (error.Fail()) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("failed to start debugserver process: %s", - error.AsCString()); + LLDB_LOGF(log, "failed to start debugserver process: %s", + error.AsCString()); return error; } @@ -3614,22 +3539,22 @@ bool ProcessGDBRemote::MonitorDebugserverProcess( Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); const bool handled = true; - if (log) - log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 - ", signo=%i (0x%x), exit_status=%i)", - __FUNCTION__, debugserver_pid, signo, signo, exit_status); + LLDB_LOGF(log, + "ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 + ", signo=%i (0x%x), exit_status=%i)", + __FUNCTION__, debugserver_pid, signo, signo, exit_status); std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock(); - if (log) - log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, - static_cast<void *>(process_sp.get())); + LLDB_LOGF(log, "ProcessGDBRemote::%s(process = %p)", __FUNCTION__, + static_cast<void *>(process_sp.get())); if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) return handled; // Sleep for a half a second to make sure our inferior process has time to // set its exit status before we set it incorrectly when both the debugserver // and the inferior process shut down. - usleep(500000); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + // If our process hasn't yet exited, debugserver might have died. If the // process did exit, then we are reaping it. const StateType state = process_sp->GetState(); @@ -3692,8 +3617,7 @@ void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) { bool ProcessGDBRemote::StartAsyncThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); if (!m_async_thread.IsJoinable()) { @@ -3709,10 +3633,11 @@ bool ProcessGDBRemote::StartAsyncThread() { return false; } m_async_thread = *async_thread; - } else if (log) - log->Printf("ProcessGDBRemote::%s () - Called when Async thread was " - "already running.", - __FUNCTION__); + } else + LLDB_LOGF(log, + "ProcessGDBRemote::%s () - Called when Async thread was " + "already running.", + __FUNCTION__); return m_async_thread.IsJoinable(); } @@ -3720,8 +3645,7 @@ bool ProcessGDBRemote::StartAsyncThread() { void ProcessGDBRemote::StopAsyncThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s ()", __FUNCTION__); std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); if (m_async_thread.IsJoinable()) { @@ -3733,8 +3657,9 @@ void ProcessGDBRemote::StopAsyncThread() { // Stop the stdio thread m_async_thread.Join(nullptr); m_async_thread.Reset(); - } else if (log) - log->Printf( + } else + LLDB_LOGF( + log, "ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__); } @@ -3768,25 +3693,25 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ProcessGDBRemote *process = (ProcessGDBRemote *)arg; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") thread starting...", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") thread starting...", + __FUNCTION__, arg, process->GetID()); EventSP event_sp; bool done = false; while (!done) { - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") listener.WaitForEvent (NULL, event_sp)...", - __FUNCTION__, arg, process->GetID()); + 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)) { - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") Got an event of type: %d...", - __FUNCTION__, arg, process->GetID(), event_type); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") Got an event of type: %d...", + __FUNCTION__, arg, process->GetID(), event_type); switch (event_type) { case eBroadcastBitAsyncContinue: { @@ -3797,10 +3722,10 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { const char *continue_cstr = (const char *)continue_packet->GetBytes(); const size_t continue_cstr_len = continue_packet->GetByteSize(); - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got eBroadcastBitAsyncContinue: %s", - __FUNCTION__, arg, process->GetID(), continue_cstr); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got eBroadcastBitAsyncContinue: %s", + __FUNCTION__, arg, process->GetID(), continue_cstr); if (::strstr(continue_cstr, "vAttach") == nullptr) process->SetPrivateState(eStateRunning); @@ -3891,18 +3816,18 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { break; case eBroadcastBitAsyncThreadShouldExit: - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got eBroadcastBitAsyncThreadShouldExit...", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got eBroadcastBitAsyncThreadShouldExit...", + __FUNCTION__, arg, process->GetID()); done = true; break; default: - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got unknown event 0x%8.8x", - __FUNCTION__, arg, process->GetID(), event_type); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got unknown event 0x%8.8x", + __FUNCTION__, arg, process->GetID(), event_type); done = true; break; } @@ -3925,27 +3850,27 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { } default: - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") got unknown event 0x%8.8x", - __FUNCTION__, arg, process->GetID(), event_type); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") got unknown event 0x%8.8x", + __FUNCTION__, arg, process->GetID(), event_type); done = true; break; } } } else { - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") listener.WaitForEvent (NULL, event_sp) => false", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") listener.WaitForEvent (NULL, event_sp) => false", + __FUNCTION__, arg, process->GetID()); done = true; } } - if (log) - log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 - ") thread exiting...", - __FUNCTION__, arg, process->GetID()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 + ") thread exiting...", + __FUNCTION__, arg, process->GetID()); return {}; } @@ -3977,8 +3902,7 @@ bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( // thread when it starts to // run so I can stop it if that's what I want to do. Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Hit New Thread Notification breakpoint."); + LLDB_LOGF(log, "Hit New Thread Notification breakpoint."); return false; } @@ -4023,7 +3947,7 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (m_thread_create_bp_sp) { if (log && log->GetVerbose()) - log->Printf("Enabled noticing new thread breakpoint."); + LLDB_LOGF(log, "Enabled noticing new thread breakpoint."); m_thread_create_bp_sp->SetEnabled(true); } else { PlatformSP platform_sp(GetTarget().GetPlatform()); @@ -4032,14 +3956,13 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { platform_sp->SetThreadCreationBreakpoint(GetTarget()); if (m_thread_create_bp_sp) { if (log && log->GetVerbose()) - log->Printf( - "Successfully created new thread notification breakpoint %i", + LLDB_LOGF( + log, "Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID()); m_thread_create_bp_sp->SetCallback( ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true); } else { - if (log) - log->Printf("Failed to create new thread notification breakpoint."); + LLDB_LOGF(log, "Failed to create new thread notification breakpoint."); } } } @@ -4049,7 +3972,7 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { bool ProcessGDBRemote::StopNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) - log->Printf("Disabling new thread notification breakpoint."); + LLDB_LOGF(log, "Disabling new thread notification breakpoint."); if (m_thread_create_bp_sp) m_thread_create_bp_sp->SetEnabled(false); @@ -4325,19 +4248,18 @@ bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec, } if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) { - if (log) - log->Printf("ProcessGDBRemote::%s - failed to get module info for %s:%s", - __FUNCTION__, module_file_spec.GetPath().c_str(), - arch.GetTriple().getTriple().c_str()); + LLDB_LOGF(log, "ProcessGDBRemote::%s - failed to get module info for %s:%s", + __FUNCTION__, module_file_spec.GetPath().c_str(), + arch.GetTriple().getTriple().c_str()); return false; } if (log) { StreamString stream; module_spec.Dump(stream); - log->Printf("ProcessGDBRemote::%s - got module info for (%s:%s) : %s", - __FUNCTION__, module_file_spec.GetPath().c_str(), - arch.GetTriple().getTriple().c_str(), stream.GetData()); + LLDB_LOGF(log, "ProcessGDBRemote::%s - got module info for (%s:%s) : %s", + __FUNCTION__, module_file_spec.GetPath().c_str(), + arch.GetTriple().getTriple().c_str(), stream.GetData()); } m_cached_module_specs[key] = module_spec; @@ -4361,6 +4283,10 @@ llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() { return m_gdb_comm.GetOSVersion(); } +llvm::VersionTuple ProcessGDBRemote::GetHostMacCatalystVersion() { + return m_gdb_comm.GetMacCatalystVersion(); +} + namespace { typedef std::vector<std::string> stringVec; @@ -4492,14 +4418,13 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, } else if (name == "invalidate_regnums") { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0); } else if (name == "dynamic_size_dwarf_expr_bytes") { - StringExtractor opcode_extractor; std::string opcode_string = value.str(); size_t dwarf_opcode_len = opcode_string.length() / 2; assert(dwarf_opcode_len > 0); dwarf_opcode_bytes.resize(dwarf_opcode_len); reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; - opcode_extractor.GetStringRef().swap(opcode_string); + StringExtractor opcode_extractor(opcode_string); uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); assert(dwarf_opcode_len == ret_val); @@ -4565,16 +4490,15 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, // information to the current process. It will call itself recursively // for nested register definition files. It returns true if it was able // to fetch and parse an xml file. -bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_use, - std::string xml_filename, - uint32_t &cur_reg_num, - uint32_t ®_offset) { +bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( + ArchSpec &arch_to_use, std::string xml_filename, uint32_t &cur_reg_num, + uint32_t ®_offset) { // request the target xml file std::string raw; lldb_private::Status lldberr; - if (!m_gdb_comm.ReadExtFeature(ConstString("features"), - ConstString(xml_filename.c_str()), - raw, lldberr)) { + if (!m_gdb_comm.ReadExtFeature(ConstString("features"), + ConstString(xml_filename.c_str()), raw, + lldberr)) { return false; } @@ -4676,8 +4600,8 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_u } for (const auto &include : target_info.includes) { - GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, - cur_reg_num, reg_offset); + GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, cur_reg_num, + reg_offset); } } } else { @@ -4705,41 +4629,43 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { return m_register_info.GetNumRegisters() > 0; } -Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { +llvm::Expected<LoadedModuleInfoList> ProcessGDBRemote::GetLoadedModuleList() { // Make sure LLDB has an XML parser it can use first if (!XMLDocument::XMLEnabled()) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "XML parsing not available"); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS); - if (log) - log->Printf("ProcessGDBRemote::%s", __FUNCTION__); + LLDB_LOGF(log, "ProcessGDBRemote::%s", __FUNCTION__); + LoadedModuleInfoList list; GDBRemoteCommunicationClient &comm = m_gdb_comm; bool can_use_svr4 = GetGlobalPluginProperties()->GetUseSVR4(); // check that we have extended feature read support if (can_use_svr4 && comm.GetQXferLibrariesSVR4ReadSupported()) { - list.clear(); - // request the loaded library list std::string raw; lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""), raw, lldberr)) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error in libraries-svr4 packet"); // parse the xml file in memory - if (log) - log->Printf("parsing: %s", raw.c_str()); + LLDB_LOGF(log, "parsing: %s", raw.c_str()); XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error reading noname.xml"); XMLNode root_element = doc.GetRootElement("library-list-svr4"); if (!root_element) - return Status(); + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Error finding library-list-svr4 xml element"); // main link map structure llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm"); @@ -4791,10 +4717,11 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { module.get_base_is_offset(base_is_offset); module.get_dynamic(ld); - log->Printf("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 - "[%s], ld:0x%08" PRIx64 ", name:'%s')", - lm, base, (base_is_offset ? "offset" : "absolute"), ld, - name.c_str()); + LLDB_LOGF(log, + "found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 + "[%s], ld:0x%08" PRIx64 ", name:'%s')", + lm, base, (base_is_offset ? "offset" : "absolute"), ld, + name.c_str()); } list.add(module); @@ -4803,29 +4730,30 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { }); if (log) - log->Printf("found %" PRId32 " modules in total", - (int)list.m_list.size()); + LLDB_LOGF(log, "found %" PRId32 " modules in total", + (int)list.m_list.size()); + return list; } else if (comm.GetQXferLibrariesReadSupported()) { - list.clear(); - // request the loaded library list std::string raw; lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw, lldberr)) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error in libraries packet"); - if (log) - log->Printf("parsing: %s", raw.c_str()); + LLDB_LOGF(log, "parsing: %s", raw.c_str()); XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error reading noname.xml"); XMLNode root_element = doc.GetRootElement("library-list"); if (!root_element) - return Status(); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error finding library-list xml element"); root_element.ForEachChildElementWithName( "library", [log, &list](const XMLNode &library) -> bool { @@ -4853,8 +4781,8 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { module.get_base(base); module.get_base_is_offset(base_is_offset); - log->Printf("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, - (base_is_offset ? "offset" : "absolute"), name.c_str()); + LLDB_LOGF(log, "found (base:0x%08" PRIx64 "[%s], name:'%s')", base, + (base_is_offset ? "offset" : "absolute"), name.c_str()); } list.add(module); @@ -4863,13 +4791,13 @@ Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { }); if (log) - log->Printf("found %" PRId32 " modules in total", - (int)list.m_list.size()); + LLDB_LOGF(log, "found %" PRId32 " modules in total", + (int)list.m_list.size()); + return list; } else { - return Status(0, ErrorType::eErrorTypeGeneric); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Remote libraries not supported"); } - - return Status(); } lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, @@ -4884,17 +4812,18 @@ lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, value_is_offset); } -size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) { +llvm::Error ProcessGDBRemote::LoadModules() { using lldb_private::process_gdb_remote::ProcessGDBRemote; // request a list of loaded libraries from GDBServer - if (GetLoadedModuleList(module_list).Fail()) - return 0; + llvm::Expected<LoadedModuleInfoList> module_list = GetLoadedModuleList(); + if (!module_list) + return module_list.takeError(); // get a list of all the modules ModuleList new_modules; - for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list.m_list) { + for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list->m_list) { std::string mod_name; lldb::addr_t mod_base; lldb::addr_t link_map; @@ -4961,12 +4890,7 @@ size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) { m_process->GetTarget().ModulesDidLoad(new_modules); } - return new_modules.GetSize(); -} - -size_t ProcessGDBRemote::LoadModules() { - LoadedModuleInfoList module_list; - return LoadModules(module_list); + return llvm::ErrorSuccess(); } Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, @@ -5149,7 +5073,8 @@ ParseStructuredDataPacket(llvm::StringRef packet) { if (!packet.consume_front(s_async_json_packet_prefix)) { if (log) { - log->Printf( + LLDB_LOGF( + log, "GDBRemoteCommunicationClientBase::%s() received $J packet " "but was not a StructuredData packet: packet starts with " "%s", @@ -5164,16 +5089,18 @@ ParseStructuredDataPacket(llvm::StringRef packet) { if (log) { if (json_sp) { StreamString json_str; - json_sp->Dump(json_str); + json_sp->Dump(json_str, true); json_str.Flush(); - log->Printf("ProcessGDBRemote::%s() " - "received Async StructuredData packet: %s", - __FUNCTION__, json_str.GetData()); + LLDB_LOGF(log, + "ProcessGDBRemote::%s() " + "received Async StructuredData packet: %s", + __FUNCTION__, json_str.GetData()); } else { - log->Printf("ProcessGDBRemote::%s" - "() received StructuredData packet:" - " parse failure", - __FUNCTION__); + LLDB_LOGF(log, + "ProcessGDBRemote::%s" + "() received StructuredData packet:" + " parse failure", + __FUNCTION__); } } return json_sp; @@ -5365,7 +5292,7 @@ public: result.SetStatus(eReturnStatusSuccessFinishResult); Stream &output_strm = result.GetOutputStream(); output_strm.Printf(" packet: %s\n", packet_cstr); - std::string &response_str = response.GetStringRef(); + std::string response_str = response.GetStringRef(); if (strstr(packet_cstr, "qGetProfileData") != nullptr) { response_str = process->HarmonizeThreadIdsForProfileData(response); @@ -5374,7 +5301,7 @@ public: if (response_str.empty()) output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); else - output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); + output_strm.Printf("response: %s\n", response.GetStringRef().data()); } } return true; @@ -5423,7 +5350,7 @@ public: if (response_str.empty()) output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); else - output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); + output_strm.Printf("response: %s\n", response.GetStringRef().data()); } return true; } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 9c41fc2e5e98..0e3e3b39d9c8 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -24,8 +24,8 @@ #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/ConstString.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringExtractor.h" #include "lldb/Utility/StringList.h" @@ -199,10 +199,11 @@ public: const llvm::Triple &triple) override; llvm::VersionTuple GetHostOSVersion() override; + llvm::VersionTuple GetHostMacCatalystVersion() override; - size_t LoadModules(LoadedModuleInfoList &module_list) override; + llvm::Error LoadModules() override; - size_t LoadModules() override; + llvm::Expected<LoadedModuleInfoList> GetLoadedModuleList() override; Status GetFileLoadAddress(const FileSpec &file, bool &is_loaded, lldb::addr_t &load_addr) override; @@ -391,9 +392,6 @@ protected: // Query remote GDBServer for register information bool GetGDBServerRegisterInfo(ArchSpec &arch); - // Query remote GDBServer for a detailed loaded library list - Status GetLoadedModuleList(LoadedModuleInfoList &); - lldb::ModuleSP LoadModuleAtAddress(const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr, diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td new file mode 100644 index 000000000000..16e7723e3061 --- /dev/null +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td @@ -0,0 +1,16 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "processgdbremote" in { + def PacketTimeout: Property<"packet-timeout", "UInt64">, + Global, + DefaultUnsignedValue<5>, + Desc<"Specify the default packet timeout in seconds.">; + def TargetDefinitionFile: Property<"target-definition-file", "FileSpec">, + Global, + DefaultStringValue<"">, + Desc<"The file that provides the description for remote target registers.">; + def UseSVR4: Property<"use-libraries-svr4", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules.">; +} diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 6607bce4488b..8a6a58c55450 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -215,8 +215,7 @@ StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() { StructuredData::ObjectSP object_sp; const lldb::user_id_t tid = GetProtocolID(); Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); - if (log) - log->Printf("Fetching extended information for thread %4.4" PRIx64, tid); + LLDB_LOGF(log, "Fetching extended information for thread %4.4" PRIx64, tid); ProcessSP process_sp(GetProcess()); if (process_sp) { ProcessGDBRemote *gdb_process = @@ -230,9 +229,8 @@ void ThreadGDBRemote::WillResume(StateType resume_state) { int signo = GetResumeSignal(); const lldb::user_id_t tid = GetProtocolID(); Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); - if (log) - log->Printf("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, - StateAsCString(resume_state)); + LLDB_LOGF(log, "Resuming thread: %4.4" PRIx64 " with state: %s.", tid, + StateAsCString(resume_state)); ProcessSP process_sp(GetProcess()); if (process_sp) { diff --git a/source/Plugins/Process/minidump/MinidumpParser.cpp b/source/Plugins/Process/minidump/MinidumpParser.cpp index ff015aa54b76..70933f91fe51 100644 --- a/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -188,6 +188,7 @@ ArchSpec MinidumpParser::GetArchitecture() { case OSPlatform::Win32NT: case OSPlatform::Win32CE: triple.setOS(llvm::Triple::OSType::Win32); + triple.setVendor(llvm::Triple::VendorType::PC); break; case OSPlatform::Linux: triple.setOS(llvm::Triple::OSType::Linux); @@ -313,13 +314,15 @@ std::vector<const minidump::Module *> MinidumpParser::GetFilteredModuleList() { return filtered_modules; } -const MinidumpExceptionStream *MinidumpParser::GetExceptionStream() { - llvm::ArrayRef<uint8_t> data = GetStream(StreamType::Exception); +const minidump::ExceptionStream *MinidumpParser::GetExceptionStream() { + auto ExpectedStream = GetMinidumpFile().getExceptionStream(); + if (ExpectedStream) + return &*ExpectedStream; - if (data.size() == 0) - return nullptr; - - return MinidumpExceptionStream::Parse(data); + LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS), + ExpectedStream.takeError(), + "Failed to read minidump exception stream: {0}"); + return nullptr; } llvm::Optional<minidump::Range> @@ -426,23 +429,35 @@ CreateRegionsCacheFromLinuxMaps(MinidumpParser &parser, static bool CreateRegionsCacheFromMemoryInfoList(MinidumpParser &parser, std::vector<MemoryRegionInfo> ®ions) { - auto data = parser.GetStream(StreamType::MemoryInfoList); - if (data.empty()) - return false; - auto mem_info_list = MinidumpMemoryInfo::ParseMemoryInfoList(data); - if (mem_info_list.empty()) + Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES); + auto ExpectedInfo = parser.GetMinidumpFile().getMemoryInfoList(); + if (!ExpectedInfo) { + LLDB_LOG_ERROR(log, ExpectedInfo.takeError(), + "Failed to read memory info list: {0}"); return false; + } constexpr auto yes = MemoryRegionInfo::eYes; constexpr auto no = MemoryRegionInfo::eNo; - regions.reserve(mem_info_list.size()); - for (const auto &entry : mem_info_list) { + for (const MemoryInfo &entry : *ExpectedInfo) { MemoryRegionInfo region; - region.GetRange().SetRangeBase(entry->base_address); - region.GetRange().SetByteSize(entry->region_size); - region.SetReadable(entry->isReadable() ? yes : no); - region.SetWritable(entry->isWritable() ? yes : no); - region.SetExecutable(entry->isExecutable() ? yes : no); - region.SetMapped(entry->isMapped() ? yes : no); + region.GetRange().SetRangeBase(entry.BaseAddress); + region.GetRange().SetByteSize(entry.RegionSize); + + MemoryProtection prot = entry.Protect; + region.SetReadable(bool(prot & MemoryProtection::NoAccess) ? no : yes); + region.SetWritable( + bool(prot & (MemoryProtection::ReadWrite | MemoryProtection::WriteCopy | + MemoryProtection::ExecuteReadWrite | + MemoryProtection::ExeciteWriteCopy)) + ? yes + : no); + region.SetExecutable( + bool(prot & (MemoryProtection::Execute | MemoryProtection::ExecuteRead | + MemoryProtection::ExecuteReadWrite | + MemoryProtection::ExeciteWriteCopy)) + ? yes + : no); + region.SetMapped(entry.State != MemoryState::Free ? yes : no); regions.push_back(region); } return !regions.empty(); diff --git a/source/Plugins/Process/minidump/MinidumpParser.h b/source/Plugins/Process/minidump/MinidumpParser.h index fce64f0ed5fc..d206fe6c9a00 100644 --- a/source/Plugins/Process/minidump/MinidumpParser.h +++ b/source/Plugins/Process/minidump/MinidumpParser.h @@ -82,7 +82,7 @@ public: // have the same name, it keeps the copy with the lowest load address. std::vector<const minidump::Module *> GetFilteredModuleList(); - const MinidumpExceptionStream *GetExceptionStream(); + const llvm::minidump::ExceptionStream *GetExceptionStream(); llvm::Optional<Range> FindMemoryRange(lldb::addr_t addr); diff --git a/source/Plugins/Process/minidump/MinidumpTypes.cpp b/source/Plugins/Process/minidump/MinidumpTypes.cpp index d7fc6e43d090..ed00b1cc07db 100644 --- a/source/Plugins/Process/minidump/MinidumpTypes.cpp +++ b/source/Plugins/Process/minidump/MinidumpTypes.cpp @@ -57,17 +57,6 @@ LinuxProcStatus::Parse(llvm::ArrayRef<uint8_t> &data) { lldb::pid_t LinuxProcStatus::GetPid() const { return pid; } -// Exception stuff -const MinidumpExceptionStream * -MinidumpExceptionStream::Parse(llvm::ArrayRef<uint8_t> &data) { - const MinidumpExceptionStream *exception_stream = nullptr; - Status error = consumeObject(data, exception_stream); - if (error.Fail()) - return nullptr; - - return exception_stream; -} - std::pair<llvm::ArrayRef<MinidumpMemoryDescriptor64>, uint64_t> MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) { const llvm::support::ulittle64_t *mem_ranges_count; @@ -87,29 +76,3 @@ MinidumpMemoryDescriptor64::ParseMemory64List(llvm::ArrayRef<uint8_t> &data) { *mem_ranges_count), *base_rva); } - -std::vector<const MinidumpMemoryInfo *> -MinidumpMemoryInfo::ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data) { - const MinidumpMemoryInfoListHeader *header; - Status error = consumeObject(data, header); - if (error.Fail() || - header->size_of_header < sizeof(MinidumpMemoryInfoListHeader) || - header->size_of_entry < sizeof(MinidumpMemoryInfo)) - return {}; - - data = data.drop_front(header->size_of_header - - sizeof(MinidumpMemoryInfoListHeader)); - - if (header->size_of_entry * header->num_of_entries > data.size()) - return {}; - - std::vector<const MinidumpMemoryInfo *> result; - result.reserve(header->num_of_entries); - - for (uint64_t i = 0; i < header->num_of_entries; ++i) { - result.push_back(reinterpret_cast<const MinidumpMemoryInfo *>( - data.data() + i * header->size_of_entry)); - } - - return result; -} diff --git a/source/Plugins/Process/minidump/MinidumpTypes.h b/source/Plugins/Process/minidump/MinidumpTypes.h index b4878e82de5d..a9c807930ebf 100644 --- a/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/source/Plugins/Process/minidump/MinidumpTypes.h @@ -85,90 +85,6 @@ struct MinidumpMemoryDescriptor64 { static_assert(sizeof(MinidumpMemoryDescriptor64) == 16, "sizeof MinidumpMemoryDescriptor64 is not correct!"); -// Reference: -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680385(v=vs.85).aspx -struct MinidumpMemoryInfoListHeader { - llvm::support::ulittle32_t size_of_header; - llvm::support::ulittle32_t size_of_entry; - llvm::support::ulittle64_t num_of_entries; -}; -static_assert(sizeof(MinidumpMemoryInfoListHeader) == 16, - "sizeof MinidumpMemoryInfoListHeader is not correct!"); - -enum class MinidumpMemoryInfoState : uint32_t { - MemCommit = 0x1000, - MemFree = 0x10000, - MemReserve = 0x2000, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemFree) -}; - -enum class MinidumpMemoryInfoType : uint32_t { - MemImage = 0x1000000, - MemMapped = 0x40000, - MemPrivate = 0x20000, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ MemImage) -}; - -// Reference: -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366786(v=vs.85).aspx -enum class MinidumpMemoryProtectionContants : uint32_t { - PageExecute = 0x10, - PageExecuteRead = 0x20, - PageExecuteReadWrite = 0x40, - PageExecuteWriteCopy = 0x80, - PageNoAccess = 0x01, - PageReadOnly = 0x02, - PageReadWrite = 0x04, - PageWriteCopy = 0x08, - PageTargetsInvalid = 0x40000000, - PageTargetsNoUpdate = 0x40000000, - - PageWritable = PageExecuteReadWrite | PageExecuteWriteCopy | PageReadWrite | - PageWriteCopy, - PageExecutable = PageExecute | PageExecuteRead | PageExecuteReadWrite | - PageExecuteWriteCopy, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ PageTargetsInvalid) -}; - -// Reference: -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680386(v=vs.85).aspx -struct MinidumpMemoryInfo { - llvm::support::ulittle64_t base_address; - llvm::support::ulittle64_t allocation_base; - llvm::support::ulittle32_t allocation_protect; - llvm::support::ulittle32_t alignment1; - llvm::support::ulittle64_t region_size; - llvm::support::ulittle32_t state; - llvm::support::ulittle32_t protect; - llvm::support::ulittle32_t type; - llvm::support::ulittle32_t alignment2; - - static std::vector<const MinidumpMemoryInfo *> - ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data); - - bool isReadable() const { - const auto mask = MinidumpMemoryProtectionContants::PageNoAccess; - return (static_cast<uint32_t>(mask) & protect) == 0; - } - - bool isWritable() const { - const auto mask = MinidumpMemoryProtectionContants::PageWritable; - return (static_cast<uint32_t>(mask) & protect) != 0; - } - - bool isExecutable() const { - const auto mask = MinidumpMemoryProtectionContants::PageExecutable; - return (static_cast<uint32_t>(mask) & protect) != 0; - } - - bool isMapped() const { - return state != static_cast<uint32_t>(MinidumpMemoryInfoState::MemFree); - } -}; - -static_assert(sizeof(MinidumpMemoryInfo) == 48, - "sizeof MinidumpMemoryInfo is not correct!"); - // TODO misc2, misc3 ? // Reference: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680389(v=vs.85).aspx @@ -202,35 +118,6 @@ private: LinuxProcStatus() = default; }; -// Exception stuff -struct MinidumpException { - enum : unsigned { - ExceptonInfoMaxParams = 15, - DumpRequested = 0xFFFFFFFF, - }; - - llvm::support::ulittle32_t exception_code; - llvm::support::ulittle32_t exception_flags; - llvm::support::ulittle64_t exception_record; - llvm::support::ulittle64_t exception_address; - llvm::support::ulittle32_t number_parameters; - llvm::support::ulittle32_t unused_alignment; - llvm::support::ulittle64_t exception_information[ExceptonInfoMaxParams]; -}; -static_assert(sizeof(MinidumpException) == 152, - "sizeof MinidumpException is not correct!"); - -struct MinidumpExceptionStream { - llvm::support::ulittle32_t thread_id; - llvm::support::ulittle32_t alignment; - MinidumpException exception_record; - LocationDescriptor thread_context; - - static const MinidumpExceptionStream *Parse(llvm::ArrayRef<uint8_t> &data); -}; -static_assert(sizeof(MinidumpExceptionStream) == 168, - "sizeof MinidumpExceptionStream is not correct!"); - } // namespace minidump } // namespace lldb_private #endif // liblldb_MinidumpTypes_h_ diff --git a/source/Plugins/Process/minidump/ProcessMinidump.cpp b/source/Plugins/Process/minidump/ProcessMinidump.cpp index a7fc42cad16c..e30a3c82a887 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -49,16 +49,19 @@ namespace { class PlaceholderObjectFile : public ObjectFile { public: PlaceholderObjectFile(const lldb::ModuleSP &module_sp, - const ModuleSpec &module_spec, lldb::offset_t base, - lldb::offset_t size) + const ModuleSpec &module_spec, lldb::addr_t base, + lldb::addr_t size) : ObjectFile(module_sp, &module_spec.GetFileSpec(), /*file_offset*/ 0, /*length*/ 0, /*data_sp*/ nullptr, /*data_offset*/ 0), m_arch(module_spec.GetArchitecture()), m_uuid(module_spec.GetUUID()), m_base(base), m_size(size) { - m_symtab_up = llvm::make_unique<Symtab>(this); + m_symtab_up = std::make_unique<Symtab>(this); } - ConstString GetPluginName() override { return ConstString("placeholder"); } + static ConstString GetStaticPluginName() { + return ConstString("placeholder"); + } + ConstString GetPluginName() override { return GetStaticPluginName(); } uint32_t GetPluginVersion() override { return 1; } bool ParseHeader() override { return true; } Type CalculateType() override { return eTypeUnknown; } @@ -80,7 +83,7 @@ public: } void CreateSections(SectionList &unified_section_list) override { - m_sections_up = llvm::make_unique<SectionList>(); + m_sections_up = std::make_unique<SectionList>(); auto section_sp = std::make_shared<Section>( GetModule(), this, /*sect_id*/ 0, ConstString(".module_image"), eSectionTypeOther, m_base, m_size, /*file_offset*/ 0, /*file_size*/ 0, @@ -109,11 +112,12 @@ public: GetFileSpec(), m_base, m_base + m_size); } + lldb::addr_t GetBaseImageAddress() const { return m_base; } private: ArchSpec m_arch; UUID m_uuid; - lldb::offset_t m_base; - lldb::offset_t m_size; + lldb::addr_t m_base; + lldb::addr_t m_size; }; } // namespace @@ -215,6 +219,9 @@ Status ProcessMinidump::DoLoadCore() { m_thread_list = m_minidump_parser->GetThreads(); m_active_exception = m_minidump_parser->GetExceptionStream(); + + SetUnixSignals(UnixSignals::Create(GetArchitecture())); + ReadModuleList(); llvm::Optional<lldb::pid_t> pid = m_minidump_parser->GetPid(); @@ -234,39 +241,56 @@ uint32_t ProcessMinidump::GetPluginVersion() { return 1; } Status ProcessMinidump::DoDestroy() { return Status(); } void ProcessMinidump::RefreshStateAfterStop() { + if (!m_active_exception) return; - if (m_active_exception->exception_record.exception_code == - MinidumpException::DumpRequested) { + constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF; + if (m_active_exception->ExceptionRecord.ExceptionCode == + BreakpadDumpRequested) { + // This "ExceptionCode" value is a sentinel that is sometimes used + // when generating a dump for a process that hasn't crashed. + + // TODO: The definition and use of this "dump requested" constant + // in Breakpad are actually Linux-specific, and for similar use + // cases on Mac/Windows it defines differnt constants, referring + // to them as "simulated" exceptions; consider moving this check + // down to the OS-specific paths and checking each OS for its own + // constant. return; } lldb::StopInfoSP stop_info; lldb::ThreadSP stop_thread; - Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id); + Process::m_thread_list.SetSelectedThreadByID(m_active_exception->ThreadId); stop_thread = Process::m_thread_list.GetSelectedThread(); ArchSpec arch = GetArchitecture(); if (arch.GetTriple().getOS() == llvm::Triple::Linux) { + uint32_t signo = m_active_exception->ExceptionRecord.ExceptionCode; + + if (signo == 0) { + // No stop. + return; + } + stop_info = StopInfo::CreateStopReasonWithSignal( - *stop_thread, m_active_exception->exception_record.exception_code); + *stop_thread, signo); } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) { stop_info = StopInfoMachException::CreateStopReasonWithMachException( - *stop_thread, m_active_exception->exception_record.exception_code, 2, - m_active_exception->exception_record.exception_flags, - m_active_exception->exception_record.exception_address, 0); + *stop_thread, m_active_exception->ExceptionRecord.ExceptionCode, 2, + m_active_exception->ExceptionRecord.ExceptionFlags, + m_active_exception->ExceptionRecord.ExceptionAddress, 0); } else { std::string desc; llvm::raw_string_ostream desc_stream(desc); desc_stream << "Exception " << llvm::format_hex( - m_active_exception->exception_record.exception_code, 8) + m_active_exception->ExceptionRecord.ExceptionCode, 8) << " encountered at address " << llvm::format_hex( - m_active_exception->exception_record.exception_address, - 8); + m_active_exception->ExceptionRecord.ExceptionAddress, 8); stop_info = StopInfo::CreateStopReasonWithException( *stop_thread, desc_stream.str().c_str()); } @@ -331,8 +355,8 @@ bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list, // If the minidump contains an exception context, use it if (m_active_exception != nullptr && - m_active_exception->thread_id == thread.ThreadId) { - context_location = m_active_exception->thread_context; + m_active_exception->ThreadId == thread.ThreadId) { + context_location = m_active_exception->ThreadContext; } llvm::ArrayRef<uint8_t> context; @@ -351,14 +375,15 @@ void ProcessMinidump::ReadModuleList() { std::vector<const minidump::Module *> filtered_modules = m_minidump_parser->GetFilteredModuleList(); - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); for (auto module : filtered_modules) { std::string name = cantFail(m_minidump_parser->GetMinidumpFile().getString( module->ModuleNameRVA)); + const uint64_t load_addr = module->BaseOfImage; + const uint64_t load_size = module->SizeOfImage; LLDB_LOG(log, "found module: name: {0} {1:x10}-{2:x10} size: {3}", name, - module->BaseOfImage, module->BaseOfImage + module->SizeOfImage, - module->SizeOfImage); + load_addr, load_addr + load_size, load_size); // check if the process is wow64 - a 32 bit windows process running on a // 64 bit windows @@ -373,7 +398,7 @@ void ProcessMinidump::ReadModuleList() { Status error; // Try and find a module with a full UUID that matches. This function will // add the module to the target if it finds one. - lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec, + lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec, true /* notify */, &error); if (!module_sp) { // Try and find a module without specifying the UUID and only looking for @@ -386,8 +411,8 @@ void ProcessMinidump::ReadModuleList() { ModuleSpec basename_module_spec(module_spec); basename_module_spec.GetUUID().Clear(); basename_module_spec.GetFileSpec().GetDirectory().Clear(); - module_sp = GetTarget().GetOrCreateModule(basename_module_spec, - true /* notify */, &error); + module_sp = GetTarget().GetOrCreateModule(basename_module_spec, + true /* notify */, &error); if (module_sp) { // We consider the module to be a match if the minidump UUID is a // prefix of the actual UUID, or if either of the UUIDs are empty. @@ -401,6 +426,19 @@ void ProcessMinidump::ReadModuleList() { } } } + if (module_sp) { + // Watch out for place holder modules that have different paths, but the + // same UUID. If the base address is different, create a new module. If + // we don't then we will end up setting the load address of a different + // PlaceholderObjectFile and an assertion will fire. + auto *objfile = module_sp->GetObjectFile(); + if (objfile && objfile->GetPluginName() == + PlaceholderObjectFile::GetStaticPluginName()) { + if (((PlaceholderObjectFile *)objfile)->GetBaseImageAddress() != + load_addr) + module_sp.reset(); + } + } if (!module_sp) { // We failed to locate a matching local object file. Fortunately, the // minidump format encodes enough information about each module's memory @@ -415,12 +453,12 @@ void ProcessMinidump::ReadModuleList() { name); module_sp = Module::CreateModuleFromObjectFile<PlaceholderObjectFile>( - module_spec, module->BaseOfImage, module->SizeOfImage); + module_spec, load_addr, load_size); GetTarget().GetImages().Append(module_sp, true /* notify */); } bool load_addr_changed = false; - module_sp->SetLoadAddress(GetTarget(), module->BaseOfImage, false, + module_sp->SetLoadAddress(GetTarget(), load_addr, false, load_addr_changed); } } @@ -444,7 +482,7 @@ bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) { // debug information than needed. JITLoaderList &ProcessMinidump::GetJITLoaders() { if (!m_jit_loaders_up) { - m_jit_loaders_up = llvm::make_unique<JITLoaderList>(); + m_jit_loaders_up = std::make_unique<JITLoaderList>(); } return *m_jit_loaders_up; } diff --git a/source/Plugins/Process/minidump/ProcessMinidump.h b/source/Plugins/Process/minidump/ProcessMinidump.h index c39040f61dc5..22dc24af7c0e 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/source/Plugins/Process/minidump/ProcessMinidump.h @@ -108,7 +108,7 @@ private: FileSpec m_core_file; lldb::DataBufferSP m_core_data; llvm::ArrayRef<minidump::Thread> m_thread_list; - const MinidumpExceptionStream *m_active_exception; + const minidump::ExceptionStream *m_active_exception; lldb::CommandObjectSP m_command_sp; bool m_is_wow64; }; diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp index f2e456097dfc..72dead07dcb4 100644 --- a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp +++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp @@ -9,6 +9,7 @@ #include "RegisterContextMinidump_ARM.h" #include "Utility/ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/LLDBAssert.h" @@ -29,14 +30,14 @@ using namespace minidump; #define DEF_R(i) \ { \ "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \ - {dwarf_r##i, dwarf_r##i, INV, INV, reg_r##i}, \ + {ehframe_r##i, dwarf_r##i, INV, INV, reg_r##i}, \ nullptr, nullptr, nullptr, 0 \ } #define DEF_R_ARG(i, n) \ { \ "r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \ - {dwarf_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \ + {ehframe_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \ nullptr, nullptr, nullptr, 0 \ } @@ -173,7 +174,7 @@ static RegisterInfo g_reg_info_apple_fp = { OFFSET(r) + 7 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7}, + {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7}, nullptr, nullptr, nullptr, @@ -186,7 +187,7 @@ static RegisterInfo g_reg_info_fp = { OFFSET(r) + 11 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11}, + {ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11}, nullptr, nullptr, nullptr, @@ -213,7 +214,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(r) + 13 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, + {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp}, nullptr, nullptr, nullptr, @@ -224,7 +225,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(r) + 14 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, + {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr}, nullptr, nullptr, nullptr, @@ -235,7 +236,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(r) + 15 * 4, eEncodingUint, eFormatHex, - {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, + {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc}, nullptr, nullptr, nullptr, @@ -246,7 +247,7 @@ static RegisterInfo g_reg_infos[] = { OFFSET(cpsr), eEncodingUint, eFormatHex, - {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, + {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr}, nullptr, nullptr, nullptr, @@ -476,12 +477,22 @@ RegisterContextMinidump_ARM::RegisterContextMinidump_ARM( lldbassert(k_num_regs == k_num_reg_infos); } -size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; } +size_t RegisterContextMinidump_ARM::GetRegisterCountStatic() { + return k_num_regs; +} + +// Used for unit testing so we can verify register info is filled in for +// all register flavors (DWARF, EH Frame, generic, etc). +size_t RegisterContextMinidump_ARM::GetRegisterCount() { + return GetRegisterCountStatic(); +} +// Used for unit testing so we can verify register info is filled in. const RegisterInfo * -RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { +RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(size_t reg, + bool apple) { if (reg < k_num_reg_infos) { - if (m_apple) { + if (apple) { if (reg == reg_r7) return &g_reg_info_apple_fp; } else { @@ -493,6 +504,11 @@ RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { return nullptr; } +const RegisterInfo * +RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) { + return GetRegisterInfoAtIndexStatic(reg, m_apple); +} + size_t RegisterContextMinidump_ARM::GetRegisterSetCount() { return k_num_reg_sets; } diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h index eff8cdfef00a..7af3b98a6fe7 100644 --- a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h +++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h @@ -38,6 +38,12 @@ public: // Do nothing... registers are always valid... } + // Used for unit testing. + static size_t GetRegisterCountStatic(); + // Used for unit testing. + static const lldb_private::RegisterInfo * + GetRegisterInfoAtIndexStatic(size_t reg, bool apple); + size_t GetRegisterCount() override; const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp index 7b9598379553..3517f831970d 100644 --- a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp +++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp @@ -28,13 +28,13 @@ ScriptInterpreterNone::~ScriptInterpreterNone() {} bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command, CommandReturnObject *, const ExecuteScriptOptions &) { - m_debugger.GetErrorFile()->PutCString( + m_debugger.GetErrorStream().PutCString( "error: there is no embedded script interpreter in this mode.\n"); return false; } void ScriptInterpreterNone::ExecuteInterpreterLoop() { - m_debugger.GetErrorFile()->PutCString( + m_debugger.GetErrorStream().PutCString( "error: there is no embedded script interpreter in this mode.\n"); } diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 29dd037efd86..70d93424fdec 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -18,9 +18,11 @@ #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Errno.h" @@ -28,9 +30,41 @@ using namespace lldb_private; using namespace lldb; +using namespace lldb_private::python; +using llvm::cantFail; +using llvm::Error; +using llvm::Expected; +using llvm::Twine; -void StructuredPythonObject::Dump(Stream &s, bool pretty_print) const { - s << "Python Obj: 0x" << GetValue(); +template <> Expected<bool> python::As<bool>(Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + return obj.get().IsTrue(); +} + +template <> +Expected<long long> python::As<long long>(Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + return obj.get().AsLongLong(); +} + +template <> +Expected<std::string> python::As<std::string>(Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + PyObject *str_obj = PyObject_Str(obj.get().get()); + if (!obj) + return llvm::make_error<PythonException>(); + auto str = Take<PythonString>(str_obj); + auto utf8 = str.AsUTF8(); + if (!utf8) + return utf8.takeError(); + return utf8.get(); +} + +void StructuredPythonObject::Serialize(llvm::json::OStream &s) const { + s.value(llvm::formatv("Python Obj: {0:X}", GetValue()).str()); } // PythonObject @@ -167,12 +201,6 @@ PythonObject PythonObject::GetAttributeValue(llvm::StringRef attr) const { PyObject_GetAttr(m_py_obj, py_attr.get())); } -bool PythonObject::IsNone() const { return m_py_obj == Py_None; } - -bool PythonObject::IsValid() const { return m_py_obj != nullptr; } - -bool PythonObject::IsAllocated() const { return IsValid() && !IsNone(); } - StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { switch (GetObjectType()) { case PyObjectType::Dictionary: @@ -201,43 +229,19 @@ StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { } // PythonString -PythonBytes::PythonBytes() : PythonObject() {} -PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject() { - SetBytes(bytes); -} +PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) { SetBytes(bytes); } -PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject() { +PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) { SetBytes(llvm::ArrayRef<uint8_t>(bytes, length)); } -PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string -} - -PythonBytes::~PythonBytes() {} - bool PythonBytes::Check(PyObject *py_obj) { if (!py_obj) return false; return PyBytes_Check(py_obj); } -void PythonBytes::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonBytes::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - llvm::ArrayRef<uint8_t> PythonBytes::GetBytes() const { if (!IsValid()) return llvm::ArrayRef<uint8_t>(); @@ -257,8 +261,7 @@ size_t PythonBytes::GetSize() const { void PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes) { const char *data = reinterpret_cast<const char *>(bytes.data()); - PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); - PythonObject::Reset(PyRefType::Owned, py_bytes); + *this = Take<PythonBytes>(PyBytes_FromStringAndSize(data, bytes.size())); } StructuredData::StringSP PythonBytes::CreateStructuredString() const { @@ -275,39 +278,15 @@ PythonByteArray::PythonByteArray(llvm::ArrayRef<uint8_t> bytes) PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) { const char *str = reinterpret_cast<const char *>(bytes); - Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); -} - -PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) { - Reset(type, o); + *this = Take<PythonByteArray>(PyByteArray_FromStringAndSize(str, length)); } -PythonByteArray::PythonByteArray(const PythonBytes &object) - : PythonObject(object) {} - -PythonByteArray::~PythonByteArray() {} - bool PythonByteArray::Check(PyObject *py_obj) { if (!py_obj) return false; return PyByteArray_Check(py_obj); } -void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonByteArray::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - llvm::ArrayRef<uint8_t> PythonByteArray::GetBytes() const { if (!IsValid()) return llvm::ArrayRef<uint8_t>(); @@ -334,21 +313,18 @@ StructuredData::StringSP PythonByteArray::CreateStructuredString() const { // PythonString -PythonString::PythonString(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string -} - -PythonString::PythonString(llvm::StringRef string) : PythonObject() { - SetString(string); -} - -PythonString::PythonString(const char *string) : PythonObject() { - SetString(llvm::StringRef(string)); +Expected<PythonString> PythonString::FromUTF8(llvm::StringRef string) { +#if PY_MAJOR_VERSION >= 3 + PyObject *str = PyUnicode_FromStringAndSize(string.data(), string.size()); +#else + PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); +#endif + if (!str) + return llvm::make_error<PythonException>(); + return Take<PythonString>(str); } -PythonString::PythonString() : PythonObject() {} - -PythonString::~PythonString() {} +PythonString::PythonString(llvm::StringRef string) { SetString(string); } bool PythonString::Check(PyObject *py_obj) { if (!py_obj) @@ -363,30 +339,40 @@ bool PythonString::Check(PyObject *py_obj) { return false; } -void PythonString::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonString::Check(py_obj)) { - PythonObject::Reset(); - return; - } +void PythonString::Convert(PyRefType &type, PyObject *&py_obj) { #if PY_MAJOR_VERSION < 3 // In Python 2, Don't store PyUnicode objects directly, because we need // access to their underlying character buffers which Python 2 doesn't // provide. - if (PyUnicode_Check(py_obj)) - result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); + if (PyUnicode_Check(py_obj)) { + PyObject *s = PyUnicode_AsUTF8String(py_obj); + if (s == nullptr) { + PyErr_Clear(); + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + return; + } + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + else + type = PyRefType::Owned; + py_obj = s; + } #endif - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); } llvm::StringRef PythonString::GetString() const { + auto s = AsUTF8(); + if (!s) { + llvm::consumeError(s.takeError()); + return llvm::StringRef(""); + } + return s.get(); +} + +Expected<llvm::StringRef> PythonString::AsUTF8() const { if (!IsValid()) - return llvm::StringRef(); + return nullDeref(); Py_ssize_t size; const char *data; @@ -394,10 +380,16 @@ llvm::StringRef PythonString::GetString() const { #if PY_MAJOR_VERSION >= 3 data = PyUnicode_AsUTF8AndSize(m_py_obj, &size); #else - char *c; - PyString_AsStringAndSize(m_py_obj, &c, &size); + char *c = NULL; + int r = PyString_AsStringAndSize(m_py_obj, &c, &size); + if (r < 0) + c = NULL; data = c; #endif + + if (!data) + return exception(); + return llvm::StringRef(data, size); } @@ -413,13 +405,13 @@ size_t PythonString::GetSize() const { } void PythonString::SetString(llvm::StringRef string) { -#if PY_MAJOR_VERSION >= 3 - PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); - PythonObject::Reset(PyRefType::Owned, unicode); -#else - PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); - PythonObject::Reset(PyRefType::Owned, str); -#endif + auto s = FromUTF8(string); + if (!s) { + llvm::consumeError(s.takeError()); + Reset(); + } else { + *this = std::move(s.get()); + } } StructuredData::StringSP PythonString::CreateStructuredString() const { @@ -430,18 +422,7 @@ StructuredData::StringSP PythonString::CreateStructuredString() const { // PythonInteger -PythonInteger::PythonInteger() : PythonObject() {} - -PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) - : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type -} - -PythonInteger::PythonInteger(int64_t value) : PythonObject() { - SetInteger(value); -} - -PythonInteger::~PythonInteger() {} +PythonInteger::PythonInteger(int64_t value) { SetInteger(value); } bool PythonInteger::Check(PyObject *py_obj) { if (!py_obj) @@ -456,16 +437,7 @@ bool PythonInteger::Check(PyObject *py_obj) { #endif } -void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonInteger::Check(py_obj)) { - PythonObject::Reset(); - return; - } - +void PythonInteger::Convert(PyRefType &type, PyObject *&py_obj) { #if PY_MAJOR_VERSION < 3 // Always store this as a PyLong, which makes interoperability between Python // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x @@ -474,16 +446,23 @@ void PythonInteger::Reset(PyRefType type, PyObject *py_obj) { // Since we converted the original object to a different type, the new // object is an owned object regardless of the ownership semantics // requested by the user. - result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); + long long value = PyInt_AsLong(py_obj); + PyObject *l = nullptr; + if (!PyErr_Occurred()) + l = PyLong_FromLongLong(value); + if (l == nullptr) { + PyErr_Clear(); + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + return; + } + if (type == PyRefType::Owned) + Py_DECREF(py_obj); + else + type = PyRefType::Owned; + py_obj = l; } #endif - - assert(PyLong_Check(result.get()) && - "Couldn't get a PyLong from this PyObject"); - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); } int64_t PythonInteger::GetInteger() const { @@ -506,7 +485,7 @@ int64_t PythonInteger::GetInteger() const { } void PythonInteger::SetInteger(int64_t value) { - PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); + *this = Take<PythonInteger>(PyLong_FromLongLong(value)); } StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { @@ -517,11 +496,6 @@ StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { // PythonBoolean -PythonBoolean::PythonBoolean(PyRefType type, PyObject *py_obj) - : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a boolean type -} - PythonBoolean::PythonBoolean(bool value) { SetValue(value); } @@ -530,27 +504,12 @@ bool PythonBoolean::Check(PyObject *py_obj) { return py_obj ? PyBool_Check(py_obj) : false; } -void PythonBoolean::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonBoolean::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - bool PythonBoolean::GetValue() const { return m_py_obj ? PyObject_IsTrue(m_py_obj) : false; } void PythonBoolean::SetValue(bool value) { - PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); + *this = Take<PythonBoolean>(PyBool_FromLong(value)); } StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { @@ -561,42 +520,21 @@ StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { // PythonList -PythonList::PythonList(PyInitialValue value) : PythonObject() { +PythonList::PythonList(PyInitialValue value) { if (value == PyInitialValue::Empty) - Reset(PyRefType::Owned, PyList_New(0)); -} - -PythonList::PythonList(int list_size) : PythonObject() { - Reset(PyRefType::Owned, PyList_New(list_size)); + *this = Take<PythonList>(PyList_New(0)); } -PythonList::PythonList(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list +PythonList::PythonList(int list_size) { + *this = Take<PythonList>(PyList_New(list_size)); } -PythonList::~PythonList() {} - bool PythonList::Check(PyObject *py_obj) { if (!py_obj) return false; return PyList_Check(py_obj); } -void PythonList::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonList::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - uint32_t PythonList::GetSize() const { if (IsValid()) return PyList_GET_SIZE(m_py_obj); @@ -638,17 +576,13 @@ StructuredData::ArraySP PythonList::CreateStructuredArray() const { // PythonTuple -PythonTuple::PythonTuple(PyInitialValue value) : PythonObject() { +PythonTuple::PythonTuple(PyInitialValue value) { if (value == PyInitialValue::Empty) - Reset(PyRefType::Owned, PyTuple_New(0)); -} - -PythonTuple::PythonTuple(int tuple_size) : PythonObject() { - Reset(PyRefType::Owned, PyTuple_New(tuple_size)); + *this = Take<PythonTuple>(PyTuple_New(0)); } -PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple +PythonTuple::PythonTuple(int tuple_size) { + *this = Take<PythonTuple>(PyTuple_New(tuple_size)); } PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) { @@ -674,29 +608,12 @@ PythonTuple::PythonTuple(std::initializer_list<PyObject *> objects) { } } -PythonTuple::~PythonTuple() {} - bool PythonTuple::Check(PyObject *py_obj) { if (!py_obj) return false; return PyTuple_Check(py_obj); } -void PythonTuple::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonTuple::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - uint32_t PythonTuple::GetSize() const { if (IsValid()) return PyTuple_GET_SIZE(m_py_obj); @@ -730,18 +647,11 @@ StructuredData::ArraySP PythonTuple::CreateStructuredArray() const { // PythonDictionary -PythonDictionary::PythonDictionary(PyInitialValue value) : PythonObject() { +PythonDictionary::PythonDictionary(PyInitialValue value) { if (value == PyInitialValue::Empty) - Reset(PyRefType::Owned, PyDict_New()); + *this = Take<PythonDictionary>(PyDict_New()); } -PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) - : PythonObject() { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary -} - -PythonDictionary::~PythonDictionary() {} - bool PythonDictionary::Check(PyObject *py_obj) { if (!py_obj) return false; @@ -749,21 +659,6 @@ bool PythonDictionary::Check(PyObject *py_obj) { return PyDict_Check(py_obj); } -void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonDictionary::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - uint32_t PythonDictionary::GetSize() const { if (IsValid()) return PyDict_Size(m_py_obj); @@ -777,16 +672,66 @@ PythonList PythonDictionary::GetKeys() const { } PythonObject PythonDictionary::GetItemForKey(const PythonObject &key) const { - if (IsAllocated() && key.IsValid()) - return PythonObject(PyRefType::Borrowed, - PyDict_GetItem(m_py_obj, key.get())); - return PythonObject(); + auto item = GetItem(key); + if (!item) { + llvm::consumeError(item.takeError()); + return PythonObject(); + } + return std::move(item.get()); +} + +Expected<PythonObject> +PythonDictionary::GetItem(const PythonObject &key) const { + if (!IsValid()) + return nullDeref(); +#if PY_MAJOR_VERSION >= 3 + PyObject *o = PyDict_GetItemWithError(m_py_obj, key.get()); + if (PyErr_Occurred()) + return exception(); +#else + PyObject *o = PyDict_GetItem(m_py_obj, key.get()); +#endif + if (!o) + return keyError(); + return Retain<PythonObject>(o); +} + +Expected<PythonObject> PythonDictionary::GetItem(const Twine &key) const { + if (!IsValid()) + return nullDeref(); + PyObject *o = PyDict_GetItemString(m_py_obj, NullTerminated(key)); + if (PyErr_Occurred()) + return exception(); + if (!o) + return keyError(); + return Retain<PythonObject>(o); +} + +Error PythonDictionary::SetItem(const PythonObject &key, + const PythonObject &value) const { + if (!IsValid() || !value.IsValid()) + return nullDeref(); + int r = PyDict_SetItem(m_py_obj, key.get(), value.get()); + if (r < 0) + return exception(); + return Error::success(); +} + +Error PythonDictionary::SetItem(const Twine &key, + const PythonObject &value) const { + if (!IsValid() || !value.IsValid()) + return nullDeref(); + int r = PyDict_SetItemString(m_py_obj, NullTerminated(key), value.get()); + if (r < 0) + return exception(); + return Error::success(); } void PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) { - if (IsAllocated() && key.IsValid() && value.IsValid()) - PyDict_SetItem(m_py_obj, key.get(), value.get()); + Error error = SetItem(key, value); + if (error) + llvm::consumeError(std::move(error)); } StructuredData::DictionarySP @@ -803,14 +748,6 @@ PythonDictionary::CreateStructuredDictionary() const { return result; } -PythonModule::PythonModule() : PythonObject() {} - -PythonModule::PythonModule(PyRefType type, PyObject *py_obj) { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module -} - -PythonModule::~PythonModule() {} - PythonModule PythonModule::BuiltinsModule() { #if PY_MAJOR_VERSION >= 3 return AddModule("builtins"); @@ -826,9 +763,23 @@ PythonModule PythonModule::AddModule(llvm::StringRef module) { return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); } -PythonModule PythonModule::ImportModule(llvm::StringRef module) { - std::string str = module.str(); - return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); +Expected<PythonModule> PythonModule::Import(const Twine &name) { + PyObject *mod = PyImport_ImportModule(NullTerminated(name)); + if (!mod) + return exception(); + return Take<PythonModule>(mod); +} + +Expected<PythonObject> PythonModule::Get(const Twine &name) { + if (!IsValid()) + return nullDeref(); + PyObject *dict = PyModule_GetDict(m_py_obj); + if (!dict) + return exception(); + PyObject *item = PyDict_GetItemString(dict, NullTerminated(name)); + if (!item) + return exception(); + return Retain<PythonObject>(item); } bool PythonModule::Check(PyObject *py_obj) { @@ -838,33 +789,12 @@ bool PythonModule::Check(PyObject *py_obj) { return PyModule_Check(py_obj); } -void PythonModule::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonModule::Check(py_obj)) { - PythonObject::Reset(); - return; - } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); -} - PythonDictionary PythonModule::GetDictionary() const { - return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); -} - -PythonCallable::PythonCallable() : PythonObject() {} - -PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) { - Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable + if (!IsValid()) + return PythonDictionary(); + return Retain<PythonDictionary>(PyModule_GetDict(m_py_obj)); } -PythonCallable::~PythonCallable() {} - bool PythonCallable::Check(PyObject *py_obj) { if (!py_obj) return false; @@ -872,32 +802,80 @@ bool PythonCallable::Check(PyObject *py_obj) { return PyCallable_Check(py_obj); } -void PythonCallable::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonCallable::Check(py_obj)) { - PythonObject::Reset(); - return; +PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const { + auto arginfo = GetInitArgInfo(); + if (!arginfo) { + llvm::consumeError(arginfo.takeError()); + return ArgInfo{}; } - - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); + return arginfo.get(); } -PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { - ArgInfo result = {0, false, false, false}; +Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const { if (!IsValid()) - return result; + return nullDeref(); + auto init = As<PythonCallable>(GetAttribute("__init__")); + if (!init) + return init.takeError(); + return init.get().GetArgInfo(); +} + +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 +static const char get_arg_info_script[] = R"( +from inspect import signature, Parameter, ismethod +from collections import namedtuple +ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method']) +def main(f): + count = 0 + varargs = False + for parameter in signature(f).parameters.values(): + kind = parameter.kind + if kind in (Parameter.POSITIONAL_ONLY, + Parameter.POSITIONAL_OR_KEYWORD): + count += 1 + elif kind == Parameter.VAR_POSITIONAL: + varargs = True + elif kind in (Parameter.KEYWORD_ONLY, + Parameter.VAR_KEYWORD): + pass + else: + raise Exception(f'unknown parameter kind: {kind}') + return ArgInfo(count, varargs, ismethod(f)) +)"; +#endif + +Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const { + ArgInfo result = {}; + if (!IsValid()) + return nullDeref(); + +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 + + // no need to synchronize access to this global, we already have the GIL + static PythonScript get_arg_info(get_arg_info_script); + Expected<PythonObject> pyarginfo = get_arg_info(*this); + if (!pyarginfo) + return pyarginfo.takeError(); + result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count"))); + result.has_varargs = + cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs"))); + bool is_method = + cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method"))); + result.max_positional_args = + result.has_varargs ? ArgInfo::UNBOUNDED : result.count; + + // FIXME emulate old broken behavior + if (is_method) + result.count++; +#else + bool is_bound_method = false; PyObject *py_func_obj = m_py_obj; if (PyMethod_Check(py_func_obj)) { py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); PythonObject im_self = GetAttributeValue("im_self"); if (im_self.IsValid() && !im_self.IsNone()) - result.is_bound_method = true; + is_bound_method = true; } else { // see if this is a callable object with an __call__ method if (!PyFunction_Check(py_func_obj)) { @@ -906,9 +884,9 @@ PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { auto __callable__ = __call__.AsType<PythonCallable>(); if (__callable__.IsValid()) { py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); - PythonObject im_self = GetAttributeValue("im_self"); + PythonObject im_self = __callable__.GetAttributeValue("im_self"); if (im_self.IsValid() && !im_self.IsNone()) - result.is_bound_method = true; + is_bound_method = true; } } } @@ -923,10 +901,27 @@ PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { result.count = code->co_argcount; result.has_varargs = !!(code->co_flags & CO_VARARGS); - result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); + result.max_positional_args = result.has_varargs + ? ArgInfo::UNBOUNDED + : (result.count - (int)is_bound_method); + +#endif + return result; } +constexpr unsigned + PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17 + +PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { + auto arginfo = GetArgInfo(); + if (!arginfo) { + llvm::consumeError(arginfo.takeError()); + return ArgInfo{}; + } + return arginfo.get(); +} + PythonObject PythonCallable::operator()() { return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr)); } @@ -945,21 +940,9 @@ operator()(std::initializer_list<PythonObject> args) { PyObject_CallObject(m_py_obj, arg_tuple.get())); } -PythonFile::PythonFile() : PythonObject() {} - -PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } - -PythonFile::PythonFile(const char *path, const char *mode) { - lldb_private::File file; - FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode)); - Reset(file, mode); -} - -PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } - -PythonFile::~PythonFile() {} - bool PythonFile::Check(PyObject *py_obj) { + if (!py_obj) + return false; #if PY_MAJOR_VERSION < 3 return PyFile_Check(py_obj); #else @@ -967,86 +950,633 @@ bool PythonFile::Check(PyObject *py_obj) { // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper // over `io.open()`, which returns some object derived from `io.IOBase`. As a // result, the only way to detect a file in Python 3 is to check whether it - // inherits from `io.IOBase`. Since it is possible for non-files to also - // inherit from `io.IOBase`, we additionally verify that it has the `fileno` - // attribute, which should guarantee that it is backed by the file system. - PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); - PythonDictionary io_dict(PyRefType::Borrowed, - PyModule_GetDict(io_module.get())); - PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); - - PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); - - if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) + // inherits from `io.IOBase`. + auto io_module = PythonModule::Import("io"); + if (!io_module) { + llvm::consumeError(io_module.takeError()); return false; - if (!object_type.HasAttribute("fileno")) + } + auto iobase = io_module.get().Get("IOBase"); + if (!iobase) { + llvm::consumeError(iobase.takeError()); return false; - - return true; + } + int r = PyObject_IsInstance(py_obj, iobase.get().get()); + if (r < 0) { + llvm::consumeError(exception()); // clear the exception and log it. + return false; + } + return !!r; #endif } -void PythonFile::Reset(PyRefType type, PyObject *py_obj) { - // Grab the desired reference type so that if we end up rejecting `py_obj` it - // still gets decremented if necessary. - PythonObject result(type, py_obj); - - if (!PythonFile::Check(py_obj)) { - PythonObject::Reset(); - return; +namespace { +class GIL { +public: + GIL() { + m_state = PyGILState_Ensure(); + assert(!PyErr_Occurred()); } + ~GIL() { PyGILState_Release(m_state); } + +protected: + PyGILState_STATE m_state; +}; +} // namespace + +const char *PythonException::toCString() const { + if (!m_repr_bytes) + return "unknown exception"; + return PyBytes_AS_STRING(m_repr_bytes); +} + +PythonException::PythonException(const char *caller) { + assert(PyErr_Occurred()); + m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; + PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); + PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); + PyErr_Clear(); + if (m_exception) { + PyObject *repr = PyObject_Repr(m_exception); + if (repr) { + m_repr_bytes = PyUnicode_AsEncodedString(repr, "utf-8", nullptr); + if (!m_repr_bytes) { + PyErr_Clear(); + } + Py_XDECREF(repr); + } else { + PyErr_Clear(); + } + } + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT); + if (caller) + LLDB_LOGF(log, "%s failed with exception: %s", caller, toCString()); + else + LLDB_LOGF(log, "python exception: %s", toCString()); +} +void PythonException::Restore() { + if (m_exception_type && m_exception) { + PyErr_Restore(m_exception_type, m_exception, m_traceback); + } else { + PyErr_SetString(PyExc_Exception, toCString()); + } + m_exception_type = m_exception = m_traceback = NULL; +} - // Calling PythonObject::Reset(const PythonObject&) will lead to stack - // overflow since it calls back into the virtual implementation. - PythonObject::Reset(PyRefType::Borrowed, result.get()); +PythonException::~PythonException() { + Py_XDECREF(m_exception_type); + Py_XDECREF(m_exception); + Py_XDECREF(m_traceback); + Py_XDECREF(m_repr_bytes); } -void PythonFile::Reset(File &file, const char *mode) { - if (!file.IsValid()) { - Reset(); - return; +void PythonException::log(llvm::raw_ostream &OS) const { OS << toCString(); } + +std::error_code PythonException::convertToErrorCode() const { + return llvm::inconvertibleErrorCode(); +} + +bool PythonException::Matches(PyObject *exc) const { + return PyErr_GivenExceptionMatches(m_exception_type, exc); +} + +const char read_exception_script[] = R"( +import sys +from traceback import print_exception +if sys.version_info.major < 3: + from StringIO import StringIO +else: + from io import StringIO +def main(exc_type, exc_value, tb): + f = StringIO() + print_exception(exc_type, exc_value, tb, file=f) + return f.getvalue() +)"; + +std::string PythonException::ReadBacktrace() const { + + if (!m_traceback) + return toCString(); + + // no need to synchronize access to this global, we already have the GIL + static PythonScript read_exception(read_exception_script); + + Expected<std::string> backtrace = As<std::string>( + read_exception(m_exception_type, m_exception, m_traceback)); + + if (!backtrace) { + std::string message = + std::string(toCString()) + "\n" + + "Traceback unavailble, an error occurred while reading it:\n"; + return (message + llvm::toString(backtrace.takeError())); } - char *cmode = const_cast<char *>(mode); + return std::move(backtrace.get()); +} + +char PythonException::ID = 0; + +llvm::Expected<File::OpenOptions> +GetOptionsForPyObject(const PythonObject &obj) { #if PY_MAJOR_VERSION >= 3 - Reset(PyRefType::Owned, PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, - -1, nullptr, "ignore", nullptr, 0)); + auto options = File::OpenOptions(0); + auto readable = As<bool>(obj.CallMethod("readable")); + if (!readable) + return readable.takeError(); + auto writable = As<bool>(obj.CallMethod("writable")); + if (!writable) + return writable.takeError(); + if (readable.get()) + options |= File::eOpenOptionRead; + if (writable.get()) + options |= File::eOpenOptionWrite; + return options; #else - // Read through the Python source, doesn't seem to modify these strings - Reset(PyRefType::Owned, - PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, - nullptr)); + PythonString py_mode = obj.GetAttributeValue("mode").AsType<PythonString>(); + return File::GetOptionsFromMode(py_mode.GetString()); #endif } -uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) { - if (mode.empty()) - return 0; +// Base class template for python files. All it knows how to do +// is hold a reference to the python object and close or flush it +// when the File is closed. +namespace { +template <typename Base> class OwnedPythonFile : public Base { +public: + template <typename... Args> + OwnedPythonFile(const PythonFile &file, bool borrowed, Args... args) + : Base(args...), m_py_obj(file), m_borrowed(borrowed) { + assert(m_py_obj); + } + + ~OwnedPythonFile() override { + assert(m_py_obj); + GIL takeGIL; + Close(); + // we need to ensure the python object is released while we still + // hold the GIL + m_py_obj.Reset(); + } + + bool IsPythonSideValid() const { + GIL takeGIL; + auto closed = As<bool>(m_py_obj.GetAttribute("closed")); + if (!closed) { + llvm::consumeError(closed.takeError()); + return false; + } + return !closed.get(); + } + + bool IsValid() const override { + return IsPythonSideValid() && Base::IsValid(); + } + + Status Close() override { + assert(m_py_obj); + Status py_error, base_error; + GIL takeGIL; + if (!m_borrowed) { + auto r = m_py_obj.CallMethod("close"); + if (!r) + py_error = Status(r.takeError()); + } + base_error = Base::Close(); + if (py_error.Fail()) + return py_error; + return base_error; + }; + + PyObject *GetPythonObject() const { + assert(m_py_obj.IsValid()); + return m_py_obj.get(); + } + + static bool classof(const File *file) = delete; + +protected: + PythonFile m_py_obj; + bool m_borrowed; +}; +} // namespace + +// A SimplePythonFile is a OwnedPythonFile that just does all I/O as +// a NativeFile +namespace { +class SimplePythonFile : public OwnedPythonFile<NativeFile> { +public: + SimplePythonFile(const PythonFile &file, bool borrowed, int fd, + File::OpenOptions options) + : OwnedPythonFile(file, borrowed, fd, options, false) {} + + static char ID; + bool isA(const void *classID) const override { + return classID == &ID || NativeFile::isA(classID); + } + static bool classof(const File *file) { return file->isA(&ID); } +}; +char SimplePythonFile::ID = 0; +} // namespace + +#if PY_MAJOR_VERSION >= 3 + +namespace { +class PythonBuffer { +public: + PythonBuffer &operator=(const PythonBuffer &) = delete; + PythonBuffer(const PythonBuffer &) = delete; + + static Expected<PythonBuffer> Create(PythonObject &obj, + int flags = PyBUF_SIMPLE) { + Py_buffer py_buffer = {}; + PyObject_GetBuffer(obj.get(), &py_buffer, flags); + if (!py_buffer.obj) + return llvm::make_error<PythonException>(); + return PythonBuffer(py_buffer); + } + + PythonBuffer(PythonBuffer &&other) { + m_buffer = other.m_buffer; + other.m_buffer.obj = nullptr; + } - return llvm::StringSwitch<uint32_t>(mode.str()) - .Case("r", File::eOpenOptionRead) - .Case("w", File::eOpenOptionWrite) - .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend | - File::eOpenOptionCanCreate) - .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite) - .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite | - File::eOpenOptionCanCreate | File::eOpenOptionTruncate) - .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite | - File::eOpenOptionAppend | File::eOpenOptionCanCreate) - .Default(0); + ~PythonBuffer() { + if (m_buffer.obj) + PyBuffer_Release(&m_buffer); + } + + Py_buffer &get() { return m_buffer; } + +private: + // takes ownership of the buffer. + PythonBuffer(const Py_buffer &py_buffer) : m_buffer(py_buffer) {} + Py_buffer m_buffer; +}; +} // namespace + +// Shared methods between TextPythonFile and BinaryPythonFile +namespace { +class PythonIOFile : public OwnedPythonFile<File> { +public: + PythonIOFile(const PythonFile &file, bool borrowed) + : OwnedPythonFile(file, borrowed) {} + + ~PythonIOFile() override { Close(); } + + bool IsValid() const override { return IsPythonSideValid(); } + + Status Close() override { + assert(m_py_obj); + GIL takeGIL; + if (m_borrowed) + return Flush(); + auto r = m_py_obj.CallMethod("close"); + if (!r) + return Status(r.takeError()); + return Status(); + } + + Status Flush() override { + GIL takeGIL; + auto r = m_py_obj.CallMethod("flush"); + if (!r) + return Status(r.takeError()); + return Status(); + } + + Expected<File::OpenOptions> GetOptions() const override { + GIL takeGIL; + return GetOptionsForPyObject(m_py_obj); + } + + static char ID; + bool isA(const void *classID) const override { + return classID == &ID || File::isA(classID); + } + static bool classof(const File *file) { return file->isA(&ID); } +}; +char PythonIOFile::ID = 0; +} // namespace + +namespace { +class BinaryPythonFile : public PythonIOFile { +protected: + int m_descriptor; + +public: + BinaryPythonFile(int fd, const PythonFile &file, bool borrowed) + : PythonIOFile(file, borrowed), + m_descriptor(File::DescriptorIsValid(fd) ? fd + : File::kInvalidDescriptor) {} + + int GetDescriptor() const override { return m_descriptor; } + + Status Write(const void *buf, size_t &num_bytes) override { + GIL takeGIL; + PyObject *pybuffer_p = PyMemoryView_FromMemory( + const_cast<char *>((const char *)buf), num_bytes, PyBUF_READ); + if (!pybuffer_p) + return Status(llvm::make_error<PythonException>()); + auto pybuffer = Take<PythonObject>(pybuffer_p); + num_bytes = 0; + auto bytes_written = As<long long>(m_py_obj.CallMethod("write", pybuffer)); + if (!bytes_written) + return Status(bytes_written.takeError()); + if (bytes_written.get() < 0) + return Status(".write() method returned a negative number!"); + static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); + num_bytes = bytes_written.get(); + return Status(); + } + + Status Read(void *buf, size_t &num_bytes) override { + GIL takeGIL; + static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); + auto pybuffer_obj = + m_py_obj.CallMethod("read", (unsigned long long)num_bytes); + if (!pybuffer_obj) + return Status(pybuffer_obj.takeError()); + num_bytes = 0; + if (pybuffer_obj.get().IsNone()) { + // EOF + num_bytes = 0; + return Status(); + } + auto pybuffer = PythonBuffer::Create(pybuffer_obj.get()); + if (!pybuffer) + return Status(pybuffer.takeError()); + memcpy(buf, pybuffer.get().get().buf, pybuffer.get().get().len); + num_bytes = pybuffer.get().get().len; + return Status(); + } +}; +} // namespace + +namespace { +class TextPythonFile : public PythonIOFile { +protected: + int m_descriptor; + +public: + TextPythonFile(int fd, const PythonFile &file, bool borrowed) + : PythonIOFile(file, borrowed), + m_descriptor(File::DescriptorIsValid(fd) ? fd + : File::kInvalidDescriptor) {} + + int GetDescriptor() const override { return m_descriptor; } + + Status Write(const void *buf, size_t &num_bytes) override { + GIL takeGIL; + auto pystring = + PythonString::FromUTF8(llvm::StringRef((const char *)buf, num_bytes)); + if (!pystring) + return Status(pystring.takeError()); + num_bytes = 0; + auto bytes_written = + As<long long>(m_py_obj.CallMethod("write", pystring.get())); + if (!bytes_written) + return Status(bytes_written.takeError()); + if (bytes_written.get() < 0) + return Status(".write() method returned a negative number!"); + static_assert(sizeof(long long) >= sizeof(size_t), "overflow"); + num_bytes = bytes_written.get(); + return Status(); + } + + Status Read(void *buf, size_t &num_bytes) override { + GIL takeGIL; + size_t num_chars = num_bytes / 6; + size_t orig_num_bytes = num_bytes; + num_bytes = 0; + if (orig_num_bytes < 6) { + return Status("can't read less than 6 bytes from a utf8 text stream"); + } + auto pystring = As<PythonString>( + m_py_obj.CallMethod("read", (unsigned long long)num_chars)); + if (!pystring) + return Status(pystring.takeError()); + if (pystring.get().IsNone()) { + // EOF + return Status(); + } + auto stringref = pystring.get().AsUTF8(); + if (!stringref) + return Status(stringref.takeError()); + num_bytes = stringref.get().size(); + memcpy(buf, stringref.get().begin(), num_bytes); + return Status(); + } +}; +} // namespace + +#endif + +llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) { + if (!IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid PythonFile"); + + int fd = PyObject_AsFileDescriptor(m_py_obj); + if (fd < 0) { + PyErr_Clear(); + return ConvertToFileForcingUseOfScriptingIOMethods(borrowed); + } + auto options = GetOptionsForPyObject(*this); + if (!options) + return options.takeError(); + + // LLDB and python will not share I/O buffers. We should probably + // flush the python buffers now. + auto r = CallMethod("flush"); + if (!r) + return r.takeError(); + + FileSP file_sp; + if (borrowed) { + // In this case we we don't need to retain the python + // object at all. + file_sp = std::make_shared<NativeFile>(fd, options.get(), false); + } else { + file_sp = std::static_pointer_cast<File>( + std::make_shared<SimplePythonFile>(*this, borrowed, fd, options.get())); + } + if (!file_sp->IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid File"); + + return file_sp; } -bool PythonFile::GetUnderlyingFile(File &file) const { +llvm::Expected<FileSP> +PythonFile::ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed) { + + assert(!PyErr_Occurred()); + if (!IsValid()) - return false; + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid PythonFile"); + +#if PY_MAJOR_VERSION < 3 + + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "not supported on python 2"); + +#else + + int fd = PyObject_AsFileDescriptor(m_py_obj); + if (fd < 0) { + PyErr_Clear(); + fd = File::kInvalidDescriptor; + } + + auto io_module = PythonModule::Import("io"); + if (!io_module) + return io_module.takeError(); + auto textIOBase = io_module.get().Get("TextIOBase"); + if (!textIOBase) + return textIOBase.takeError(); + auto rawIOBase = io_module.get().Get("RawIOBase"); + if (!rawIOBase) + return rawIOBase.takeError(); + auto bufferedIOBase = io_module.get().Get("BufferedIOBase"); + if (!bufferedIOBase) + return bufferedIOBase.takeError(); + + FileSP file_sp; + + auto isTextIO = IsInstance(textIOBase.get()); + if (!isTextIO) + return isTextIO.takeError(); + if (isTextIO.get()) + file_sp = std::static_pointer_cast<File>( + std::make_shared<TextPythonFile>(fd, *this, borrowed)); + + auto isRawIO = IsInstance(rawIOBase.get()); + if (!isRawIO) + return isRawIO.takeError(); + auto isBufferedIO = IsInstance(bufferedIOBase.get()); + if (!isBufferedIO) + return isBufferedIO.takeError(); + + if (isRawIO.get() || isBufferedIO.get()) { + file_sp = std::static_pointer_cast<File>( + std::make_shared<BinaryPythonFile>(fd, *this, borrowed)); + } + + if (!file_sp) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "python file is neither text nor binary"); + + if (!file_sp->IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid File"); + + return file_sp; + +#endif +} + +Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) { + if (!file.IsValid()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid file"); + + if (auto *simple = llvm::dyn_cast<SimplePythonFile>(&file)) + return Retain<PythonFile>(simple->GetPythonObject()); +#if PY_MAJOR_VERSION >= 3 + if (auto *pythonio = llvm::dyn_cast<PythonIOFile>(&file)) + return Retain<PythonFile>(pythonio->GetPythonObject()); +#endif + + if (!mode) { + auto m = file.GetOpenMode(); + if (!m) + return m.takeError(); + mode = m.get(); + } + + PyObject *file_obj; +#if PY_MAJOR_VERSION >= 3 + file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr, + "ignore", nullptr, 0); +#else + // Read through the Python source, doesn't seem to modify these strings + char *cmode = const_cast<char *>(mode); + // We pass ::flush instead of ::fclose here so we borrow the FILE* -- + // the lldb_private::File still owns it. + file_obj = + PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush); +#endif + + if (!file_obj) + return exception(); + + return Take<PythonFile>(file_obj); +} + +Error PythonScript::Init() { + if (function.IsValid()) + return Error::success(); + + PythonDictionary globals(PyInitialValue::Empty); + auto builtins = PythonModule::BuiltinsModule(); + if (Error error = globals.SetItem("__builtins__", builtins)) + return error; + PyObject *o = + PyRun_String(script, Py_file_input, globals.get(), globals.get()); + if (!o) + return exception(); + Take<PythonObject>(o); + auto f = As<PythonCallable>(globals.GetItem("main")); + if (!f) + return f.takeError(); + function = std::move(f.get()); + + return Error::success(); +} + +llvm::Expected<PythonObject> +python::runStringOneLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals) { + if (!globals.IsValid() || !locals.IsValid()) + return nullDeref(); + + PyObject *code = + Py_CompileString(NullTerminated(string), "<string>", Py_eval_input); + if (!code) { + PyErr_Clear(); + code = + Py_CompileString(NullTerminated(string), "<string>", Py_single_input); + } + if (!code) + return exception(); + auto code_ref = Take<PythonObject>(code); + +#if PY_MAJOR_VERSION < 3 + PyObject *result = + PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get()); +#else + PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); +#endif + + if (!result) + return exception(); + + return Take<PythonObject>(result); +} - file.Close(); - // We don't own the file descriptor returned by this function, make sure the - // File object knows about that. - file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); - PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); - file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); - return file.IsValid(); +llvm::Expected<PythonObject> +python::runStringMultiLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals) { + if (!globals.IsValid() || !locals.IsValid()) + return nullDeref(); + PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, + globals.get(), locals.get()); + if (!result) + return exception(); + return Take<PythonObject>(result); } #endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 049ce90bb1b1..373d3212697d 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -6,6 +6,45 @@ // //===----------------------------------------------------------------------===// +// +// !! FIXME FIXME FIXME !! +// +// Python APIs nearly all can return an exception. They do this +// by returning NULL, or -1, or some such value and setting +// the exception state with PyErr_Set*(). Exceptions must be +// handled before further python API functions are called. Failure +// to do so will result in asserts on debug builds of python. +// It will also sometimes, but not usually result in crashes of +// release builds. +// +// Nearly all the code in this header does not handle python exceptions +// correctly. It should all be converted to return Expected<> or +// Error types to capture the exception. +// +// Everything in this file except functions that return Error or +// Expected<> is considered deprecated and should not be +// used in new code. If you need to use it, fix it first. +// +// +// TODOs for this file +// +// * Make all methods safe for exceptions. +// +// * Eliminate method signatures that must translate exceptions into +// empty objects or NULLs. Almost everything here should return +// Expected<>. It should be acceptable for certain operations that +// can never fail to assert instead, such as the creation of +// PythonString from a string literal. +// +// * Elimintate Reset(), and make all non-default constructors private. +// Python objects should be created with Retain<> or Take<>, and they +// should be assigned with operator= +// +// * Eliminate default constructors, make python objects always +// nonnull, and use optionals where necessary. +// + + #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H @@ -20,12 +59,15 @@ #include "llvm/ADT/ArrayRef.h" namespace lldb_private { +namespace python { +class PythonObject; class PythonBytes; class PythonString; class PythonList; class PythonDictionary; class PythonInteger; +class PythonException; class StructuredPythonObject : public StructuredData::Generic { public: @@ -43,7 +85,7 @@ public: bool IsValid() const override { return GetValue() && GetValue() != Py_None; } - void Dump(Stream &s, bool pretty_print = true) const override; + void Serialize(llvm::json::OStream &s) const override; private: DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); @@ -72,61 +114,137 @@ enum class PyRefType { // not call Py_INCREF. }; -enum class PyInitialValue { Invalid, Empty }; -class PythonObject { -public: - PythonObject() : m_py_obj(nullptr) {} +// Take a reference that you already own, and turn it into +// a PythonObject. +// +// Most python API methods will return a +1 reference +// if they succeed or NULL if and only if +// they set an exception. Use this to collect such return +// values, after checking for NULL. +// +// If T is not just PythonObject, then obj must be already be +// checked to be of the correct type. +template <typename T> T Take(PyObject *obj) { + assert(obj); + assert(!PyErr_Occurred()); + T thing(PyRefType::Owned, obj); + assert(thing.IsValid()); + return std::move(thing); +} + +// Retain a reference you have borrowed, and turn it into +// a PythonObject. +// +// A minority of python APIs return a borrowed reference +// instead of a +1. They will also return NULL if and only +// if they set an exception. Use this to collect such return +// values, after checking for NULL. +// +// If T is not just PythonObject, then obj must be already be +// checked to be of the correct type. +template <typename T> T Retain(PyObject *obj) { + assert(obj); + assert(!PyErr_Occurred()); + T thing(PyRefType::Borrowed, obj); + assert(thing.IsValid()); + return std::move(thing); +} + +// This class can be used like a utility function to convert from +// a llvm-friendly Twine into a null-terminated const char *, +// which is the form python C APIs want their strings in. +// +// Example: +// const llvm::Twine &some_twine; +// PyFoo_Bar(x, y, z, NullTerminated(some_twine)); +// +// Why a class instead of a function? If the twine isn't already null +// terminated, it will need a temporary buffer to copy the string +// into. We need that buffer to stick around for the lifetime of the +// statement. +class NullTerminated { + const char *str; + llvm::SmallString<32> storage; - PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) { - Reset(type, py_obj); +public: + NullTerminated(const llvm::Twine &twine) { + llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); + str = ref.begin(); } + operator const char *() { return str; } +}; - PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); } +inline llvm::Error nullDeref() { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "A NULL PyObject* was dereferenced"); +} - virtual ~PythonObject() { Reset(); } +inline llvm::Error exception(const char *s = nullptr) { + return llvm::make_error<PythonException>(s); +} - void Reset() { - // Avoid calling the virtual method since it's not necessary - // to actually validate the type of the PyObject if we're - // just setting to null. - if (Py_IsInitialized()) - Py_XDECREF(m_py_obj); - m_py_obj = nullptr; - } +inline llvm::Error keyError() { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "key not in dict"); +} - void Reset(const PythonObject &rhs) { - // Avoid calling the virtual method if it's not necessary - // to actually validate the type of the PyObject. - if (!rhs.IsValid()) - Reset(); - else - Reset(PyRefType::Borrowed, rhs.m_py_obj); - } +enum class PyInitialValue { Invalid, Empty }; - // PythonObject is implicitly convertible to PyObject *, which will call the - // wrong overload. We want to explicitly disallow this, since a PyObject - // *always* owns its reference. Therefore the overload which takes a - // PyRefType doesn't make sense, and the copy constructor should be used. - void Reset(PyRefType type, const PythonObject &ref) = delete; +template <typename T, typename Enable = void> struct PythonFormat; - virtual void Reset(PyRefType type, PyObject *py_obj) { - if (py_obj == m_py_obj) - return; +template <> struct PythonFormat<unsigned long long> { + static constexpr char format = 'K'; + static auto get(unsigned long long value) { return value; } +}; - if (Py_IsInitialized()) - Py_XDECREF(m_py_obj); +template <> struct PythonFormat<long long> { + static constexpr char format = 'L'; + static auto get(long long value) { return value; } +}; - m_py_obj = py_obj; +template <> struct PythonFormat<PyObject *> { + static constexpr char format = 'O'; + static auto get(PyObject *value) { return value; } +}; + +template <typename T> +struct PythonFormat< + T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { + static constexpr char format = 'O'; + static auto get(const T &value) { return value.get(); } +}; + +class PythonObject { +public: + PythonObject() : m_py_obj(nullptr) {} + PythonObject(PyRefType type, PyObject *py_obj) { + m_py_obj = py_obj; // If this is a borrowed reference, we need to convert it to // an owned reference by incrementing it. If it is an owned // reference (for example the caller allocated it with PyDict_New() // then we must *not* increment it. - if (Py_IsInitialized() && type == PyRefType::Borrowed) + if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) Py_XINCREF(m_py_obj); } + PythonObject(const PythonObject &rhs) + : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} + + PythonObject(PythonObject &&rhs) { + m_py_obj = rhs.m_py_obj; + rhs.m_py_obj = nullptr; + } + + ~PythonObject() { Reset(); } + + void Reset() { + if (m_py_obj && Py_IsInitialized()) + Py_DECREF(m_py_obj); + m_py_obj = nullptr; + } + void Dump() const { if (m_py_obj) _PyObject_Dump(m_py_obj); @@ -144,8 +262,9 @@ public: return result; } - PythonObject &operator=(const PythonObject &other) { - Reset(PyRefType::Borrowed, other.get()); + PythonObject &operator=(PythonObject other) { + Reset(); + m_py_obj = std::exchange(other.m_py_obj, nullptr); return *this; } @@ -174,11 +293,13 @@ public: PythonObject GetAttributeValue(llvm::StringRef attribute) const; - bool IsValid() const; + bool IsNone() const { return m_py_obj == Py_None; } + + bool IsValid() const { return m_py_obj != nullptr; } - bool IsAllocated() const; + bool IsAllocated() const { return IsValid() && !IsNone(); } - bool IsNone() const; + explicit operator bool() const { return IsValid() && !IsNone(); } template <typename T> T AsType() const { if (!T::Check(m_py_obj)) @@ -189,24 +310,125 @@ public: StructuredData::ObjectSP CreateStructuredObject() const; protected: + +#if PY_MAJOR_VERSION < 3 + // The python 2 API declares some arguments as char* that should + // be const char *, but it doesn't actually modify them. + static char *py2_const_cast(const char *s) { return const_cast<char *>(s); } +#else + static const char *py2_const_cast(const char *s) { return s; } +#endif + +public: + template <typename... T> + llvm::Expected<PythonObject> CallMethod(const char *name, + const T &... t) const { + const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; + PyObject *obj = + PyObject_CallMethod(m_py_obj, py2_const_cast(name), + py2_const_cast(format), PythonFormat<T>::get(t)...); + if (!obj) + return exception(); + return python::Take<PythonObject>(obj); + } + + template <typename... T> + llvm::Expected<PythonObject> Call(const T &... t) const { + const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; + PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), + PythonFormat<T>::get(t)...); + if (!obj) + return exception(); + return python::Take<PythonObject>(obj); + } + + llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { + if (!m_py_obj) + return nullDeref(); + PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); + if (!obj) + return exception(); + return python::Take<PythonObject>(obj); + } + + llvm::Expected<bool> IsTrue() { + if (!m_py_obj) + return nullDeref(); + int r = PyObject_IsTrue(m_py_obj); + if (r < 0) + return exception(); + return !!r; + } + + llvm::Expected<long long> AsLongLong() { + if (!m_py_obj) + return nullDeref(); + assert(!PyErr_Occurred()); + long long r = PyLong_AsLongLong(m_py_obj); + if (PyErr_Occurred()) + return exception(); + return r; + } + + llvm::Expected<bool> IsInstance(const PythonObject &cls) { + if (!m_py_obj || !cls.IsValid()) + return nullDeref(); + int r = PyObject_IsInstance(m_py_obj, cls.get()); + if (r < 0) + return exception(); + return !!r; + } + +protected: PyObject *m_py_obj; }; -class PythonBytes : public PythonObject { + +// This is why C++ needs monads. +template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { + if (!obj) + return obj.takeError(); + if (!T::Check(obj.get().get())) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "type error"); + return T(PyRefType::Borrowed, std::move(obj.get().get())); +} + +template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); + +template <> +llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); + +template <> +llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); + + +template <class T> class TypedPythonObject : public PythonObject { public: - PythonBytes(); - explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); - PythonBytes(const uint8_t *bytes, size_t length); - PythonBytes(PyRefType type, PyObject *o); + // override to perform implicit type conversions on Reset + // This can be eliminated once we drop python 2 support. + static void Convert(PyRefType &type, PyObject *&py_obj) {} - ~PythonBytes() override; + TypedPythonObject(PyRefType type, PyObject *py_obj) { + if (!py_obj) + return; + T::Convert(type, py_obj); + if (T::Check(py_obj)) + PythonObject::operator=(PythonObject(type, py_obj)); + else if (type == PyRefType::Owned) + Py_DECREF(py_obj); + } - static bool Check(PyObject *py_obj); + TypedPythonObject() {} +}; - // Bring in the no-argument base class version - using PythonObject::Reset; +class PythonBytes : public TypedPythonObject<PythonBytes> { +public: + using TypedPythonObject::TypedPythonObject; + explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); + PythonBytes(const uint8_t *bytes, size_t length); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); llvm::ArrayRef<uint8_t> GetBytes() const; @@ -217,23 +439,15 @@ public: StructuredData::StringSP CreateStructuredString() const; }; -class PythonByteArray : public PythonObject { +class PythonByteArray : public TypedPythonObject<PythonByteArray> { public: - PythonByteArray(); + using TypedPythonObject::TypedPythonObject; explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); PythonByteArray(const uint8_t *bytes, size_t length); - PythonByteArray(PyRefType type, PyObject *o); PythonByteArray(const PythonBytes &object); - ~PythonByteArray() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - llvm::ArrayRef<uint8_t> GetBytes() const; size_t GetSize() const; @@ -243,45 +457,39 @@ public: StructuredData::StringSP CreateStructuredString() const; }; -class PythonString : public PythonObject { +class PythonString : public TypedPythonObject<PythonString> { public: - PythonString(); - explicit PythonString(llvm::StringRef string); - explicit PythonString(const char *string); - PythonString(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; + static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); - ~PythonString() override; + PythonString() : TypedPythonObject() {} // MSVC requires this for some reason - static bool Check(PyObject *py_obj); + explicit PythonString(llvm::StringRef string); // safe, null on error - // Bring in the no-argument base class version - using PythonObject::Reset; + static bool Check(PyObject *py_obj); + static void Convert(PyRefType &type, PyObject *&py_obj); - void Reset(PyRefType type, PyObject *py_obj) override; + llvm::StringRef GetString() const; // safe, empty string on error - llvm::StringRef GetString() const; + llvm::Expected<llvm::StringRef> AsUTF8() const; size_t GetSize() const; - void SetString(llvm::StringRef string); + void SetString(llvm::StringRef string); // safe, null on error StructuredData::StringSP CreateStructuredString() const; }; -class PythonInteger : public PythonObject { +class PythonInteger : public TypedPythonObject<PythonInteger> { public: - PythonInteger(); - explicit PythonInteger(int64_t value); - PythonInteger(PyRefType type, PyObject *o); - - ~PythonInteger() override; + using TypedPythonObject::TypedPythonObject; - static bool Check(PyObject *py_obj); + PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason - // Bring in the no-argument base class version - using PythonObject::Reset; + explicit PythonInteger(int64_t value); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); + static void Convert(PyRefType &type, PyObject *&py_obj); int64_t GetInteger() const; @@ -290,21 +498,14 @@ public: StructuredData::IntegerSP CreateStructuredInteger() const; }; -class PythonBoolean : public PythonObject { +class PythonBoolean : public TypedPythonObject<PythonBoolean> { public: - PythonBoolean() = default; - explicit PythonBoolean(bool value); - PythonBoolean(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonBoolean() override = default; + explicit PythonBoolean(bool value); static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - bool GetValue() const; void SetValue(bool value); @@ -312,22 +513,17 @@ public: StructuredData::BooleanSP CreateStructuredBoolean() const; }; -class PythonList : public PythonObject { +class PythonList : public TypedPythonObject<PythonList> { public: - PythonList() {} + using TypedPythonObject::TypedPythonObject; + + PythonList() : TypedPythonObject() {} // MSVC requires this for some reason + explicit PythonList(PyInitialValue value); explicit PythonList(int list_size); - PythonList(PyRefType type, PyObject *o); - - ~PythonList() override; static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - uint32_t GetSize() const; PythonObject GetItemAtIndex(uint32_t index) const; @@ -339,24 +535,17 @@ public: StructuredData::ArraySP CreateStructuredArray() const; }; -class PythonTuple : public PythonObject { +class PythonTuple : public TypedPythonObject<PythonTuple> { public: - PythonTuple() {} + using TypedPythonObject::TypedPythonObject; + explicit PythonTuple(PyInitialValue value); explicit PythonTuple(int tuple_size); - PythonTuple(PyRefType type, PyObject *o); PythonTuple(std::initializer_list<PythonObject> objects); PythonTuple(std::initializer_list<PyObject *> objects); - ~PythonTuple() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; - - void Reset(PyRefType type, PyObject *py_obj) override; - uint32_t GetSize() const; PythonObject GetItemAtIndex(uint32_t index) const; @@ -366,37 +555,35 @@ public: StructuredData::ArraySP CreateStructuredArray() const; }; -class PythonDictionary : public PythonObject { +class PythonDictionary : public TypedPythonObject<PythonDictionary> { public: - PythonDictionary() {} - explicit PythonDictionary(PyInitialValue value); - PythonDictionary(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonDictionary() override; - - static bool Check(PyObject *py_obj); + PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason - // Bring in the no-argument base class version - using PythonObject::Reset; + explicit PythonDictionary(PyInitialValue value); - void Reset(PyRefType type, PyObject *py_obj) override; + static bool Check(PyObject *py_obj); uint32_t GetSize() const; PythonList GetKeys() const; - PythonObject GetItemForKey(const PythonObject &key) const; - void SetItemForKey(const PythonObject &key, const PythonObject &value); + PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED + void SetItemForKey(const PythonObject &key, + const PythonObject &value); // DEPRECATED + + llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; + llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; + llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; + llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; StructuredData::DictionarySP CreateStructuredDictionary() const; }; -class PythonModule : public PythonObject { +class PythonModule : public TypedPythonObject<PythonModule> { public: - PythonModule(); - PythonModule(PyRefType type, PyObject *o); - - ~PythonModule() override; + using TypedPythonObject::TypedPythonObject; static bool Check(PyObject *py_obj); @@ -406,38 +593,57 @@ public: static PythonModule AddModule(llvm::StringRef module); - static PythonModule ImportModule(llvm::StringRef module); + // safe, returns invalid on error; + static PythonModule ImportModule(llvm::StringRef name) { + std::string s = name; + auto mod = Import(s.c_str()); + if (!mod) { + llvm::consumeError(mod.takeError()); + return PythonModule(); + } + return std::move(mod.get()); + } - // Bring in the no-argument base class version - using PythonObject::Reset; + static llvm::Expected<PythonModule> Import(const llvm::Twine &name); - void Reset(PyRefType type, PyObject *py_obj) override; + llvm::Expected<PythonObject> Get(const llvm::Twine &name); PythonDictionary GetDictionary() const; }; -class PythonCallable : public PythonObject { +class PythonCallable : public TypedPythonObject<PythonCallable> { public: + using TypedPythonObject::TypedPythonObject; + struct ArgInfo { - size_t count; - bool is_bound_method : 1; - bool has_varargs : 1; - bool has_kwargs : 1; + /* the largest number of positional arguments this callable + * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs + * function and can accept an arbitrary number */ + unsigned max_positional_args; + static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline + /* the number of positional arguments, including optional ones, + * and excluding varargs. If this is a bound method, then the + * count will still include a +1 for self. + * + * FIXME. That's crazy. This should be replaced with + * an accurate min and max for positional args. + */ + int count; + /* does the callable have positional varargs? */ + bool has_varargs : 1; // FIXME delete this }; - PythonCallable(); - PythonCallable(PyRefType type, PyObject *o); - - ~PythonCallable() override; - static bool Check(PyObject *py_obj); - // Bring in the no-argument base class version - using PythonObject::Reset; + llvm::Expected<ArgInfo> GetArgInfo() const; - void Reset(PyRefType type, PyObject *py_obj) override; + llvm::Expected<ArgInfo> GetInitArgInfo() const; - ArgInfo GetNumArguments() const; + ArgInfo GetNumArguments() const; // DEPRECATED + + // If the callable is a Py_Class, then find the number of arguments + // of the __init__ method. + ArgInfo GetNumInitArguments() const; // DEPRECATED PythonObject operator()(); @@ -451,27 +657,123 @@ public: } }; -class PythonFile : public PythonObject { +class PythonFile : public TypedPythonObject<PythonFile> { public: - PythonFile(); - PythonFile(File &file, const char *mode); - PythonFile(const char *path, const char *mode); - PythonFile(PyRefType type, PyObject *o); + using TypedPythonObject::TypedPythonObject; - ~PythonFile() override; + PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason static bool Check(PyObject *py_obj); - using PythonObject::Reset; + static llvm::Expected<PythonFile> FromFile(File &file, + const char *mode = nullptr); - void Reset(PyRefType type, PyObject *py_obj) override; - void Reset(File &file, const char *mode); + llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); + llvm::Expected<lldb::FileSP> + ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); +}; - static uint32_t GetOptionsFromMode(llvm::StringRef mode); +class PythonException : public llvm::ErrorInfo<PythonException> { +private: + PyObject *m_exception_type, *m_exception, *m_traceback; + PyObject *m_repr_bytes; - bool GetUnderlyingFile(File &file) const; +public: + static char ID; + const char *toCString() const; + PythonException(const char *caller = nullptr); + void Restore(); + ~PythonException(); + void log(llvm::raw_ostream &OS) const override; + std::error_code convertToErrorCode() const override; + bool Matches(PyObject *exc) const; + std::string ReadBacktrace() const; +}; + +// This extracts the underlying T out of an Expected<T> and returns it. +// If the Expected is an Error instead of a T, that error will be converted +// into a python exception, and this will return a default-constructed T. +// +// This is appropriate for use right at the boundary of python calling into +// C++, such as in a SWIG typemap. In such a context you should simply +// check if the returned T is valid, and if it is, return a NULL back +// to python. This will result in the Error being raised as an exception +// from python code's point of view. +// +// For example: +// ``` +// Expected<Foo *> efoop = some_cpp_function(); +// Foo *foop = unwrapOrSetPythonException(efoop); +// if (!foop) +// return NULL; +// do_something(*foop); +// +// If the Error returned was itself created because a python exception was +// raised when C++ code called into python, then the original exception +// will be restored. Otherwise a simple string exception will be raised. +template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { + if (expected) + return expected.get(); + llvm::handleAllErrors( + expected.takeError(), [](PythonException &E) { E.Restore(); }, + [](const llvm::ErrorInfoBase &E) { + PyErr_SetString(PyExc_Exception, E.message().c_str()); + }); + return T(); +} + +// This is only here to help incrementally migrate old, exception-unsafe +// code. +template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { + if (expected) + return std::move(expected.get()); + llvm::consumeError(expected.takeError()); + return T(); +} + +llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals); + +llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals); + +// Sometimes the best way to interact with a python interpreter is +// to run some python code. You construct a PythonScript with +// script string. The script assigns some function to `_function_` +// and you get a C++ callable object that calls the python function. +// +// Example: +// +// const char script[] = R"( +// def main(x, y): +// .... +// )"; +// +// Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { +// // no need to synchronize access to this global, we already have the GIL +// static PythonScript foo(script) +// return foo(x, y); +// } +class PythonScript { + const char *script; + PythonCallable function; + + llvm::Error Init(); + +public: + PythonScript(const char *script) : script(script), function() {} + + template <typename... Args> + llvm::Expected<PythonObject> operator()(Args &&... args) { + if (llvm::Error error = Init()) + return std::move(error); + return function.Call(std::forward<Args>(args)...); + } }; +} // namespace python } // namespace lldb_private #endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp deleted file mode 100644 index c9d834ce6868..000000000000 --- a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp +++ /dev/null @@ -1,169 +0,0 @@ -//===-- PythonExceptionState.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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_DISABLE_PYTHON - -// LLDB Python header must be included first -#include "lldb-python.h" - -#include "PythonExceptionState.h" - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/raw_ostream.h" - -using namespace lldb_private; - -PythonExceptionState::PythonExceptionState(bool restore_on_exit) - : m_restore_on_exit(restore_on_exit) { - Acquire(restore_on_exit); -} - -PythonExceptionState::~PythonExceptionState() { - if (m_restore_on_exit) - Restore(); -} - -void PythonExceptionState::Acquire(bool restore_on_exit) { - // If a state is already acquired, the user needs to decide whether they want - // to discard or restore it. Don't allow the potential silent loss of a - // valid state. - assert(!IsError()); - - if (!HasErrorOccurred()) - return; - - PyObject *py_type = nullptr; - PyObject *py_value = nullptr; - PyObject *py_traceback = nullptr; - PyErr_Fetch(&py_type, &py_value, &py_traceback); - // PyErr_Fetch clears the error flag. - assert(!HasErrorOccurred()); - - // Ownership of the objects returned by `PyErr_Fetch` is transferred to us. - m_type.Reset(PyRefType::Owned, py_type); - m_value.Reset(PyRefType::Owned, py_value); - m_traceback.Reset(PyRefType::Owned, py_traceback); - m_restore_on_exit = restore_on_exit; -} - -void PythonExceptionState::Restore() { - if (m_type.IsValid()) { - // The documentation for PyErr_Restore says "Do not pass a null type and - // non-null value or traceback. So only restore if type was non-null to - // begin with. In this case we're passing ownership back to Python so - // release them all. - PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release()); - } - - // After we restore, we should not hold onto the exception state. Demand - // that it be re-acquired. - Discard(); -} - -void PythonExceptionState::Discard() { - m_type.Reset(); - m_value.Reset(); - m_traceback.Reset(); -} - -void PythonExceptionState::Reset() { - if (m_restore_on_exit) - Restore(); - else - Discard(); -} - -bool PythonExceptionState::HasErrorOccurred() { return PyErr_Occurred(); } - -bool PythonExceptionState::IsError() const { - return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid(); -} - -PythonObject PythonExceptionState::GetType() const { return m_type; } - -PythonObject PythonExceptionState::GetValue() const { return m_value; } - -PythonObject PythonExceptionState::GetTraceback() const { return m_traceback; } - -std::string PythonExceptionState::Format() const { - // Don't allow this function to modify the error state. - PythonExceptionState state(true); - - std::string backtrace = ReadBacktrace(); - if (!IsError()) - return std::string(); - - // It's possible that ReadPythonBacktrace generated another exception. If - // this happens we have to clear the exception, because otherwise - // PyObject_Str() will assert below. That's why we needed to do the save / - // restore at the beginning of this function. - PythonExceptionState bt_error_state(false); - - std::string error_string; - llvm::raw_string_ostream error_stream(error_string); - error_stream << m_value.Str().GetString() << "\n"; - - if (!bt_error_state.IsError()) { - // If we were able to read the backtrace, just append it. - error_stream << backtrace << "\n"; - } else { - // Otherwise, append some information about why we were unable to obtain - // the backtrace. - PythonString bt_error = bt_error_state.GetValue().Str(); - error_stream << "An error occurred while retrieving the backtrace: " - << bt_error.GetString() << "\n"; - } - return error_stream.str(); -} - -std::string PythonExceptionState::ReadBacktrace() const { - std::string retval("backtrace unavailable"); - - auto traceback_module = PythonModule::ImportModule("traceback"); -#if PY_MAJOR_VERSION >= 3 - auto stringIO_module = PythonModule::ImportModule("io"); -#else - auto stringIO_module = PythonModule::ImportModule("StringIO"); -#endif - if (!m_traceback.IsAllocated()) - return retval; - - if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated()) - return retval; - - auto stringIO_builder = - stringIO_module.ResolveName<PythonCallable>("StringIO"); - if (!stringIO_builder.IsAllocated()) - return retval; - - auto stringIO_buffer = stringIO_builder(); - if (!stringIO_buffer.IsAllocated()) - return retval; - - auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb"); - if (!printTB.IsAllocated()) - return retval; - - auto printTB_result = - printTB(m_traceback.get(), Py_None, stringIO_buffer.get()); - auto stringIO_getvalue = - stringIO_buffer.ResolveName<PythonCallable>("getvalue"); - if (!stringIO_getvalue.IsAllocated()) - return retval; - - auto printTB_string = stringIO_getvalue().AsType<PythonString>(); - if (!printTB_string.IsAllocated()) - return retval; - - llvm::StringRef string_data(printTB_string.GetString()); - retval.assign(string_data.data(), string_data.size()); - - return retval; -} - -#endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h deleted file mode 100644 index 3a88aa037776..000000000000 --- a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- PythonExceptionState.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_PYTHONEXCEPTIONSTATE_H -#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H - -#ifndef LLDB_DISABLE_PYTHON - -#include "PythonDataObjects.h" - -namespace lldb_private { - -class PythonExceptionState { -public: - explicit PythonExceptionState(bool restore_on_exit); - ~PythonExceptionState(); - - void Acquire(bool restore_on_exit); - - void Restore(); - - void Discard(); - - void Reset(); - - static bool HasErrorOccurred(); - - bool IsError() const; - - PythonObject GetType() const; - - PythonObject GetValue() const; - - PythonObject GetTraceback() const; - - std::string Format() const; - -private: - std::string ReadBacktrace() const; - - bool m_restore_on_exit; - - PythonObject m_type; - PythonObject m_value; - PythonObject m_traceback; -}; -} - -#endif - -#endif diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 2d2b68ceaaa6..3eee52184142 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -16,7 +16,6 @@ #include "lldb-python.h" #include "PythonDataObjects.h" -#include "PythonExceptionState.h" #include "ScriptInterpreterPythonImpl.h" #include "lldb/API/SBFrame.h" @@ -45,6 +44,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatAdapters.h" #include <memory> #include <mutex> @@ -54,6 +54,8 @@ using namespace lldb; using namespace lldb_private; +using namespace lldb_private::python; +using llvm::Expected; // Defined in the SWIG source file #if PY_MAJOR_VERSION >= 3 @@ -96,6 +98,8 @@ LLDBSwigPythonCreateCommandObject(const char *python_class_name, extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan( const char *python_class_name, const char *session_dictionary_name, + StructuredDataImpl *args_data, + std::string &error_string, const lldb::ThreadPlanSP &thread_plan_sp); extern "C" bool LLDBSWIGPythonCallThreadPlan(void *implementor, @@ -302,39 +306,26 @@ void ScriptInterpreterPython::ComputePythonDirForApple( auto rend = llvm::sys::path::rend(path_ref); auto framework = std::find(rbegin, rend, "LLDB.framework"); if (framework == rend) { - ComputePythonDirForPosix(path); + ComputePythonDir(path); return; } path.resize(framework - rend); llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python"); } -void ScriptInterpreterPython::ComputePythonDirForPosix( +void ScriptInterpreterPython::ComputePythonDir( llvm::SmallVectorImpl<char> &path) { - auto style = llvm::sys::path::Style::posix; -#if defined(LLDB_PYTHON_RELATIVE_LIBDIR) // Build the path by backing out of the lib dir, then building with whatever // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL - // x86_64). - llvm::sys::path::remove_filename(path, style); - llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR); -#else - llvm::sys::path::append(path, style, - "python" + llvm::Twine(PY_MAJOR_VERSION) + "." + - llvm::Twine(PY_MINOR_VERSION), - "site-packages"); -#endif -} - -void ScriptInterpreterPython::ComputePythonDirForWindows( - llvm::SmallVectorImpl<char> &path) { - auto style = llvm::sys::path::Style::windows; - llvm::sys::path::remove_filename(path, style); - llvm::sys::path::append(path, style, "lib", "site-packages"); + // x86_64, or bin on Windows). + llvm::sys::path::remove_filename(path); + llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR); +#if defined(_WIN32) // This will be injected directly through FileSpec.GetDirectory().SetString(), // so we need to normalize manually. std::replace(path.begin(), path.end(), '\\', '/'); +#endif } FileSpec ScriptInterpreterPython::GetPythonDir() { @@ -347,10 +338,8 @@ FileSpec ScriptInterpreterPython::GetPythonDir() { #if defined(__APPLE__) ComputePythonDirForApple(path); -#elif defined(_WIN32) - ComputePythonDirForWindows(path); #else - ComputePythonDirForPosix(path); + ComputePythonDir(path); #endif spec.GetDirectory().SetString(path); return spec; @@ -382,7 +371,7 @@ void ScriptInterpreterPython::Terminate() {} ScriptInterpreterPythonImpl::Locker::Locker( ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry, - uint16_t on_leave, FILE *in, FILE *out, FILE *err) + uint16_t on_leave, FileSP in, FileSP out, FileSP err) : ScriptInterpreterLocker(), m_teardown_session((on_leave & TearDownSession) == TearDownSession), m_python_interpreter(py_interpreter) { @@ -412,8 +401,8 @@ bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() { } bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags, - FILE *in, FILE *out, - FILE *err) { + FileSP in, FileSP out, + FileSP err) { if (!m_python_interpreter) return false; return m_python_interpreter->EnterSession(on_entry_flags, in, out, err); @@ -448,9 +437,9 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(), m_run_one_line_str_global(), m_dictionary_name(m_debugger.GetInstanceName().AsCString()), - m_terminal_state(), m_active_io_handler(eIOHandlerNone), - m_session_is_active(false), m_pty_slave_is_open(false), - m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) { + m_active_io_handler(eIOHandlerNone), m_session_is_active(false), + m_pty_slave_is_open(false), m_valid_session(true), m_lock_count(0), + m_command_thread_state(nullptr) { InitializePrivate(); m_dictionary_name.append("_dict"); @@ -535,7 +524,7 @@ def function (frame, bp_loc, internal_dict): } if (instructions) { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(instructions); output_sp->Flush(); @@ -558,7 +547,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, if (!bp_options) continue; - auto data_up = llvm::make_unique<CommandDataPython>(); + auto data_up = std::make_unique<CommandDataPython>(); if (!data_up) break; data_up->user_source.SplitIntoLines(data); @@ -571,7 +560,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, bp_options->SetCallback( ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); } else if (!batch_mode) { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); if (error_sp) { error_sp->Printf("Warning: No command attached to breakpoint.\n"); error_sp->Flush(); @@ -583,7 +572,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, case eIOHandlerWatchpoint: { WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData(); - auto data_up = llvm::make_unique<WatchpointOptions::CommandData>(); + auto data_up = std::make_unique<WatchpointOptions::CommandData>(); data_up->user_source.SplitIntoLines(data); if (GenerateWatchpointCommandCallbackData(data_up->user_source, @@ -593,7 +582,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, wp_options->SetCallback( ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); } else if (!batch_mode) { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); if (error_sp) { error_sp->Printf("Warning: No command attached to breakpoint.\n"); error_sp->Flush(); @@ -609,29 +598,15 @@ ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) { return std::make_shared<ScriptInterpreterPythonImpl>(debugger); } -void ScriptInterpreterPythonImpl::ResetOutputFileHandle(FILE *fh) {} - -void ScriptInterpreterPythonImpl::SaveTerminalState(int fd) { - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state on - // the input file handle. - m_terminal_state.Save(fd, false); -} - -void ScriptInterpreterPythonImpl::RestoreTerminalState() { - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state on - // the input file handle. - m_terminal_state.Restore(); -} - void ScriptInterpreterPythonImpl::LeaveSession() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (log) log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()"); + // Unset the LLDB global variables. + PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process " + "= None; lldb.thread = None; lldb.frame = None"); + // checking that we have a valid thread state - since we use our own // threading and locking in some (rare) cases during cleanup Python may end // up believing we have no thread state and PyImport_AddModule will crash if @@ -662,45 +637,52 @@ void ScriptInterpreterPythonImpl::LeaveSession() { m_session_is_active = false; } -bool ScriptInterpreterPythonImpl::SetStdHandle(File &file, const char *py_name, - PythonFile &save_file, +bool ScriptInterpreterPythonImpl::SetStdHandle(FileSP file_sp, + const char *py_name, + PythonObject &save_file, const char *mode) { - if (file.IsValid()) { - // Flush the file before giving it to python to avoid interleaved output. - file.Flush(); + if (!file_sp || !*file_sp) { + save_file.Reset(); + return false; + } + File &file = *file_sp; - PythonDictionary &sys_module_dict = GetSysModuleDictionary(); + // Flush the file before giving it to python to avoid interleaved output. + file.Flush(); - save_file = sys_module_dict.GetItemForKey(PythonString(py_name)) - .AsType<PythonFile>(); + PythonDictionary &sys_module_dict = GetSysModuleDictionary(); - PythonFile new_file(file, mode); - sys_module_dict.SetItemForKey(PythonString(py_name), new_file); - return true; - } else - save_file.Reset(); - return false; + auto new_file = PythonFile::FromFile(file, mode); + if (!new_file) { + llvm::consumeError(new_file.takeError()); + return false; + } + + save_file = sys_module_dict.GetItemForKey(PythonString(py_name)); + + sys_module_dict.SetItemForKey(PythonString(py_name), new_file.get()); + return true; } bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, - FILE *in, FILE *out, FILE *err) { + FileSP in_sp, FileSP out_sp, + FileSP err_sp) { // If we have already entered the session, without having officially 'left' // it, then there is no need to 'enter' it again. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (m_session_is_active) { - if (log) - log->Printf( - "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 - ") session is already active, returning without doing anything", - on_entry_flags); + LLDB_LOGF( + log, + "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 + ") session is already active, returning without doing anything", + on_entry_flags); return false; } - if (log) - log->Printf( - "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 - ")", - on_entry_flags); + LLDB_LOGF( + log, + "ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16 ")", + on_entry_flags); m_session_is_active = true; @@ -733,33 +715,29 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { - File in_file(in, false); - File out_file(out, false); - File err_file(err, false); - - lldb::StreamFileSP in_sp; - lldb::StreamFileSP out_sp; - lldb::StreamFileSP err_sp; - if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid()) - m_debugger.AdoptTopIOHandlerFilesIfInvalid(in_sp, out_sp, err_sp); + lldb::FileSP top_in_sp; + lldb::StreamFileSP top_out_sp, top_err_sp; + if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp) + m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp, + top_err_sp); if (on_entry_flags & Locker::NoSTDIN) { m_saved_stdin.Reset(); } else { - if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) { - if (in_sp) - SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r"); + if (!SetStdHandle(in_sp, "stdin", m_saved_stdin, "r")) { + if (top_in_sp) + SetStdHandle(top_in_sp, "stdin", m_saved_stdin, "r"); } } - if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w")) { - if (out_sp) - SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w"); + if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) { + if (top_out_sp) + SetStdHandle(top_out_sp->GetFileSP(), "stdout", m_saved_stdout, "w"); } - if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w")) { - if (err_sp) - SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w"); + if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) { + if (top_err_sp) + SetStdHandle(top_err_sp->GetFileSP(), "stderr", m_saved_stderr, "w"); } } @@ -769,9 +747,9 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, return true; } -PythonObject &ScriptInterpreterPythonImpl::GetMainModule() { +PythonModule &ScriptInterpreterPythonImpl::GetMainModule() { if (!m_main_module.IsValid()) - m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__")); + m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__")); return m_main_module; } @@ -788,19 +766,16 @@ PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() { if (!main_dict.IsValid()) return m_session_dict; - PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name)); - m_session_dict.Reset(PyRefType::Borrowed, item.get()); + m_session_dict = unwrapIgnoringErrors( + As<PythonDictionary>(main_dict.GetItem(m_dictionary_name))); return m_session_dict; } PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() { if (m_sys_module_dict.IsValid()) return m_sys_module_dict; - - PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys")); - if (sys_module.IsValid()) - m_sys_module_dict.Reset(PyRefType::Borrowed, - PyModule_GetDict(sys_module.get())); + PythonModule sys_module = unwrapIgnoringErrors(PythonModule::Import("sys")); + m_sys_module_dict = sys_module.GetDictionary(); return m_sys_module_dict; } @@ -867,7 +842,7 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( // directly down to Python. Debugger &debugger = m_debugger; - StreamFileSP input_file_sp; + FileSP input_file_sp; StreamFileSP output_file_sp; StreamFileSP error_file_sp; Communication output_comm( @@ -875,7 +850,7 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( bool join_read_thread = false; if (options.GetEnableIO()) { if (result) { - input_file_sp = debugger.GetInputFile(); + input_file_sp = debugger.GetInputFileSP(); // Set output to a temporary file so we can forward the results on to // the result object @@ -906,9 +881,9 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( ::setbuf(outfile_handle, nullptr); result->SetImmediateOutputFile( - debugger.GetOutputFile()->GetFile().GetStream()); + debugger.GetOutputStream().GetFileSP()); result->SetImmediateErrorFile( - debugger.GetErrorFile()->GetFile().GetStream()); + debugger.GetErrorStream().GetFileSP()); } } } @@ -916,22 +891,26 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp); } else { - input_file_sp = std::make_shared<StreamFile>(); - FileSystem::Instance().Open(input_file_sp->GetFile(), + auto nullin = FileSystem::Instance().Open( FileSpec(FileSystem::DEV_NULL), File::eOpenOptionRead); - - output_file_sp = std::make_shared<StreamFile>(); - FileSystem::Instance().Open(output_file_sp->GetFile(), + auto nullout = FileSystem::Instance().Open( FileSpec(FileSystem::DEV_NULL), File::eOpenOptionWrite); - - error_file_sp = output_file_sp; + if (!nullin) { + result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n", + llvm::fmt_consume(nullin.takeError())); + return false; + } + if (!nullout) { + result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n", + llvm::fmt_consume(nullout.takeError())); + return false; + } + input_file_sp = std::move(nullin.get()); + error_file_sp = output_file_sp = std::make_shared<StreamFile>(std::move(nullout.get())); } - FILE *in_file = input_file_sp->GetFile().GetStream(); - FILE *out_file = output_file_sp->GetFile().GetStream(); - FILE *err_file = error_file_sp->GetFile().GetStream(); bool success = false; { // WARNING! It's imperative that this RAII scope be as tight as @@ -947,8 +926,8 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( Locker::AcquireLock | Locker::InitSession | (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN), - Locker::FreeAcquiredLock | Locker::TearDownSession, in_file, out_file, - err_file); + Locker::FreeAcquiredLock | Locker::TearDownSession, input_file_sp, + output_file_sp->GetFileSP(), error_file_sp->GetFileSP()); // Find the correct script interpreter dictionary in the main module. PythonDictionary &session_dict = GetSessionDictionary(); @@ -975,9 +954,8 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLine( } // Flush our output and error file handles - ::fflush(out_file); - if (out_file != err_file) - ::fflush(err_file); + output_file_sp->Flush(); + error_file_sp->Flush(); } if (join_read_thread) { @@ -1020,7 +998,7 @@ void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() { // a running interpreter loop inside the already running Python interpreter // loop, so we won't do it. - if (!debugger.GetInputFile()->GetFile().IsValid()) + if (!debugger.GetInputFile().IsValid()) return; IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this)); @@ -1040,19 +1018,19 @@ bool ScriptInterpreterPythonImpl::Interrupt() { long tid = state->thread_id; PyThreadState_Swap(state); int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); - if (log) - log->Printf("ScriptInterpreterPythonImpl::Interrupt() sending " - "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", - tid, num_threads); + LLDB_LOGF(log, + "ScriptInterpreterPythonImpl::Interrupt() sending " + "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", + tid, num_threads); return true; } } - if (log) - log->Printf( - "ScriptInterpreterPythonImpl::Interrupt() python code not running, " - "can't interrupt"); + LLDB_LOGF(log, + "ScriptInterpreterPythonImpl::Interrupt() python code not running, " + "can't interrupt"); return false; } + bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options) { @@ -1063,152 +1041,111 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( Locker::NoSTDIN, Locker::FreeAcquiredLock | Locker::TearDownSession); - PythonObject py_return; - PythonObject &main_module = GetMainModule(); - PythonDictionary globals(PyRefType::Borrowed, - PyModule_GetDict(main_module.get())); - PythonObject py_error; - bool ret_success = false; - int success; + PythonModule &main_module = GetMainModule(); + PythonDictionary globals = main_module.GetDictionary(); PythonDictionary locals = GetSessionDictionary(); - - if (!locals.IsValid()) { - locals.Reset( - PyRefType::Owned, - PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); - } - + if (!locals.IsValid()) + locals = unwrapIgnoringErrors( + As<PythonDictionary>(globals.GetAttribute(m_dictionary_name))); if (!locals.IsValid()) locals = globals; - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); - - std::string as_string = in_string.str(); - { // scope for PythonInputReaderManager - // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); - py_return.Reset(PyRefType::Owned, - PyRun_String(as_string.c_str(), Py_eval_input, - globals.get(), locals.get())); - if (!py_return.IsValid()) { - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); - - py_return.Reset(PyRefType::Owned, - PyRun_String(as_string.c_str(), Py_single_input, - globals.get(), locals.get())); - } + Expected<PythonObject> maybe_py_return = + runStringOneLine(in_string, globals, locals); + + if (!maybe_py_return) { + llvm::handleAllErrors( + maybe_py_return.takeError(), + [&](PythonException &E) { + E.Restore(); + if (options.GetMaskoutErrors()) { + if (E.Matches(PyExc_SyntaxError)) { + PyErr_Print(); + } + PyErr_Clear(); + } + }, + [](const llvm::ErrorInfoBase &E) {}); + return false; } - if (py_return.IsValid()) { - switch (return_type) { - case eScriptReturnTypeCharPtr: // "char *" - { - const char format[3] = "s#"; - success = PyArg_Parse(py_return.get(), format, (char **)ret_value); - break; - } - case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == - // Py_None - { - const char format[3] = "z"; - success = PyArg_Parse(py_return.get(), format, (char **)ret_value); - break; - } - case eScriptReturnTypeBool: { - const char format[2] = "b"; - success = PyArg_Parse(py_return.get(), format, (bool *)ret_value); - break; - } - case eScriptReturnTypeShortInt: { - const char format[2] = "h"; - success = PyArg_Parse(py_return.get(), format, (short *)ret_value); - break; - } - case eScriptReturnTypeShortIntUnsigned: { - const char format[2] = "H"; - success = - PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); - break; - } - case eScriptReturnTypeInt: { - const char format[2] = "i"; - success = PyArg_Parse(py_return.get(), format, (int *)ret_value); - break; - } - case eScriptReturnTypeIntUnsigned: { - const char format[2] = "I"; - success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); - break; - } - case eScriptReturnTypeLongInt: { - const char format[2] = "l"; - success = PyArg_Parse(py_return.get(), format, (long *)ret_value); - break; - } - case eScriptReturnTypeLongIntUnsigned: { - const char format[2] = "k"; - success = - PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); - break; - } - case eScriptReturnTypeLongLong: { - const char format[2] = "L"; - success = PyArg_Parse(py_return.get(), format, (long long *)ret_value); - break; - } - case eScriptReturnTypeLongLongUnsigned: { - const char format[2] = "K"; - success = - PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value); - break; - } - case eScriptReturnTypeFloat: { - const char format[2] = "f"; - success = PyArg_Parse(py_return.get(), format, (float *)ret_value); - break; - } - case eScriptReturnTypeDouble: { - const char format[2] = "d"; - success = PyArg_Parse(py_return.get(), format, (double *)ret_value); - break; - } - case eScriptReturnTypeChar: { - const char format[2] = "c"; - success = PyArg_Parse(py_return.get(), format, (char *)ret_value); - break; - } - case eScriptReturnTypeOpaqueObject: { - success = true; - PyObject *saved_value = py_return.get(); - Py_XINCREF(saved_value); - *((PyObject **)ret_value) = saved_value; - break; - } - } + PythonObject py_return = std::move(maybe_py_return.get()); + assert(py_return.IsValid()); - ret_success = success; + switch (return_type) { + case eScriptReturnTypeCharPtr: // "char *" + { + const char format[3] = "s#"; + return PyArg_Parse(py_return.get(), format, (char **)ret_value); + } + case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == + // Py_None + { + const char format[3] = "z"; + return PyArg_Parse(py_return.get(), format, (char **)ret_value); + } + case eScriptReturnTypeBool: { + const char format[2] = "b"; + return PyArg_Parse(py_return.get(), format, (bool *)ret_value); + } + case eScriptReturnTypeShortInt: { + const char format[2] = "h"; + return PyArg_Parse(py_return.get(), format, (short *)ret_value); + } + case eScriptReturnTypeShortIntUnsigned: { + const char format[2] = "H"; + return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); + } + case eScriptReturnTypeInt: { + const char format[2] = "i"; + return PyArg_Parse(py_return.get(), format, (int *)ret_value); + } + case eScriptReturnTypeIntUnsigned: { + const char format[2] = "I"; + return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); + } + case eScriptReturnTypeLongInt: { + const char format[2] = "l"; + return PyArg_Parse(py_return.get(), format, (long *)ret_value); + } + case eScriptReturnTypeLongIntUnsigned: { + const char format[2] = "k"; + return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); + } + case eScriptReturnTypeLongLong: { + const char format[2] = "L"; + return PyArg_Parse(py_return.get(), format, (long long *)ret_value); + } + case eScriptReturnTypeLongLongUnsigned: { + const char format[2] = "K"; + return PyArg_Parse(py_return.get(), format, + (unsigned long long *)ret_value); + } + case eScriptReturnTypeFloat: { + const char format[2] = "f"; + return PyArg_Parse(py_return.get(), format, (float *)ret_value); + } + case eScriptReturnTypeDouble: { + const char format[2] = "d"; + return PyArg_Parse(py_return.get(), format, (double *)ret_value); + } + case eScriptReturnTypeChar: { + const char format[2] = "c"; + return PyArg_Parse(py_return.get(), format, (char *)ret_value); + } + case eScriptReturnTypeOpaqueObject: { + *((PyObject **)ret_value) = py_return.release(); + return true; } - - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) { - ret_success = false; - if (options.GetMaskoutErrors()) { - if (PyErr_GivenExceptionMatches(py_error.get(), PyExc_SyntaxError)) - PyErr_Print(); - PyErr_Clear(); - } } - - return ret_success; } Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( const char *in_string, const ExecuteScriptOptions &options) { - Status error; + + if (in_string == nullptr) + return Status(); Locker locker(this, Locker::AcquireLock | Locker::InitSession | @@ -1216,52 +1153,32 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( Locker::NoSTDIN, Locker::FreeAcquiredLock | Locker::TearDownSession); - PythonObject return_value; - PythonObject &main_module = GetMainModule(); - PythonDictionary globals(PyRefType::Borrowed, - PyModule_GetDict(main_module.get())); - PythonObject py_error; + PythonModule &main_module = GetMainModule(); + PythonDictionary globals = main_module.GetDictionary(); PythonDictionary locals = GetSessionDictionary(); - if (!locals.IsValid()) - locals.Reset( - PyRefType::Owned, - PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); - + locals = unwrapIgnoringErrors( + As<PythonDictionary>(globals.GetAttribute(m_dictionary_name))); if (!locals.IsValid()) locals = globals; - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); + Expected<PythonObject> return_value = + runStringMultiLine(in_string, globals, locals); - if (in_string != nullptr) { - PythonObject code_object; - code_object.Reset(PyRefType::Owned, - Py_CompileString(in_string, "temp.py", Py_file_input)); - - if (code_object.IsValid()) { -// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it -// takes a PyObject. They are convertible (hence the function -// PyCode_Check(PyObject*), so we have to do the cast for Python 2.x -#if PY_MAJOR_VERSION >= 3 - PyObject *py_code_obj = code_object.get(); -#else - PyCodeObject *py_code_obj = - reinterpret_cast<PyCodeObject *>(code_object.get()); -#endif - return_value.Reset( - PyRefType::Owned, - PyEval_EvalCode(py_code_obj, globals.get(), locals.get())); - } + if (!return_value) { + llvm::Error error = + llvm::handleErrors(return_value.takeError(), [&](PythonException &E) { + llvm::Error error = llvm::createStringError( + llvm::inconvertibleErrorCode(), E.ReadBacktrace()); + if (!options.GetMaskoutErrors()) + E.Restore(); + return error; + }); + return Status(std::move(error)); } - PythonExceptionState exception_state(!options.GetMaskoutErrors()); - if (exception_state.IsError()) - error.SetErrorString(exception_state.Format().c_str()); - - return error; + return Status(); } void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback( @@ -1308,7 +1225,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( // Set a Python one-liner as the callback for the breakpoint. Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( BreakpointOptions *bp_options, const char *command_body_text) { - auto data_up = llvm::make_unique<CommandDataPython>(); + auto data_up = std::make_unique<CommandDataPython>(); // Split the command_body_text into lines, and pass that to // GenerateBreakpointCommandCallbackData. That will wrap the body in an @@ -1331,7 +1248,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( // Set a Python one-liner as the callback for the watchpoint. void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( WatchpointOptions *wp_options, const char *oneliner) { - auto data_up = llvm::make_unique<WatchpointOptions::CommandData>(); + auto data_up = std::make_unique<WatchpointOptions::CommandData>(); // It's necessary to set both user_source and script_source to the oneliner. // The former is used to generate callback description (as in watchpoint @@ -1853,12 +1770,14 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( } StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( - const char *class_name, lldb::ThreadPlanSP thread_plan_sp) { + const char *class_name, StructuredDataImpl *args_data, + std::string &error_str, + lldb::ThreadPlanSP thread_plan_sp) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::ObjectSP(); if (!thread_plan_sp.get()) - return StructuredData::ObjectSP(); + return {}; Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter(); @@ -1866,17 +1785,18 @@ StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); if (!script_interpreter) - return StructuredData::ObjectSP(); + return {}; void *ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedThreadPlan( class_name, python_interpreter->m_dictionary_name.c_str(), - thread_plan_sp); + args_data, error_str, thread_plan_sp); + if (!ret_val) + return {}; } return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); @@ -2052,15 +1972,22 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings( if (!generic) return StructuredData::DictionarySP(); - PythonObject reply_pyobj; Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); TargetSP target_sp(target->shared_from_this()); - reply_pyobj.Reset(PyRefType::Owned, - (PyObject *)LLDBSWIGPython_GetDynamicSetting( - generic->GetValue(), setting_name, target_sp)); - PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get()); + auto setting = (PyObject *)LLDBSWIGPython_GetDynamicSetting( + generic->GetValue(), setting_name, target_sp); + + if (!setting) + return StructuredData::DictionarySP(); + + PythonDictionary py_dict = + unwrapIgnoringErrors(As<PythonDictionary>(Take<PythonObject>(setting))); + + if (!py_dict) + return StructuredData::DictionarySP(); + return py_dict.CreateStructuredDictionary(); } @@ -2230,18 +2157,6 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( return ret_val; } -void ScriptInterpreterPythonImpl::Clear() { - // Release any global variables that might have strong references to - // LLDB objects when clearing the python script interpreter. - Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock); - - // This may be called as part of Py_Finalize. In that case the modules are - // destroyed in random order and we can't guarantee that we can access these. - if (Py_IsInitialized()) - PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process " - "= None; lldb.thread = None; lldb.frame = None"); -} - bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h index 24941ec77452..33ae308041b2 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -48,8 +48,7 @@ public: protected: static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path); - static void ComputePythonDirForPosix(llvm::SmallVectorImpl<char> &path); - static void ComputePythonDirForWindows(llvm::SmallVectorImpl<char> &path); + static void ComputePythonDir(llvm::SmallVectorImpl<char> &path); }; } // namespace lldb_private diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index a9993c4068a2..929567e579d8 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -78,6 +78,8 @@ public: StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, + StructuredDataImpl *args_data, + std::string &error_str, lldb::ThreadPlanSP thread_plan) override; bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, @@ -188,8 +190,6 @@ public: const TypeSummaryOptions &options, std::string &retval) override; - void Clear() override; - bool GetDocumentationForItem(const char *item, std::string &dest) override; bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, @@ -256,8 +256,6 @@ public: void SetWatchpointCommandCallback(WatchpointOptions *wp_options, const char *oneliner) override; - void ResetOutputFileHandle(FILE *new_fh) override; - const char *GetDictionaryName() { return m_dictionary_name.c_str(); } PyThreadState *GetThreadState() { return m_command_thread_state; } @@ -296,17 +294,19 @@ public: TearDownSession = 0x0004 }; - Locker(ScriptInterpreterPythonImpl *py_interpreter = nullptr, + Locker(ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry = AcquireLock | InitSession, - uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr, - FILE *out = nullptr, FILE *err = nullptr); + uint16_t on_leave = FreeLock | TearDownSession, + lldb::FileSP in = nullptr, lldb::FileSP out = nullptr, + lldb::FileSP err = nullptr); ~Locker() override; private: bool DoAcquireLock(); - bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); + bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in, + lldb::FileSP out, lldb::FileSP err); bool DoFreeLock(); @@ -314,7 +314,6 @@ public: bool m_teardown_session; ScriptInterpreterPythonImpl *m_python_interpreter; - // FILE* m_tmp_fh; PyGILState_STATE m_GILState; }; @@ -343,14 +342,11 @@ public: static void AddToSysPath(AddLocation location, std::string path); - bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); + bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out, + lldb::FileSP err); void LeaveSession(); - void SaveTerminalState(int fd); - - void RestoreTerminalState(); - uint32_t IsExecutingPython() const { return m_lock_count > 0; } uint32_t IncrementLockCount() { return ++m_lock_count; } @@ -367,27 +363,26 @@ public: eIOHandlerWatchpoint }; - PythonObject &GetMainModule(); + python::PythonModule &GetMainModule(); - PythonDictionary &GetSessionDictionary(); + python::PythonDictionary &GetSessionDictionary(); - PythonDictionary &GetSysModuleDictionary(); + python::PythonDictionary &GetSysModuleDictionary(); bool GetEmbeddedInterpreterModuleObjects(); - bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file, - const char *mode); - - PythonFile m_saved_stdin; - PythonFile m_saved_stdout; - PythonFile m_saved_stderr; - PythonObject m_main_module; - PythonDictionary m_session_dict; - PythonDictionary m_sys_module_dict; - PythonObject m_run_one_line_function; - PythonObject m_run_one_line_str_global; + bool SetStdHandle(lldb::FileSP file, const char *py_name, + python::PythonObject &save_file, const char *mode); + + python::PythonObject m_saved_stdin; + python::PythonObject m_saved_stdout; + python::PythonObject m_saved_stderr; + python::PythonModule m_main_module; + python::PythonDictionary m_session_dict; + python::PythonDictionary m_sys_module_dict; + python::PythonObject m_run_one_line_function; + python::PythonObject m_run_one_line_str_global; std::string m_dictionary_name; - TerminalState m_terminal_state; ActiveIOHandler m_active_io_handler; bool m_session_is_active; bool m_pty_slave_is_open; diff --git a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp index 81a27125c036..c6b234baa8c8 100644 --- a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp +++ b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp @@ -104,30 +104,13 @@ void SetGlobalEnableOptions(const DebuggerSP &debugger_sp, /// Code to handle the StructuredDataDarwinLog settings -static constexpr PropertyDefinition g_properties[] = { - { - "enable-on-startup", // name - OptionValue::eTypeBoolean, // type - true, // global - false, // default uint value - nullptr, // default cstring value - {}, // enum values - "Enable Darwin os_log collection when debugged process is launched " - "or attached." // description - }, - { - "auto-enable-options", // name - OptionValue::eTypeString, // type - true, // global - 0, // default uint value - "", // default cstring value - {}, // enum values - "Specify the options to 'plugin structured-data darwin-log enable' " - "that should be applied when automatically enabling logging on " - "startup/attach." // description - }}; - -enum { ePropertyEnableOnStartup = 0, ePropertyAutoEnableOptions = 1 }; +#define LLDB_PROPERTIES_darwinlog +#include "StructuredDataDarwinLogProperties.inc" + +enum { +#define LLDB_PROPERTIES_darwinlog +#include "StructuredDataDarwinLogPropertiesEnum.inc" +}; class StructuredDataDarwinLogProperties : public Properties { public: @@ -138,7 +121,7 @@ public: StructuredDataDarwinLogProperties() : Properties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_darwinlog_properties); } ~StructuredDataDarwinLogProperties() override {} @@ -146,13 +129,13 @@ public: bool GetEnableOnStartup() const { const uint32_t idx = ePropertyEnableOnStartup; return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_darwinlog_properties[idx].default_uint_value != 0); } llvm::StringRef GetAutoEnableOptions() const { const uint32_t idx = ePropertyAutoEnableOptions; return m_collection_sp->GetPropertyAtIndexAsString( - nullptr, idx, g_properties[idx].default_cstr_value); + nullptr, idx, g_darwinlog_properties[idx].default_cstr_value); } const char *GetLoggingModuleName() const { return "libsystem_trace.dylib"; } @@ -305,11 +288,8 @@ private: // Instantiate the regex so we can report any errors. auto regex = RegularExpression(op_arg); - if (!regex.IsValid()) { - char error_text[256]; - error_text[0] = '\0'; - regex.GetErrorAsCString(error_text, sizeof(error_text)); - error.SetErrorString(error_text); + if (llvm::Error err = regex.GetError()) { + error.SetErrorString(llvm::toString(std::move(err))); return FilterRuleSP(); } @@ -807,15 +787,10 @@ protected: // Now check if we have a running process. If so, we should instruct the // process monitor to enable/disable DarwinLog support now. - Target *target = GetSelectedOrDummyTarget(); - if (!target) { - // No target, so there is nothing more to do right now. - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } + Target &target = GetSelectedOrDummyTarget(); // Grab the active process. - auto process_sp = target->GetProcessSP(); + auto process_sp = target.GetProcessSP(); if (!process_sp) { // No active process, so there is nothing more to do right now. result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -897,9 +872,9 @@ protected: // Figure out if we've got a process. If so, we can tell if DarwinLog is // available for that process. - Target *target = GetSelectedOrDummyTarget(); - auto process_sp = target ? target->GetProcessSP() : ProcessSP(); - if (!target || !process_sp) { + Target &target = GetSelectedOrDummyTarget(); + auto process_sp = target.GetProcessSP(); + if (!process_sp) { stream.PutCString("Availability: unknown (requires process)\n"); stream.PutCString("Enabled: not applicable " "(requires process)\n"); @@ -1119,26 +1094,26 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData( object_sp->Dump(json_stream); else json_stream.PutCString("<null>"); - log->Printf("StructuredDataDarwinLog::%s() called with json: %s", - __FUNCTION__, json_stream.GetData()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called with json: %s", + __FUNCTION__, json_stream.GetData()); } // Ignore empty structured data. if (!object_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() StructuredData object " - "is null", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() StructuredData object " + "is null", + __FUNCTION__); return; } // Ignore any data that isn't for us. if (type_name != GetDarwinLogTypeName()) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() StructuredData type " - "expected to be %s but was %s, ignoring", - __FUNCTION__, GetDarwinLogTypeName().AsCString(), - type_name.AsCString()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() StructuredData type " + "expected to be %s but was %s, ignoring", + __FUNCTION__, GetDarwinLogTypeName().AsCString(), + type_name.AsCString()); return; } @@ -1148,9 +1123,8 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData( DebuggerSP debugger_sp = process.GetTarget().GetDebugger().shared_from_this(); auto options_sp = GetGlobalEnableOptions(debugger_sp); if (options_sp && options_sp->GetBroadcastEvents()) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() broadcasting event", - __FUNCTION__); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() broadcasting event", + __FUNCTION__); process.BroadcastStructuredData(object_sp, shared_from_this()); } @@ -1263,19 +1237,18 @@ void StructuredDataDarwinLog::SetEnabled(bool enabled) { void StructuredDataDarwinLog::ModulesDidLoad(Process &process, ModuleList &module_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s called (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s called (process uid %u)", + __FUNCTION__, process.GetUniqueID()); // Check if we should enable the darwin log support on startup/attach. if (!GetGlobalProperties()->GetEnableOnStartup() && !s_is_explicitly_enabled) { // We're neither auto-enabled or explicitly enabled, so we shouldn't try to // enable here. - if (log) - log->Printf("StructuredDataDarwinLog::%s not applicable, we're not " - "enabled (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s not applicable, we're not " + "enabled (process uid %u)", + __FUNCTION__, process.GetUniqueID()); return; } @@ -1283,10 +1256,10 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, { std::lock_guard<std::mutex> locker(m_added_breakpoint_mutex); if (m_added_breakpoint) { - if (log) - log->Printf("StructuredDataDarwinLog::%s process uid %u's " - "post-libtrace-init breakpoint is already set", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s process uid %u's " + "post-libtrace-init breakpoint is already set", + __FUNCTION__, process.GetUniqueID()); return; } } @@ -1298,11 +1271,11 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, GetGlobalProperties()->GetLoggingModuleName(); if (!logging_module_cstr || (logging_module_cstr[0] == 0)) { // We need this. Bail. - if (log) - log->Printf("StructuredDataDarwinLog::%s no logging module name " - "specified, we don't know where to set a breakpoint " - "(process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s no logging module name " + "specified, we don't know where to set a breakpoint " + "(process uid %u)", + __FUNCTION__, process.GetUniqueID()); return; } @@ -1324,23 +1297,23 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process, } if (!found_logging_support_module) { - if (log) - log->Printf("StructuredDataDarwinLog::%s logging module %s " - "has not yet been loaded, can't set a breakpoint " - "yet (process uid %u)", - __FUNCTION__, logging_module_name.AsCString(), - process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s logging module %s " + "has not yet been loaded, can't set a breakpoint " + "yet (process uid %u)", + __FUNCTION__, logging_module_name.AsCString(), + process.GetUniqueID()); return; } // Time to enqueue the breakpoint so we can wait for logging support to be // initialized before we try to tap the libtrace stream. AddInitCompletionHook(process); - if (log) - log->Printf("StructuredDataDarwinLog::%s post-init hook breakpoint " - "set for logging module %s (process uid %u)", - __FUNCTION__, logging_module_name.AsCString(), - process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s post-init hook breakpoint " + "set for logging module %s (process uid %u)", + __FUNCTION__, logging_module_name.AsCString(), + process.GetUniqueID()); // We need to try the enable here as well, which will succeed in the event // that we're attaching to (rather than launching) the process and the @@ -1519,38 +1492,36 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( // we can execute our logic to enable the logging support. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s() called", __FUNCTION__); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called", __FUNCTION__); // Get the current thread. if (!context) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: no context, " - "ignoring", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: no context, " + "ignoring", + __FUNCTION__); return false; } // Get the plugin from the process. auto process_sp = context->exe_ctx_ref.GetProcessSP(); if (!process_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: invalid " - "process in context, ignoring", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: invalid " + "process in context, ignoring", + __FUNCTION__); return false; } - if (log) - log->Printf("StructuredDataDarwinLog::%s() call is for process uid %d", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() call is for process uid %d", + __FUNCTION__, process_sp->GetUniqueID()); auto plugin_sp = process_sp->GetStructuredDataPlugin(GetDarwinLogTypeName()); if (!plugin_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: no plugin for " - "feature %s in process uid %u", - __FUNCTION__, GetDarwinLogTypeName().AsCString(), - process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: no plugin for " + "feature %s in process uid %u", + __FUNCTION__, GetDarwinLogTypeName().AsCString(), + process_sp->GetUniqueID()); return false; } @@ -1561,51 +1532,51 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( std::weak_ptr<StructuredDataPlugin> plugin_wp(plugin_sp); ThreadPlanCallOnFunctionExit::Callback callback = [plugin_wp, &called_enable_method, log, process_uid]() { - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "called (process uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "called (process uid %u)", + process_uid); auto strong_plugin_sp = plugin_wp.lock(); if (!strong_plugin_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "plugin no longer exists, ignoring (process " - "uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "plugin no longer exists, ignoring (process " + "uid %u)", + process_uid); return; } // Make sure we only call it once, just in case the thread plan hits // the breakpoint twice. if (!called_enable_method) { - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "calling EnableNow() (process uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "calling EnableNow() (process uid %u)", + process_uid); static_cast<StructuredDataDarwinLog *>(strong_plugin_sp.get()) ->EnableNow(); called_enable_method = true; } else { // Our breakpoint was hit more than once. Unexpected but no harm // done. Log it. - if (log) - log->Printf("StructuredDataDarwinLog::post-init callback: " - "skipping EnableNow(), already called by " - "callback [we hit this more than once] " - "(process uid %u)", - process_uid); + LLDB_LOGF(log, + "StructuredDataDarwinLog::post-init callback: " + "skipping EnableNow(), already called by " + "callback [we hit this more than once] " + "(process uid %u)", + process_uid); } }; // Grab the current thread. auto thread_sp = context->exe_ctx_ref.GetThreadSP(); if (!thread_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to " - "retrieve the current thread from the execution " - "context, nowhere to run the thread plan (process uid " - "%u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to " + "retrieve the current thread from the execution " + "context, nowhere to run the thread plan (process uid " + "%u)", + __FUNCTION__, process_sp->GetUniqueID()); return false; } @@ -1614,10 +1585,10 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( ThreadPlanSP(new ThreadPlanCallOnFunctionExit(*thread_sp, callback)); const bool abort_other_plans = false; thread_sp->QueueThreadPlan(thread_plan_sp, abort_other_plans); - if (log) - log->Printf("StructuredDataDarwinLog::%s() queuing thread plan on " - "trace library init method entry (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() queuing thread plan on " + "trace library init method entry (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); // We return false here to indicate that it isn't a public stop. return false; @@ -1625,18 +1596,17 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback( void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s() called (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called (process uid %u)", + __FUNCTION__, process.GetUniqueID()); // Make sure we haven't already done this. { std::lock_guard<std::mutex> locker(m_added_breakpoint_mutex); if (m_added_breakpoint) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() ignoring request, " - "breakpoint already set (process uid %u)", - __FUNCTION__, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() ignoring request, " + "breakpoint already set (process uid %u)", + __FUNCTION__, process.GetUniqueID()); return; } @@ -1669,22 +1639,22 @@ void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) { eLanguageTypeC, offset, skip_prologue, internal, hardware); if (!breakpoint_sp) { // Huh? Bail here. - if (log) - log->Printf("StructuredDataDarwinLog::%s() failed to set " - "breakpoint in module %s, function %s (process uid %u)", - __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), - func_name, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() failed to set " + "breakpoint in module %s, function %s (process uid %u)", + __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), + func_name, process.GetUniqueID()); return; } // Set our callback. breakpoint_sp->SetCallback(InitCompletionHookCallback, nullptr); m_breakpoint_id = breakpoint_sp->GetID(); - if (log) - log->Printf("StructuredDataDarwinLog::%s() breakpoint set in module %s," - "function %s (process uid %u)", - __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), - func_name, process.GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() breakpoint set in module %s," + "function %s (process uid %u)", + __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(), + func_name, process.GetUniqueID()); } void StructuredDataDarwinLog::DumpTimestamp(Stream &stream, @@ -1825,22 +1795,20 @@ size_t StructuredDataDarwinLog::HandleDisplayOfEvent( void StructuredDataDarwinLog::EnableNow() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("StructuredDataDarwinLog::%s() called", __FUNCTION__); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called", __FUNCTION__); // Run the enable command. auto process_sp = GetProcess(); if (!process_sp) { // Nothing to do. - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to get " - "valid process, skipping", - __FUNCTION__); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to get " + "valid process, skipping", + __FUNCTION__); return; } - if (log) - log->Printf("StructuredDataDarwinLog::%s() call is for process uid %u", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, "StructuredDataDarwinLog::%s() call is for process uid %u", + __FUNCTION__, process_sp->GetUniqueID()); // If we have configuration data, we can directly enable it now. Otherwise, // we need to run through the command interpreter to parse the auto-run @@ -1849,10 +1817,10 @@ void StructuredDataDarwinLog::EnableNow() { DebuggerSP debugger_sp = process_sp->GetTarget().GetDebugger().shared_from_this(); if (!debugger_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to get " - "debugger shared pointer, skipping (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to get " + "debugger shared pointer, skipping (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); return; } @@ -1864,13 +1832,15 @@ void StructuredDataDarwinLog::EnableNow() { const bool success = RunEnableCommand(interpreter); if (log) { if (success) - log->Printf("StructuredDataDarwinLog::%s() ran enable command " - "successfully for (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() ran enable command " + "successfully for (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); else - log->Printf("StructuredDataDarwinLog::%s() error: running " - "enable command failed (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() error: running " + "enable command failed (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); } // Report failures to the debugger error stream. auto error_stream_sp = debugger_sp->GetAsyncErrorStream(); @@ -1886,11 +1856,11 @@ void StructuredDataDarwinLog::EnableNow() { // specified options. auto config_sp = options_sp->BuildConfigurationData(true); if (!config_sp) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() warning: failed to " - "build configuration data for enable options, skipping " - "(process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() warning: failed to " + "build configuration data for enable options, skipping " + "(process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); return; } @@ -1901,11 +1871,11 @@ void StructuredDataDarwinLog::EnableNow() { // Report results. if (!error.Success()) { - if (log) - log->Printf("StructuredDataDarwinLog::%s() " - "ConfigureStructuredData() call failed " - "(process uid %u): %s", - __FUNCTION__, process_sp->GetUniqueID(), error.AsCString()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() " + "ConfigureStructuredData() call failed " + "(process uid %u): %s", + __FUNCTION__, process_sp->GetUniqueID(), error.AsCString()); auto error_stream_sp = debugger_sp->GetAsyncErrorStream(); if (error_stream_sp) { error_stream_sp->Printf("failed to configure DarwinLog " @@ -1916,9 +1886,9 @@ void StructuredDataDarwinLog::EnableNow() { m_is_enabled = false; } else { m_is_enabled = true; - if (log) - log->Printf("StructuredDataDarwinLog::%s() success via direct " - "configuration (process uid %u)", - __FUNCTION__, process_sp->GetUniqueID()); + LLDB_LOGF(log, + "StructuredDataDarwinLog::%s() success via direct " + "configuration (process uid %u)", + __FUNCTION__, process_sp->GetUniqueID()); } } diff --git a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLogProperties.td b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLogProperties.td new file mode 100644 index 000000000000..5c22158542f9 --- /dev/null +++ b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLogProperties.td @@ -0,0 +1,12 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "darwinlog" in { + def EnableOnStartup: Property<"enable-on-startup", "Boolean">, + Global, + DefaultFalse, + Desc<"Enable Darwin os_log collection when debugged process is launched or attached.">; + def AutoEnableOptions: Property<"auto-enable-options", "String">, + Global, + DefaultStringValue<"">, + Desc<"Specify the options to 'plugin structured-data darwin-log enable' that should be applied when automatically enabling logging on startup/attach.">; +} diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index d4258274a38c..f84cf0c5368d 100644 --- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -15,7 +15,6 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/PostfixExpression.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Utility/Log.h" @@ -126,8 +125,8 @@ SymbolFileBreakpad::LineIterator::operator++() { llvm::iterator_range<SymbolFileBreakpad::LineIterator> SymbolFileBreakpad::lines(Record::Kind section_type) { - return llvm::make_range(LineIterator(*m_obj_file, section_type), - LineIterator(*m_obj_file)); + return llvm::make_range(LineIterator(*m_objfile_sp, section_type), + LineIterator(*m_objfile_sp)); } namespace { @@ -179,15 +178,13 @@ ConstString SymbolFileBreakpad::GetPluginNameStatic() { } uint32_t SymbolFileBreakpad::CalculateAbilities() { - if (!m_obj_file) - return 0; - if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic()) + if (!m_objfile_sp || !llvm::isa<ObjectFileBreakpad>(*m_objfile_sp)) return 0; return CompileUnits | Functions | LineTables; } -uint32_t SymbolFileBreakpad::GetNumCompileUnits() { +uint32_t SymbolFileBreakpad::CalculateNumCompileUnits() { ParseCUData(); return m_cu_data->GetSize(); } @@ -204,7 +201,8 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) { // The FileSpec of the compile unit will be the file corresponding to the // first LINE record. - LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); + LineIterator It(*m_objfile_sp, Record::Func, data.bookmark), + End(*m_objfile_sp); assert(Record::classify(*It) == Record::Func); ++It; // Skip FUNC record. if (It != End) { @@ -213,12 +211,12 @@ CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) { spec = (*m_files)[record->FileNum]; } - auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), + auto cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), /*user_data*/ nullptr, spec, index, eLanguageTypeUnknown, /*is_optimized*/ eLazyBoolNo); - GetSymbolVendor().SetCompileUnitAtIndex(index, cu_sp); + SetCompileUnitAtIndex(index, cu_sp); return cu_sp; } @@ -228,6 +226,7 @@ size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data; if (!data.line_table_up) @@ -239,6 +238,7 @@ bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { bool SymbolFileBreakpad::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data; if (!data.support_files) ParseLineTableAndSupportFiles(comp_unit, data); @@ -251,6 +251,7 @@ uint32_t SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry))) return 0; @@ -260,7 +261,7 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, if (idx == UINT32_MAX) return 0; - sc.comp_unit = GetSymbolVendor().GetCompileUnitAtIndex(idx).get(); + sc.comp_unit = GetCompileUnitAtIndex(idx).get(); SymbolContextItem result = eSymbolContextCompUnit; if (resolve_scope & eSymbolContextLineEntry) { if (sc.comp_unit->GetLineTable()->FindLineEntryByAddress(so_addr, @@ -275,57 +276,43 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, uint32_t SymbolFileBreakpad::ResolveSymbolContext( const FileSpec &file_spec, uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!(resolve_scope & eSymbolContextCompUnit)) return 0; uint32_t old_size = sc_list.GetSize(); for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) { - CompileUnit &cu = *GetSymbolVendor().GetCompileUnitAtIndex(i); + CompileUnit &cu = *GetCompileUnitAtIndex(i); cu.ResolveSymbolContext(file_spec, line, check_inlines, /*exact*/ false, resolve_scope, sc_list); } return sc_list.GetSize() - old_size; } -uint32_t SymbolFileBreakpad::FindFunctions( +void SymbolFileBreakpad::FindFunctions( ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { // TODO - if (!append) - sc_list.Clear(); - return sc_list.GetSize(); } -uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { // TODO - if (!append) - sc_list.Clear(); - return sc_list.GetSize(); } -uint32_t SymbolFileBreakpad::FindTypes( +void SymbolFileBreakpad::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { - if (!append) - types.Clear(); - return types.GetSize(); -} + uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) {} -size_t -SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - if (!append) - types.Clear(); - return types.GetSize(); -} +void SymbolFileBreakpad::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) {} void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); - Module &module = *m_obj_file->GetModule(); + Module &module = *m_objfile_sp->GetModule(); addr_t base = GetBaseFileAddress(); if (base == LLDB_INVALID_ADDRESS) { LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping " @@ -347,8 +334,8 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { return; } symbols.try_emplace( - address, /*symID*/ 0, Mangled(name, /*is_mangled*/ false), - eSymbolTypeCode, /*is_global*/ true, /*is_debug*/ false, + address, /*symID*/ 0, Mangled(name), eSymbolTypeCode, + /*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false, /*is_artificial*/ false, AddressRange(section_sp, address - section_sp->GetFileAddress(), size.getValueOr(0)), @@ -372,6 +359,20 @@ void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { symtab.CalculateSymbolSizes(); } +llvm::Expected<lldb::addr_t> +SymbolFileBreakpad::GetParameterStackSize(Symbol &symbol) { + ParseUnwindData(); + if (auto *entry = m_unwind_data->win.FindEntryThatContains( + symbol.GetAddress().GetFileAddress())) { + auto record = StackWinRecord::parse( + *LineIterator(*m_objfile_sp, Record::StackWin, entry->data)); + assert(record.hasValue()); + return record->ParameterSize; + } + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Parameter size unknown."); +} + static llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>> GetRule(llvm::StringRef &unwind_rules) { // Unwind rules are of the form @@ -418,7 +419,17 @@ ResolveRegisterOrRA(const SymbolFile::RegisterInfoResolver &resolver, return ResolveRegister(resolver, name); } -bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, +llvm::ArrayRef<uint8_t> SymbolFileBreakpad::SaveAsDWARF(postfix::Node &node) { + ArchSpec arch = m_objfile_sp->GetArchitecture(); + StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(), + arch.GetByteOrder()); + ToDWARF(node, dwarf); + uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize()); + std::memcpy(saved, dwarf.GetData(), dwarf.GetSize()); + return {saved, dwarf.GetSize()}; +} + +bool SymbolFileBreakpad::ParseCFIUnwindRow(llvm::StringRef unwind_rules, const RegisterInfoResolver &resolver, UnwindPlan::Row &row) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); @@ -427,7 +438,7 @@ bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, while (auto rule = GetRule(unwind_rules)) { node_alloc.Reset(); llvm::StringRef lhs = rule->first; - postfix::Node *rhs = postfix::Parse(rule->second, node_alloc); + postfix::Node *rhs = postfix::ParseOneExpression(rule->second, node_alloc); if (!rhs) { LLDB_LOG(log, "Could not parse `{0}` as unwind rhs.", rule->second); return false; @@ -451,18 +462,12 @@ bool SymbolFileBreakpad::ParseUnwindRow(llvm::StringRef unwind_rules, return false; } - ArchSpec arch = m_obj_file->GetArchitecture(); - StreamString dwarf(Stream::eBinary, arch.GetAddressByteSize(), - arch.GetByteOrder()); - ToDWARF(*rhs, dwarf); - uint8_t *saved = m_allocator.Allocate<uint8_t>(dwarf.GetSize()); - std::memcpy(saved, dwarf.GetData(), dwarf.GetSize()); - + llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*rhs); if (lhs == ".cfa") { - row.GetCFAValue().SetIsDWARFExpression(saved, dwarf.GetSize()); + row.GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size()); } else if (const RegisterInfo *info = ResolveRegisterOrRA(resolver, lhs)) { UnwindPlan::Row::RegisterLocation loc; - loc.SetIsDWARFExpression(saved, dwarf.GetSize()); + loc.SetIsDWARFExpression(saved.data(), saved.size()); row.SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc); } else LLDB_LOG(log, "Invalid register `{0}` in unwind rule.", lhs); @@ -478,31 +483,40 @@ UnwindPlanSP SymbolFileBreakpad::GetUnwindPlan(const Address &address, const RegisterInfoResolver &resolver) { ParseUnwindData(); - const UnwindMap::Entry *entry = - m_unwind_data->FindEntryThatContains(address.GetFileAddress()); - if (!entry) - return nullptr; + if (auto *entry = + m_unwind_data->cfi.FindEntryThatContains(address.GetFileAddress())) + return ParseCFIUnwindPlan(entry->data, resolver); + if (auto *entry = + m_unwind_data->win.FindEntryThatContains(address.GetFileAddress())) + return ParseWinUnwindPlan(entry->data, resolver); + return nullptr; +} +UnwindPlanSP +SymbolFileBreakpad::ParseCFIUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver) { addr_t base = GetBaseFileAddress(); if (base == LLDB_INVALID_ADDRESS) return nullptr; - LineIterator It(*m_obj_file, Record::StackCFI, entry->data), End(*m_obj_file); + LineIterator It(*m_objfile_sp, Record::StackCFI, bookmark), + End(*m_objfile_sp); llvm::Optional<StackCFIRecord> init_record = StackCFIRecord::parse(*It); - assert(init_record.hasValue()); - assert(init_record->Size.hasValue()); + assert(init_record.hasValue() && init_record->Size.hasValue() && + "Record already parsed successfully in ParseUnwindData!"); auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB); plan_sp->SetSourceName("breakpad STACK CFI"); plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo); plan_sp->SetSourcedFromCompiler(eLazyBoolYes); plan_sp->SetPlanValidAddressRange( AddressRange(base + init_record->Address, *init_record->Size, - m_obj_file->GetModule()->GetSectionList())); + m_objfile_sp->GetModule()->GetSectionList())); auto row_sp = std::make_shared<UnwindPlan::Row>(); row_sp->SetOffset(0); - if (!ParseUnwindRow(init_record->UnwindRules, resolver, *row_sp)) + if (!ParseCFIUnwindRow(init_record->UnwindRules, resolver, *row_sp)) return nullptr; plan_sp->AppendRow(row_sp); for (++It; It != End; ++It) { @@ -514,19 +528,107 @@ SymbolFileBreakpad::GetUnwindPlan(const Address &address, row_sp = std::make_shared<UnwindPlan::Row>(*row_sp); row_sp->SetOffset(record->Address - init_record->Address); - if (!ParseUnwindRow(record->UnwindRules, resolver, *row_sp)) + if (!ParseCFIUnwindRow(record->UnwindRules, resolver, *row_sp)) return nullptr; plan_sp->AppendRow(row_sp); } return plan_sp; } -SymbolVendor &SymbolFileBreakpad::GetSymbolVendor() { - return *m_obj_file->GetModule()->GetSymbolVendor(); +UnwindPlanSP +SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); + addr_t base = GetBaseFileAddress(); + if (base == LLDB_INVALID_ADDRESS) + return nullptr; + + LineIterator It(*m_objfile_sp, Record::StackWin, bookmark); + llvm::Optional<StackWinRecord> record = StackWinRecord::parse(*It); + assert(record.hasValue() && + "Record already parsed successfully in ParseUnwindData!"); + + auto plan_sp = std::make_shared<UnwindPlan>(lldb::eRegisterKindLLDB); + plan_sp->SetSourceName("breakpad STACK WIN"); + plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo); + plan_sp->SetSourcedFromCompiler(eLazyBoolYes); + plan_sp->SetPlanValidAddressRange( + AddressRange(base + record->RVA, record->CodeSize, + m_objfile_sp->GetModule()->GetSectionList())); + + auto row_sp = std::make_shared<UnwindPlan::Row>(); + row_sp->SetOffset(0); + + llvm::BumpPtrAllocator node_alloc; + std::vector<std::pair<llvm::StringRef, postfix::Node *>> program = + postfix::ParseFPOProgram(record->ProgramString, node_alloc); + + if (program.empty()) { + LLDB_LOG(log, "Invalid unwind rule: {0}.", record->ProgramString); + return nullptr; + } + auto it = program.begin(); + const auto &symbol_resolver = + [&](postfix::SymbolNode &symbol) -> postfix::Node * { + llvm::StringRef name = symbol.GetName(); + for (const auto &rule : llvm::make_range(program.begin(), it)) { + if (rule.first == name) + return rule.second; + } + if (const RegisterInfo *info = ResolveRegister(resolver, name)) + return postfix::MakeNode<postfix::RegisterNode>( + node_alloc, info->kinds[eRegisterKindLLDB]); + return nullptr; + }; + + // We assume the first value will be the CFA. It is usually called T0, but + // clang will use T1, if it needs to realign the stack. + auto *symbol = llvm::dyn_cast<postfix::SymbolNode>(it->second); + if (symbol && symbol->GetName() == ".raSearch") { + row_sp->GetCFAValue().SetRaSearch(record->LocalSize + + record->SavedRegisterSize); + } else { + if (!postfix::ResolveSymbols(it->second, symbol_resolver)) { + LLDB_LOG(log, "Resolving symbols in `{0}` failed.", + record->ProgramString); + return nullptr; + } + llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*it->second); + row_sp->GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size()); + } + + // Replace the node value with InitialValueNode, so that subsequent + // expressions refer to the CFA value instead of recomputing the whole + // expression. + it->second = postfix::MakeNode<postfix::InitialValueNode>(node_alloc); + + + // Now process the rest of the assignments. + for (++it; it != program.end(); ++it) { + const RegisterInfo *info = ResolveRegister(resolver, it->first); + // It is not an error if the resolution fails because the program may + // contain temporary variables. + if (!info) + continue; + if (!postfix::ResolveSymbols(it->second, symbol_resolver)) { + LLDB_LOG(log, "Resolving symbols in `{0}` failed.", + record->ProgramString); + return nullptr; + } + + llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*it->second); + UnwindPlan::Row::RegisterLocation loc; + loc.SetIsDWARFExpression(saved.data(), saved.size()); + row_sp->SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc); + } + + plan_sp->AppendRow(row_sp); + return plan_sp; } addr_t SymbolFileBreakpad::GetBaseFileAddress() { - return m_obj_file->GetModule() + return m_objfile_sp->GetModule() ->GetObjectFile() ->GetBaseAddress() .GetFileAddress(); @@ -569,8 +671,8 @@ void SymbolFileBreakpad::ParseCUData() { // We shall create one compile unit for each FUNC record. So, count the number // of FUNC records, and store them in m_cu_data, together with their ranges. - for (LineIterator It(*m_obj_file, Record::Func), End(*m_obj_file); It != End; - ++It) { + for (LineIterator It(*m_objfile_sp, Record::Func), End(*m_objfile_sp); + It != End; ++It) { if (auto record = FuncRecord::parse(*It)) { m_cu_data->Append(CompUnitMap::Entry(base + record->Address, record->Size, CompUnitData(It.GetBookmark()))); @@ -589,7 +691,7 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, "How did we create compile units without a base address?"); SupportFileMap map; - data.line_table_up = llvm::make_unique<LineTable>(&cu); + data.line_table_up = std::make_unique<LineTable>(&cu); std::unique_ptr<LineSequence> line_seq_up( data.line_table_up->CreateLineSequenceContainer()); llvm::Optional<addr_t> next_addr; @@ -603,7 +705,8 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, line_seq_up->Clear(); }; - LineIterator It(*m_obj_file, Record::Func, data.bookmark), End(*m_obj_file); + LineIterator It(*m_objfile_sp, Record::Func, data.bookmark), + End(*m_objfile_sp); assert(Record::classify(*It) == Record::Func); for (++It; It != End; ++It) { auto record = LineRecord::parse(*It); @@ -631,8 +734,8 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, void SymbolFileBreakpad::ParseUnwindData() { if (m_unwind_data) return; - m_unwind_data.emplace(); + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS); addr_t base = GetBaseFileAddress(); if (base == LLDB_INVALID_ADDRESS) { @@ -640,14 +743,24 @@ void SymbolFileBreakpad::ParseUnwindData() { "of object file."); } - for (LineIterator It(*m_obj_file, Record::StackCFI), End(*m_obj_file); + for (LineIterator It(*m_objfile_sp, Record::StackCFI), End(*m_objfile_sp); It != End; ++It) { if (auto record = StackCFIRecord::parse(*It)) { if (record->Size) - m_unwind_data->Append(UnwindMap::Entry( + m_unwind_data->cfi.Append(UnwindMap::Entry( base + record->Address, *record->Size, It.GetBookmark())); } else LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It); } - m_unwind_data->Sort(); + m_unwind_data->cfi.Sort(); + + for (LineIterator It(*m_objfile_sp, Record::StackWin), End(*m_objfile_sp); + It != End; ++It) { + if (auto record = StackWinRecord::parse(*It)) { + m_unwind_data->win.Append(UnwindMap::Entry( + base + record->RVA, record->CodeSize, It.GetBookmark())); + } else + LLDB_LOG(log, "Failed to parse: {0}. Skipping record.", *It); + } + m_unwind_data->win.Sort(); } diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 8a0b7645fd0a..a10138cdf92f 100644 --- a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -12,6 +12,7 @@ #include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/PostfixExpression.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/UnwindPlan.h" @@ -31,12 +32,13 @@ public: return "Breakpad debug symbol file reader."; } - static SymbolFile *CreateInstance(ObjectFile *obj_file) { - return new SymbolFileBreakpad(obj_file); + static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp) { + return new SymbolFileBreakpad(std::move(objfile_sp)); } // Constructors and Destructors - SymbolFileBreakpad(ObjectFile *object_file) : SymbolFile(object_file) {} + SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)) {} ~SymbolFileBreakpad() override {} @@ -46,10 +48,6 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override { return lldb::eLanguageTypeUnknown; } @@ -72,12 +70,10 @@ public: size_t ParseBlocksRecursive(Function &func) override { return 0; } - uint32_t FindGlobalVariables(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - uint32_t max_matches, - VariableList &variables) override { - return 0; - } + void FindGlobalVariables(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + VariableList &variables) override {} size_t ParseVariablesForContext(const SymbolContext &sc) override { return 0; @@ -99,31 +95,30 @@ public: lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; - size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, - TypeList &type_list) override { - return 0; - } + void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, + TypeList &type_list) override {} - uint32_t FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, - bool include_inlines, bool append, - SymbolContextList &sc_list) override; + void FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, SymbolContextList &sc_list) override; - uint32_t FindFunctions(const RegularExpression ®ex, bool include_inlines, - bool append, SymbolContextList &sc_list) override; + void FindFunctions(const RegularExpression ®ex, bool include_inlines, + SymbolContextList &sc_list) override; - uint32_t FindTypes(ConstString name, - const CompilerDeclContext *parent_decl_ctx, bool append, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) override; - size_t FindTypes(const std::vector<CompilerContext> &context, bool append, - TypeMap &types) override; + void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, + TypeMap &types) override; - TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override { - return nullptr; + llvm::Expected<TypeSystem &> + GetTypeSystemForLanguage(lldb::LanguageType language) override { + return llvm::make_error<llvm::StringError>( + "SymbolFileBreakpad does not support GetTypeSystemForLanguage", + llvm::inconvertibleErrorCode()); } CompilerDeclContext @@ -134,6 +129,8 @@ public: void AddSymbols(Symtab &symtab) override; + llvm::Expected<lldb::addr_t> GetParameterStackSize(Symbol &symbol) override; + lldb::UnwindPlanSP GetUnwindPlan(const Address &address, const RegisterInfoResolver &resolver) override; @@ -196,15 +193,22 @@ private: }; - SymbolVendor &GetSymbolVendor(); + uint32_t CalculateNumCompileUnits() override; + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + lldb::addr_t GetBaseFileAddress(); void ParseFileRecords(); void ParseCUData(); void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data); void ParseUnwindData(); - bool ParseUnwindRow(llvm::StringRef unwind_rules, - const RegisterInfoResolver &resolver, - UnwindPlan::Row &row); + llvm::ArrayRef<uint8_t> SaveAsDWARF(postfix::Node &node); + lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver); + bool ParseCFIUnwindRow(llvm::StringRef unwind_rules, + const RegisterInfoResolver &resolver, + UnwindPlan::Row &row); + lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark, + const RegisterInfoResolver &resolver); using CompUnitMap = RangeDataVector<lldb::addr_t, lldb::addr_t, CompUnitData>; @@ -212,7 +216,11 @@ private: llvm::Optional<CompUnitMap> m_cu_data; using UnwindMap = RangeDataVector<lldb::addr_t, lldb::addr_t, Bookmark>; - llvm::Optional<UnwindMap> m_unwind_data; + struct UnwindData { + UnwindMap cfi; + UnwindMap win; + }; + llvm::Optional<UnwindData> m_unwind_data; llvm::BumpPtrAllocator m_allocator; }; diff --git a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index 9ae047da1325..0a5073b8cd9e 100644 --- a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -21,30 +21,30 @@ std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create( Module &module, DWARFDataExtractor apple_names, DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types, DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) { - auto apple_names_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_names_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_names, debug_str, ".apple_names"); if (!apple_names_table_up->IsValid()) apple_names_table_up.reset(); auto apple_namespaces_table_up = - llvm::make_unique<DWARFMappedHash::MemoryTable>( + std::make_unique<DWARFMappedHash::MemoryTable>( apple_namespaces, debug_str, ".apple_namespaces"); if (!apple_namespaces_table_up->IsValid()) apple_namespaces_table_up.reset(); - auto apple_types_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_types_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_types, debug_str, ".apple_types"); if (!apple_types_table_up->IsValid()) apple_types_table_up.reset(); - auto apple_objc_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( + auto apple_objc_table_up = std::make_unique<DWARFMappedHash::MemoryTable>( apple_objc, debug_str, ".apple_objc"); if (!apple_objc_table_up->IsValid()) apple_objc_table_up.reset(); if (apple_names_table_up || apple_names_table_up || apple_types_table_up || apple_objc_table_up) - return llvm::make_unique<AppleDWARFIndex>( + return std::make_unique<AppleDWARFIndex>( module, std::move(apple_names_table_up), std::move(apple_namespaces_table_up), std::move(apple_types_table_up), std::move(apple_objc_table_up)); @@ -110,6 +110,7 @@ void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, const bool has_qualified_name_hash = m_apple_types_up->GetHeader().header_data.ContainsAtom( DWARFMappedHash::eAtomTypeQualNameHash); + const ConstString type_name(context[0].name); const dw_tag_t tag = context[0].tag; if (has_tag && has_qualified_name_hash) { @@ -119,12 +120,32 @@ void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( type_name.GetStringRef(), tag, qualified_name_hash, offsets); - } else if (has_tag) { + return; + } + + if (has_tag) { + // When searching for a scoped type (for example, + // "std::vector<int>::const_iterator") searching for the innermost + // name alone ("const_iterator") could yield many false + // positives. By searching for the parent type ("vector<int>") + // first we can avoid extracting type DIEs from object files that + // would fail the filter anyway. + if (!has_qualified_name_hash && (context.GetSize() > 1) && + (context[1].tag == DW_TAG_class_type || + context[1].tag == DW_TAG_structure_type)) { + DIEArray class_matches; + m_apple_types_up->FindByName(context[1].name, class_matches); + if (class_matches.empty()) + return; + } + if (log) m_module.LogMessage(log, "FindByNameAndTag()"); m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); - } else - m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); + return; + } + + m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); } void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index e7927b31b9c3..7ee4727cde91 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -28,7 +28,6 @@ public: virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, - lldb_private::Log *log, bool *type_is_new_ptr) = 0; virtual lldb_private::Function * @@ -48,8 +47,8 @@ public: virtual lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) = 0; - virtual std::vector<DWARFDIE> - GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) = 0; + virtual void EnsureAllDIEsInDeclContextHaveBeenParsed( + lldb_private::CompilerDeclContext decl_context) = 0; static llvm::Optional<lldb_private::SymbolFile::ArrayInfo> ParseChildArrayInfo(const DWARFDIE &parent_die, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index b85ab54a10d3..636e6032b877 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -9,7 +9,6 @@ #include <stdlib.h> #include "DWARFASTParserClang.h" -#include "DWARFDIE.h" #include "DWARFDebugInfo.h" #include "DWARFDeclContext.h" #include "DWARFDefines.h" @@ -28,7 +27,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Target/Language.h" @@ -144,23 +143,27 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { // If this type comes from a Clang module, look in the DWARF section // of the pcm file in the module cache. Clang generates DWO skeleton // units as breadcrumbs to find them. - std::vector<CompilerContext> decl_context; + llvm::SmallVector<CompilerContext, 4> decl_context; die.GetDeclContext(decl_context); TypeMap dwo_types; - if (!dwo_module_sp->GetSymbolVendor()->FindTypes(decl_context, true, - dwo_types)) { + // The type in the Clang module must have the same language as the current CU. + LanguageSet languages; + languages.Insert(die.GetCU()->GetLanguageType()); + dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, dwo_types); + if (dwo_types.Empty()) { if (!IsClangModuleFwdDecl(die)) return TypeSP(); - // Since this this type is defined in one of the Clang modules imported by - // this symbol file, search all of them. + // Since this type is defined in one of the Clang modules imported + // by this symbol file, search all of them. auto &sym_file = die.GetCU()->GetSymbolFileDWARF(); for (const auto &name_module : sym_file.getExternalTypeModules()) { if (!name_module.second) continue; - SymbolVendor *sym_vendor = name_module.second->GetSymbolVendor(); - if (sym_vendor->FindTypes(decl_context, true, dwo_types)) + name_module.second->GetSymbolFile()->FindTypes(decl_context, + languages, dwo_types); + if (dwo_types.GetSize()) break; } } @@ -188,7 +191,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward)); - dwarf->GetTypeList()->Insert(type_sp); + dwarf->GetTypeList().Insert(type_sp); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type); if (tag_decl) @@ -228,42 +231,7 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer, } } -namespace { -/// Parsed form of all attributes that are relevant for type reconstruction. -/// Some attributes are relevant for all kinds of types (declaration), while -/// others are only meaningful to a specific type (is_virtual) -struct ParsedTypeAttributes { - explicit ParsedTypeAttributes(const DWARFDIE &die); - - AccessType accessibility = eAccessNone; - bool is_artificial = false; - bool is_complete_objc_class = false; - bool is_explicit = false; - bool is_forward_declaration = false; - bool is_inline = false; - bool is_scoped_enum = false; - bool is_vector = false; - bool is_virtual = false; - clang::StorageClass storage = clang::SC_None; - const char *mangled_name = nullptr; - ConstString name; - Declaration decl; - DWARFDIE object_pointer; - DWARFFormValue abstract_origin; - DWARFFormValue containing_type; - DWARFFormValue signature; - DWARFFormValue specification; - DWARFFormValue type; - LanguageType class_language = eLanguageTypeUnknown; - llvm::Optional<uint64_t> byte_size; - size_t calling_convention = llvm::dwarf::DW_CC_normal; - uint32_t bit_stride = 0; - uint32_t byte_stride = 0; - uint32_t encoding = 0; -}; -} // namespace - -ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die) { +ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) { DWARFAttributes attributes; size_t num_attributes = die.GetAttributes(attributes); for (size_t i = 0; i < num_attributes; ++i) { @@ -390,13 +358,17 @@ static std::string GetUnitName(const DWARFDIE &die) { } TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, - const DWARFDIE &die, Log *log, + const DWARFDIE &die, bool *type_is_new_ptr) { if (type_is_new_ptr) *type_is_new_ptr = false; if (!die) return nullptr; + + Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | + DWARF_LOG_LOOKUPS)); + SymbolFileDWARF *dwarf = die.GetDWARF(); if (log) { DWARFDIE context_die; @@ -420,11 +392,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, // Set a bit that lets us know that we are currently parsing this dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - ParsedTypeAttributes attrs(die); + ParsedDWARFTypeAttributes attrs(die); if (DWARFDIE signature_die = attrs.signature.Reference()) { if (TypeSP type_sp = - ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) { + ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) { dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); if (clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE(signature_die)) @@ -434,7 +406,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, return nullptr; } - TypeList *type_list = dwarf->GetTypeList(); if (type_is_new_ptr) *type_is_new_ptr = true; @@ -562,7 +533,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, bool function_type_is_new_pointer; TypeSP lldb_function_type_sp = ParseTypeFromDWARF( - sc, function_type, log, &function_type_is_new_pointer); + sc, function_type, &function_type_is_new_pointer); if (lldb_function_type_sp) { clang_type = m_ast.CreateBlockPointerType( @@ -660,370 +631,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: { - // UniqueDWARFASTType is large, so don't create a local variables on - // the stack, put it on the heap. This function is often called - // recursively and clang isn't good and sharing the stack space for - // variables in different blocks. - std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_up( - new UniqueDWARFASTType()); - - ConstString unique_typename(attrs.name); - Declaration unique_decl(attrs.decl); - - if (attrs.name) { - if (Language::LanguageIsCPlusPlus(cu_language)) { - // For C++, we rely solely upon the one definition rule that says - // only one thing can exist at a given decl context. We ignore the - // file and line that things are declared on. - std::string qualified_name; - if (die.GetQualifiedName(qualified_name)) - unique_typename = ConstString(qualified_name); - unique_decl.Clear(); - } - - if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), - *unique_ast_entry_up)) { - type_sp = unique_ast_entry_up->m_type_sp; - if (type_sp) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - } - - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - int tag_decl_kind = -1; - AccessType default_accessibility = eAccessNone; - if (tag == DW_TAG_structure_type) { - tag_decl_kind = clang::TTK_Struct; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_union_type) { - tag_decl_kind = clang::TTK_Union; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_class_type) { - tag_decl_kind = clang::TTK_Class; - default_accessibility = eAccessPrivate; - } - - if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && - !die.HasChildren() && cu_language == eLanguageTypeObjC) { - // Work around an issue with clang at the moment where forward - // declarations for objective C classes are emitted as: - // DW_TAG_structure_type [2] - // DW_AT_name( "ForwardObjcClass" ) - // DW_AT_byte_size( 0x00 ) - // DW_AT_decl_file( "..." ) - // DW_AT_decl_line( 1 ) - // - // Note that there is no DW_AT_declaration and there are no children, - // and the byte size is zero. - attrs.is_forward_declaration = true; - } - - if (attrs.class_language == eLanguageTypeObjC || - attrs.class_language == eLanguageTypeObjC_plus_plus) { - if (!attrs.is_complete_objc_class && - die.Supports_DW_AT_APPLE_objc_complete_type()) { - // We have a valid eSymbolTypeObjCClass class symbol whose name - // matches the current objective C class that we are trying to find - // and this DIE isn't the complete definition (we checked - // is_complete_objc_class above and know it is false), so the real - // definition is in here somewhere - type_sp = - dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( - die, attrs.name, true); - } - } - - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " - "incomplete objc type, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - } - - if (attrs.is_forward_declaration) { - // We have a forward declaration to a type and we need to try and - // find a full declaration. We look in the current type index just in - // case we have a forward declaration followed by an actual - // declarations in the DWARF. If this fails, we need to look - // elsewhere... - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, trying to find complete type", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - - // See if the type comes from a DWO module and if so, track down that - // type. - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, - // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, see - // if we have a declaration anywhere else... - type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } - } - - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString(), - type_sp->GetID()); - } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = - GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; - } - } - assert(tag_decl_kind != -1); - bool clang_type_was_created = false; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, nullptr); - - // If your decl context is a record that was imported from another - // AST context (in the gmodules case), we need to make sure the type - // backing the Decl is complete before adding children to it. This is - // not an issue in the non-gmodules case because the debug info will - // always contain a full definition of parent types in that case. - CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, - attrs.name.GetCString()); - - if (attrs.accessibility == eAccessNone && decl_ctx) { - // Check the decl context that contains this class/struct/union. If - // it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); - if (DeclKindIsCXXClass(containing_decl_kind)) - attrs.accessibility = default_accessibility; - } - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); - - if (attrs.name.GetStringRef().contains('<')) { - ClangASTContext::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, - attrs.name.GetCString(), - tag_decl_kind, template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast<void *>(this), die.GetOffset(), - DW_TAG_value_to_name(tag), attrs.name.GetCString()); - } - return TypeSP(); - } - - clang::ClassTemplateSpecializationDecl *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, class_template_decl, tag_decl_kind, - template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; - - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } - } - - if (!clang_type_was_created) { - clang_type_was_created = true; - clang_type = m_ast.CreateRecordType( - decl_ctx, attrs.accessibility, attrs.name.GetCString(), - tag_decl_kind, attrs.class_language, &metadata); - } - } - - // Store a forward declaration to this class type in case any - // parameters in any class methods need it for the clang types for - // function prototypes. - LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name, - attrs.byte_size, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, &attrs.decl, clang_type, - Type::eResolveStateForward); - - type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); - - // Add our type to the unique type map so we don't end up creating many - // copies of the same type over and over in the ASTContext for our - // module - unique_ast_entry_up->m_type_sp = type_sp; - unique_ast_entry_up->m_die = die; - unique_ast_entry_up->m_declaration = unique_decl; - unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); - dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, - *unique_ast_entry_up); - - if (attrs.is_forward_declaration && die.HasChildren()) { - // Check to see if the DIE actually has a definition, some version of - // GCC will - // emit DIEs with DW_AT_declaration set to true, but yet still have - // subprogram, members, or inheritance, so we can't trust it - DWARFDIE child_die = die.GetFirstChild(); - while (child_die) { - switch (child_die.Tag()) { - case DW_TAG_inheritance: - case DW_TAG_subprogram: - case DW_TAG_member: - case DW_TAG_APPLE_property: - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_enumeration_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - child_die.Clear(); - attrs.is_forward_declaration = false; - break; - default: - child_die = child_die.GetSibling(); - break; - } - } - } - - if (!attrs.is_forward_declaration) { - // Always start the definition for a class type so that if the class - // has child classes or types that require the class to be created - // for use as their decl contexts the class will be ready to accept - // these child definitions. - if (!die.HasChildren()) { - // No children for this struct/union/class, lets finish it - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), attrs.name.GetCString()); - } - - if (tag == DW_TAG_structure_type) // this only applies in C - { - clang::RecordDecl *record_decl = - ClangASTContext::GetAsRecordDecl(clang_type); - - if (record_decl) { - GetClangASTImporter().InsertRecordDecl( - record_decl, ClangASTImporter::LayoutInfo()); - } - } - } else if (clang_type_was_created) { - // Start the definition if the class is not objective C since the - // underlying decls respond to isCompleteDefinition(). Objective - // C decls don't respond to isCompleteDefinition() so we can't - // start the declaration definition right away. For C++ - // class/union/structs we want to start the definition in case the - // class is needed as the declaration context for a contained class - // or type without the need to complete that type.. - - if (attrs.class_language != eLanguageTypeObjC && - attrs.class_language != eLanguageTypeObjC_plus_plus) - ClangASTContext::StartTagDeclarationDefinition(clang_type); - - // Leave this as a forward declaration until we need to know the - // details of the type. lldb_private::Type will automatically call - // the SymbolFile virtual function - // "SymbolFileDWARF::CompleteType(Type *)" When the definition - // needs to be defined. - assert(!dwarf->GetForwardDeclClangTypeToDie().count( - ClangUtil::RemoveFastQualifiers(clang_type) - .GetOpaqueQualType()) && - "Type already in the forward declaration map!"); - // Can't assume m_ast.GetSymbolFile() is actually a - // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple - // binaries. - dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = - clang_type.GetOpaqueQualType(); - dwarf->GetForwardDeclClangTypeToDie() - [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = - die.GetID(); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); - } - } - - // If we made a clang type, set the trivial abi if applicable: We only - // do this for pass by value - which implies the Trivial ABI. There - // isn't a way to assert that something that would normally be pass by - // value is pass by reference, so we ignore that attribute if set. - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) { - record_decl->setHasTrivialSpecialMemberForCall(); - } - } - - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) - record_decl->setArgPassingRestrictions( - clang::RecordDecl::APK_CannotPassInRegs); - } - - } break; + assert((!type_sp && !clang_type) && + "Did not expect partially computed structure-like type"); + TypeSP struct_like_type_sp = ParseStructureLikeDIE(die, attrs); + return UpdateSymbolContextScopeForType(sc, die, struct_like_type_sp); + } case DW_TAG_enumeration_type: { if (attrs.is_forward_declaration) { @@ -1395,8 +1007,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, is_attr_used, attrs.is_artificial); type_handled = cxx_method_decl != NULL; + // Artificial methods are always handled even when we + // don't create a new declaration for them. + type_handled |= attrs.is_artificial; - if (type_handled) { + if (cxx_method_decl) { LinkDeclContextToDIE( ClangASTContext::GetAsDeclContext(cxx_method_decl), die); @@ -1407,12 +1022,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, if (!object_pointer_name.empty()) { metadata.SetObjectPtrName( object_pointer_name.c_str()); - if (log) - log->Printf( - "Setting object pointer name: %s on method " - "object %p.\n", - object_pointer_name.c_str(), - static_cast<void *>(cxx_method_decl)); + LLDB_LOGF(log, + "Setting object pointer name: %s on method " + "object %p.\n", + object_pointer_name.c_str(), + static_cast<void *>(cxx_method_decl)); } m_ast.SetMetadata(cxx_method_decl, metadata); } else { @@ -1520,11 +1134,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, if (!object_pointer_name.empty()) { metadata.SetObjectPtrName(object_pointer_name.c_str()); - if (log) - log->Printf("Setting object pointer name: %s on function " - "object %p.", - object_pointer_name.c_str(), - static_cast<void *>(function_decl)); + LLDB_LOGF(log, + "Setting object pointer name: %s on function " + "object %p.", + object_pointer_name.c_str(), + static_cast<void *>(function_decl)); } m_ast.SetMetadata(function_decl, metadata); } @@ -1651,31 +1265,418 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, break; } - if (type_sp.get()) { - DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); - dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + // TODO: We should consider making the switch above exhaustive to simplify + // control flow in ParseTypeFromDWARF. Then, we could simply replace this + // return statement with a call to llvm_unreachable. + return UpdateSymbolContextScopeForType(sc, die, type_sp); +} + +TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType( + const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) { + if (!type_sp) + return type_sp; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + TypeList &type_list = dwarf->GetTypeList(); + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit || + sc_parent_tag == DW_TAG_partial_unit) { + symbol_context_scope = sc.comp_unit; + } else if (sc.function != NULL && sc_parent_die) { + symbol_context_scope = + sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; + } else { + symbol_context_scope = sc.module_sp.get(); + } + + if (symbol_context_scope != NULL) + type_sp->SetSymbolContextScope(symbol_context_scope); - SymbolContextScope *symbol_context_scope = NULL; - if (sc_parent_tag == DW_TAG_compile_unit || - sc_parent_tag == DW_TAG_partial_unit) { - symbol_context_scope = sc.comp_unit; - } else if (sc.function != NULL && sc_parent_die) { - symbol_context_scope = - sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); - if (symbol_context_scope == NULL) - symbol_context_scope = sc.function; - } else - symbol_context_scope = sc.module_sp.get(); + // We are ready to put this type into the uniqued list up at the module + // level. + type_list.Insert(type_sp); - if (symbol_context_scope != NULL) { - type_sp->SetSymbolContextScope(symbol_context_scope); + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; +} + +TypeSP +DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs) { + TypeSP type_sp; + CompilerType clang_type; + const dw_tag_t tag = die.Tag(); + SymbolFileDWARF *dwarf = die.GetDWARF(); + LanguageType cu_language = die.GetLanguage(); + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_TYPE_COMPLETION | + DWARF_LOG_LOOKUPS); + + // UniqueDWARFASTType is large, so don't create a local variables on the + // stack, put it on the heap. This function is often called recursively and + // clang isn't good at sharing the stack space for variables in different + // blocks. + auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>(); + + ConstString unique_typename(attrs.name); + Declaration unique_decl(attrs.decl); + + if (attrs.name) { + if (Language::LanguageIsCPlusPlus(cu_language)) { + // For C++, we rely solely upon the one definition rule that says + // only one thing can exist at a given decl context. We ignore the + // file and line that things are declared on. + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + unique_typename = ConstString(qualified_name); + unique_decl.Clear(); + } + + if (dwarf->GetUniqueDWARFASTTypeMap().Find( + unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1), + *unique_ast_entry_up)) { + type_sp = unique_ast_entry_up->m_type_sp; + if (type_sp) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + LinkDeclContextToDIE( + GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die); + return type_sp; + } } + } - // We are ready to put this type into the uniqued list up at the module - // level - type_list->Insert(type_sp); + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + int tag_decl_kind = -1; + AccessType default_accessibility = eAccessNone; + if (tag == DW_TAG_structure_type) { + tag_decl_kind = clang::TTK_Struct; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_union_type) { + tag_decl_kind = clang::TTK_Union; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_class_type) { + tag_decl_kind = clang::TTK_Class; + default_accessibility = eAccessPrivate; + } - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name && + !die.HasChildren() && cu_language == eLanguageTypeObjC) { + // Work around an issue with clang at the moment where forward + // declarations for objective C classes are emitted as: + // DW_TAG_structure_type [2] + // DW_AT_name( "ForwardObjcClass" ) + // DW_AT_byte_size( 0x00 ) + // DW_AT_decl_file( "..." ) + // DW_AT_decl_line( 1 ) + // + // Note that there is no DW_AT_declaration and there are no children, + // and the byte size is zero. + attrs.is_forward_declaration = true; + } + + if (attrs.class_language == eLanguageTypeObjC || + attrs.class_language == eLanguageTypeObjC_plus_plus) { + if (!attrs.is_complete_objc_class && + die.Supports_DW_AT_APPLE_objc_complete_type()) { + // We have a valid eSymbolTypeObjCClass class symbol whose name + // matches the current objective C class that we are trying to find + // and this DIE isn't the complete definition (we checked + // is_complete_objc_class above and know it is false), so the real + // definition is in here somewhere + type_sp = + dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( + die, attrs.name, true); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " + "incomplete objc type, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } + + if (attrs.is_forward_declaration) { + // We have a forward declaration to a type and we need to try and + // find a full declaration. We look in the current type index just in + // case we have a forward declaration followed by an actual + // declarations in the DWARF. If this fails, we need to look + // elsewhere... + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, trying to find complete type", + static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag), + attrs.name.GetCString()); + } + + // See if the type comes from a DWO module and if so, track down that + // type. + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, + // type_name_const_str); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, see + // if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString(), + type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + assert(tag_decl_kind != -1); + bool clang_type_was_created = false; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + clang::DeclContext *decl_ctx = + GetClangDeclContextContainingDIE(die, nullptr); + + // If your decl context is a record that was imported from another + // AST context (in the gmodules case), we need to make sure the type + // backing the Decl is complete before adding children to it. This is + // not an issue in the non-gmodules case because the debug info will + // always contain a full definition of parent types in that case. + CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, + attrs.name.GetCString()); + + if (attrs.accessibility == eAccessNone && decl_ctx) { + // Check the decl context that contains this class/struct/union. If + // it is a class we must give it an accessibility. + const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + if (DeclKindIsCXXClass(containing_decl_kind)) + attrs.accessibility = default_accessibility; + } + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); + + if (attrs.name.GetStringRef().contains('<')) { + ClangASTContext::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, + template_param_infos); + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), attrs.name.GetCString()); + } + return TypeSP(); + } + + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, class_template_decl, tag_decl_kind, + template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType( + class_specialization_decl); + clang_type_was_created = true; + + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); + } + } + + if (!clang_type_was_created) { + clang_type_was_created = true; + clang_type = m_ast.CreateRecordType( + decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, + attrs.class_language, &metadata); + } + } + + // Store a forward declaration to this class type in case any + // parameters in any class methods need it for the clang types for + // function prototypes. + LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); + type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name, + attrs.byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &attrs.decl, + clang_type, Type::eResolveStateForward); + + type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class); + + // Add our type to the unique type map so we don't end up creating many + // copies of the same type over and over in the ASTContext for our + // module + unique_ast_entry_up->m_type_sp = type_sp; + unique_ast_entry_up->m_die = die; + unique_ast_entry_up->m_declaration = unique_decl; + unique_ast_entry_up->m_byte_size = attrs.byte_size.getValueOr(0); + dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, + *unique_ast_entry_up); + + if (attrs.is_forward_declaration && die.HasChildren()) { + // Check to see if the DIE actually has a definition, some version of + // GCC will + // emit DIEs with DW_AT_declaration set to true, but yet still have + // subprogram, members, or inheritance, so we can't trust it + DWARFDIE child_die = die.GetFirstChild(); + while (child_die) { + switch (child_die.Tag()) { + case DW_TAG_inheritance: + case DW_TAG_subprogram: + case DW_TAG_member: + case DW_TAG_APPLE_property: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + child_die.Clear(); + attrs.is_forward_declaration = false; + break; + default: + child_die = child_die.GetSibling(); + break; + } + } + } + + if (!attrs.is_forward_declaration) { + // Always start the definition for a class type so that if the class + // has child classes or types that require the class to be created + // for use as their decl contexts the class will be ready to accept + // these child definitions. + if (!die.HasChildren()) { + // No children for this struct/union/class, lets finish it + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), attrs.name.GetCString()); + } + + if (tag == DW_TAG_structure_type) // this only applies in C + { + clang::RecordDecl *record_decl = + ClangASTContext::GetAsRecordDecl(clang_type); + + if (record_decl) { + GetClangASTImporter().InsertRecordDecl( + record_decl, ClangASTImporter::LayoutInfo()); + } + } + } else if (clang_type_was_created) { + // Start the definition if the class is not objective C since the + // underlying decls respond to isCompleteDefinition(). Objective + // C decls don't respond to isCompleteDefinition() so we can't + // start the declaration definition right away. For C++ + // class/union/structs we want to start the definition in case the + // class is needed as the declaration context for a contained class + // or type without the need to complete that type.. + + if (attrs.class_language != eLanguageTypeObjC && + attrs.class_language != eLanguageTypeObjC_plus_plus) + ClangASTContext::StartTagDeclarationDefinition(clang_type); + + // Leave this as a forward declaration until we need to know the + // details of the type. lldb_private::Type will automatically call + // the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" When the definition + // needs to be defined. + assert(!dwarf->GetForwardDeclClangTypeToDie().count( + ClangUtil::RemoveFastQualifiers(clang_type) + .GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + // Can't assume m_ast.GetSymbolFile() is actually a + // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple + // binaries. + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = + clang_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie() + [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = + die.GetID(); + m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + } + } + + // If we made a clang type, set the trivial abi if applicable: We only + // do this for pass by value - which implies the Trivial ABI. There + // isn't a way to assert that something that would normally be pass by + // value is pass by reference, so we ignore that attribute if set. + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl && record_decl->getDefinition()) { + record_decl->setHasTrivialSpecialMemberForCall(); + } + } + + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) + record_decl->setArgPassingRestrictions( + clang::RecordDecl::APK_CannotPassInRegs); } return type_sp; } @@ -2181,14 +2182,16 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, return false; } -std::vector<DWARFDIE> DWARFASTParserClang::GetDIEForDeclContext( +void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed( lldb_private::CompilerDeclContext decl_context) { - std::vector<DWARFDIE> result; - for (auto it = m_decl_ctx_to_die.find( - (clang::DeclContext *)decl_context.GetOpaqueDeclContext()); - it != m_decl_ctx_to_die.end(); it++) - result.push_back(it->second); - return result; + auto opaque_decl_ctx = + (clang::DeclContext *)decl_context.GetOpaqueDeclContext(); + 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()) + GetClangDeclForDIE(decl); } CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) { @@ -2530,9 +2533,11 @@ bool DWARFASTParserClang::ParseChildMembers( if (DWARFExpression::Evaluate( nullptr, // ExecutionContext * nullptr, // RegisterContext * - module_sp, debug_info_data, die.GetCU(), block_offset, - block_length, eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + module_sp, + DataExtractor(debug_info_data, block_offset, + block_length), + die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, + memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); } @@ -2965,11 +2970,12 @@ bool DWARFASTParserClang::ParseChildMembers( uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate(nullptr, nullptr, module_sp, - debug_info_data, die.GetCU(), - block_offset, block_length, - eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + if (DWARFExpression::Evaluate( + nullptr, nullptr, module_sp, + DataExtractor(debug_info_data, block_offset, + block_length), + die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr, + memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(nullptr).UInt(); } @@ -3270,6 +3276,8 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, array_info.element_orders.push_back(num_elements); } } break; + default: + break; } } return array_info; @@ -3672,11 +3680,11 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (src_size != dst_size) { if (src_size != 0 && dst_size != 0) { - if (log) - log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, " - "but they didn't have the same size (src=%d, dst=%d)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_size, dst_size); + LLDB_LOGF(log, + "warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, " + "but they didn't have the same size (src=%d, dst=%d)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), src_size, + dst_size); } fast_path = false; @@ -3690,12 +3698,12 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); if (src_die.Tag() != dst_die.Tag()) { - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " - "but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_die.GetOffset(), src_die.GetTagAsCString(), - dst_die.GetOffset(), dst_die.GetTagAsCString()); + LLDB_LOGF(log, + "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " + "but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), + src_die.GetOffset(), src_die.GetTagAsCString(), + dst_die.GetOffset(), dst_die.GetTagAsCString()); fast_path = false; } @@ -3706,12 +3714,11 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (src_name == dst_name || (strcmp(src_name, dst_name) == 0)) continue; - if (log) - log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " - "but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", - src_class_die.GetOffset(), dst_class_die.GetOffset(), - src_die.GetOffset(), src_name, dst_die.GetOffset(), - dst_name); + LLDB_LOGF(log, + "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, " + "but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", + src_class_die.GetOffset(), dst_class_die.GetOffset(), + src_die.GetOffset(), src_name, dst_die.GetOffset(), dst_name); fast_path = false; } @@ -3733,32 +3740,31 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x for " - "0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x for " + "0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf( - "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), src_child_type->GetID(), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "uniquing type %p (uid=0x%" PRIx64 + ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } } else { @@ -3778,39 +3784,36 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x " - "for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x " + "for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf("uniquing type %p (uid=0x%" PRIx64 - ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), - src_child_type->GetID(), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF( + log, + "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } else { - if (log) - log->Printf("warning: couldn't find a match for 0x%8.8x", - dst_die.GetOffset()); + LLDB_LOGF(log, "warning: couldn't find a match for 0x%8.8x", + dst_die.GetOffset()); failures.push_back(dst_die); } @@ -3836,32 +3839,31 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; if (src_decl_ctx) { - if (log) - log->Printf("uniquing decl context %p from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_decl_ctx), src_die.GetOffset(), - dst_die.GetOffset()); + LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_decl_ctx), src_die.GetOffset(), + dst_die.GetOffset()); dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die); } else { - if (log) - log->Printf("warning: tried to unique decl context from 0x%8.8x " - "for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique decl context from 0x%8.8x " + "for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; if (src_child_type) { - if (log) - log->Printf( - "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", - static_cast<void *>(src_child_type), src_child_type->GetID(), - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF( + log, + "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", + static_cast<void *>(src_child_type), src_child_type->GetID(), + src_die.GetOffset(), dst_die.GetOffset()); dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; } else { - if (log) - log->Printf("warning: tried to unique lldb_private::Type from " - "0x%8.8x for 0x%8.8x, but none was found", - src_die.GetOffset(), dst_die.GetOffset()); + LLDB_LOGF(log, + "warning: tried to unique lldb_private::Type from " + "0x%8.8x for 0x%8.8x, but none was found", + src_die.GetOffset(), dst_die.GetOffset()); } } } @@ -3872,10 +3874,10 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( ConstString dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx); - if (log) - log->Printf("warning: need to create artificial method for 0x%8.8x for " - "method '%s'", - dst_die.GetOffset(), dst_name_artificial.GetCString()); + LLDB_LOGF(log, + "warning: need to create artificial method for 0x%8.8x for " + "method '%s'", + dst_die.GetOffset(), dst_name_artificial.GetCString()); failures.push_back(dst_die); } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 5b5d83d65932..106f9254a449 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -15,7 +15,10 @@ #include "llvm/ADT/SmallVector.h" #include "DWARFASTParser.h" +#include "DWARFDIE.h" #include "DWARFDefines.h" +#include "DWARFFormValue.h" +#include "LogChannelDWARF.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/ClangASTContext.h" @@ -29,6 +32,8 @@ class CompileUnit; class DWARFDebugInfoEntry; class SymbolFileDWARF; +struct ParsedDWARFTypeAttributes; + class DWARFASTParserClang : public DWARFASTParser { public: DWARFASTParserClang(lldb_private::ClangASTContext &ast); @@ -37,7 +42,7 @@ public: // DWARFASTParser interface. lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, - const DWARFDIE &die, lldb_private::Log *log, + const DWARFDIE &die, bool *type_is_new_ptr) override; lldb_private::Function * @@ -51,8 +56,8 @@ public: lldb_private::CompilerDecl GetDeclForUIDFromDWARF(const DWARFDIE &die) override; - std::vector<DWARFDIE> - GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) override; + void EnsureAllDIEsInDeclContextHaveBeenParsed( + lldb_private::CompilerDeclContext decl_context) override; lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override; @@ -63,9 +68,28 @@ public: lldb_private::ClangASTImporter &GetClangASTImporter(); protected: + /// Protected typedefs and members. + /// @{ class DelayedAddObjCClassProperty; typedef std::vector<DelayedAddObjCClassProperty> DelayedPropertyList; + typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> + DIEToDeclContextMap; + typedef std::multimap<const clang::DeclContext *, const DWARFDIE> + DeclContextToDIEMap; + typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> + DIEToDeclMap; + typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; + + lldb_private::ClangASTContext &m_ast; + DIEToDeclMap m_die_to_decl; + DeclToDIEMap m_decl_to_die; + DIEToDeclContextMap m_die_to_decl_ctx; + DeclContextToDIEMap m_decl_ctx_to_die; + std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; + /// @} + clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die); clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die); @@ -103,6 +127,10 @@ protected: bool is_signed, uint32_t enumerator_byte_size, const DWARFDIE &parent_die); + /// Parse a structure, class, or union type DIE. + lldb::TypeSP ParseStructureLikeDIE(const DWARFDIE &die, + ParsedDWARFTypeAttributes &attrs); + lldb_private::Type *GetTypeForDIE(const DWARFDIE &die); clang::Decl *GetClangDeclForDIE(const DWARFDIE &die); @@ -123,29 +151,52 @@ protected: void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die); + /// If \p type_sp is valid, calculate and set its symbol context scope, and + /// update the type list for its backing symbol file. + /// + /// Returns \p type_sp. + lldb::TypeSP + UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc, + const DWARFDIE &die, lldb::TypeSP type_sp); + lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log); // Return true if this type is a declaration to a type in an external // module. lldb::ModuleSP GetModuleForType(const DWARFDIE &die); +}; - typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> - DIEToDeclContextMap; - // typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> - // DeclContextToDIEMap; - typedef std::multimap<const clang::DeclContext *, const DWARFDIE> - DeclContextToDIEMap; - typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> - DIEToDeclMap; - typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; - - lldb_private::ClangASTContext &m_ast; - DIEToDeclMap m_die_to_decl; - DeclToDIEMap m_decl_to_die; - DIEToDeclContextMap m_die_to_decl_ctx; - DeclContextToDIEMap m_decl_ctx_to_die; - std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up; +/// Parsed form of all attributes that are relevant for type reconstruction. +/// Some attributes are relevant for all kinds of types (declaration), while +/// others are only meaningful to a specific type (is_virtual) +struct ParsedDWARFTypeAttributes { + explicit ParsedDWARFTypeAttributes(const DWARFDIE &die); + + lldb::AccessType accessibility = lldb::eAccessNone; + bool is_artificial = false; + bool is_complete_objc_class = false; + bool is_explicit = false; + bool is_forward_declaration = false; + bool is_inline = false; + bool is_scoped_enum = false; + bool is_vector = false; + bool is_virtual = false; + clang::StorageClass storage = clang::SC_None; + const char *mangled_name = nullptr; + lldb_private::ConstString name; + lldb_private::Declaration decl; + DWARFDIE object_pointer; + DWARFFormValue abstract_origin; + DWARFFormValue containing_type; + DWARFFormValue signature; + DWARFFormValue specification; + DWARFFormValue type; + lldb::LanguageType class_language = lldb::eLanguageTypeUnknown; + llvm::Optional<uint64_t> byte_size; + size_t calling_convention = llvm::dwarf::DW_CC_normal; + uint32_t bit_stride = 0; + uint32_t byte_stride = 0; + uint32_t encoding = 0; }; #endif // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp index 6128163a2926..741669b05754 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp @@ -18,7 +18,8 @@ using namespace lldb_private; DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() - : m_code(InvalidCode), m_tag(0), m_has_children(0), m_attributes() {} + : m_code(InvalidCode), m_tag(llvm::dwarf::DW_TAG_null), m_has_children(0), + m_attributes() {} DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children) @@ -33,7 +34,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, return DWARFEnumState::Complete; m_attributes.clear(); - m_tag = data.GetULEB128(offset_ptr); + m_tag = static_cast<dw_tag_t>(data.GetULEB128(offset_ptr)); if (m_tag == DW_TAG_null) return llvm::make_error<llvm::object::GenericBinaryError>( "abbrev decl requires non-null tag."); @@ -68,7 +69,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, } bool DWARFAbbreviationDeclaration::IsValid() { - return m_code != 0 && m_tag != 0; + return m_code != 0 && m_tag != llvm::dwarf::DW_TAG_null; } uint32_t diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp index 96adb72c9532..033105efdc53 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/Log.h" using namespace lldb_private; @@ -29,7 +30,7 @@ dw_tag_t DWARFBaseDIE::Tag() const { if (m_die) return m_die->Tag(); else - return 0; + return llvm::dwarf::DW_TAG_null; } const char *DWARFBaseDIE::GetTagAsCString() const { @@ -102,19 +103,22 @@ SymbolFileDWARF *DWARFBaseDIE::GetDWARF() const { return nullptr; } -lldb_private::TypeSystem *DWARFBaseDIE::GetTypeSystem() const { - if (m_cu) - return m_cu->GetTypeSystem(); - else - return nullptr; +llvm::Expected<lldb_private::TypeSystem &> DWARFBaseDIE::GetTypeSystem() const { + if (!m_cu) + return llvm::make_error<llvm::StringError>( + "Unable to get TypeSystem, no compilation unit available", + llvm::inconvertibleErrorCode()); + return m_cu->GetTypeSystem(); } DWARFASTParser *DWARFBaseDIE::GetDWARFParser() const { - lldb_private::TypeSystem *type_system = GetTypeSystem(); - if (type_system) - return type_system->GetDWARFParser(); - else + auto type_system_or_err = GetTypeSystem(); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DWARFASTParser"); return nullptr; + } + return type_system_or_err->GetDWARFParser(); } bool DWARFBaseDIE::HasChildren() const { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h index 0058043017cd..9652d7946e87 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -12,6 +12,8 @@ #include "lldb/Core/dwarf.h" #include "lldb/lldb-types.h" +#include "llvm/Support/Error.h" + class DIERef; class DWARFASTParser; class DWARFAttributes; @@ -55,7 +57,7 @@ public: llvm::Optional<DIERef> GetDIERef() const; - lldb_private::TypeSystem *GetTypeSystem() const; + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystem() const; DWARFASTParser *GetDWARFParser() const; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 9d97ca15a252..5ee0687995a1 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -342,7 +342,8 @@ void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const { } } -void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const { +void DWARFDIE::GetDeclContext( + llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const { const dw_tag_t tag = Tag(); if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) return; @@ -351,40 +352,33 @@ void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const { parent.GetDeclContext(context); switch (tag) { case DW_TAG_module: - context.push_back( - CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); + context.push_back({CompilerContextKind::Module, ConstString(GetName())}); break; case DW_TAG_namespace: - context.push_back(CompilerContext(CompilerContextKind::Namespace, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Namespace, ConstString(GetName())}); break; case DW_TAG_structure_type: - context.push_back(CompilerContext(CompilerContextKind::Structure, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Struct, ConstString(GetName())}); break; case DW_TAG_union_type: - context.push_back( - CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); + context.push_back({CompilerContextKind::Union, ConstString(GetName())}); break; case DW_TAG_class_type: - context.push_back( - CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); + context.push_back({CompilerContextKind::Class, ConstString(GetName())}); break; case DW_TAG_enumeration_type: - context.push_back(CompilerContext(CompilerContextKind::Enumeration, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Enum, ConstString(GetName())}); break; case DW_TAG_subprogram: - context.push_back(CompilerContext(CompilerContextKind::Function, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Function, ConstString(GetPubname())}); break; case DW_TAG_variable: - context.push_back(CompilerContext(CompilerContextKind::Variable, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Variable, ConstString(GetPubname())}); break; case DW_TAG_typedef: - context.push_back( - CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); + context.push_back({CompilerContextKind::Typedef, ConstString(GetName())}); break; default: break; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 7753ec9008cb..a779c589611a 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -78,8 +78,8 @@ public: /// Return this DIE's decl context as it is needed to look up types /// in Clang's -gmodules debug info format. - void - GetDeclContext(std::vector<lldb_private::CompilerContext> &context) const; + void GetDeclContext( + llvm::SmallVectorImpl<lldb_private::CompilerContext> &context) const; // Getting attribute values from the DIE. // diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index ccf33e6dc341..c8da2381353e 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -66,8 +66,8 @@ void DWARFDebugAranges::Dump(Log *log) const { for (size_t i = 0; i < num_entries; ++i) { const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i); if (entry) - log->Printf("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data, - entry->GetRangeBase(), entry->GetRangeEnd()); + LLDB_LOGF(log, "0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", entry->data, + entry->GetRangeBase(), entry->GetRangeEnd()); } } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 100f35f8c6b0..1e04baca2c58 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -38,7 +38,7 @@ llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { if (m_cu_aranges_up) return *m_cu_aranges_up; - m_cu_aranges_up = llvm::make_unique<DWARFDebugAranges>(); + 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)) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 2f55b7d40ed9..8c0fbeb4b717 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -192,7 +192,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, *offset_ptr = offset; return true; } else { - m_tag = 0; + m_tag = llvm::dwarf::DW_TAG_null; m_has_children = false; return true; // NULL debug tag entry } @@ -340,18 +340,14 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - *frame_base = DWARFExpression(module, data, cu, - block_offset, block_length); + *frame_base = DWARFExpression( + module, DataExtractor(data, block_offset, block_length), cu); } else { - const DWARFDataExtractor &debug_loc_data = dwarf.DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - cu, debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - *frame_base = - DWARFExpression(module, debug_loc_data, cu, - debug_loc_offset, loc_list_length); + DataExtractor data = dwarf.DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + *frame_base = DWARFExpression(module, data, cu); if (lo_pc != LLDB_INVALID_ADDRESS) { assert(lo_pc >= cu->GetBaseAddress()); frame_base->SetLocationListSlide(lo_pc - diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 1e7b5f27642d..25c885608d85 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -31,7 +31,7 @@ public: DWARFDebugInfoEntry() : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), - m_has_children(false), m_abbr_idx(0), m_tag(0) {} + m_has_children(false), m_abbr_idx(0), m_tag(llvm::dwarf::DW_TAG_null) {} explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; } bool operator==(const DWARFDebugInfoEntry &rhs) const; @@ -178,8 +178,9 @@ protected: // a single NULL terminating child. m_has_children : 1; uint16_t m_abbr_idx; - uint16_t m_tag; // A copy of the DW_TAG value so we don't have to go through - // the compile unit abbrev table + /// 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; }; #endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp deleted file mode 100644 index 953089fee22b..000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ /dev/null @@ -1,1038 +0,0 @@ -//===-- DWARFDebugLine.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 "DWARFDebugLine.h" - -//#define ENABLE_DEBUG_PRINTF // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!! -#include <assert.h> - -#include <memory> - -#include "lldb/Core/FileSpecList.h" -#include "lldb/Core/Module.h" -#include "lldb/Host/Host.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Timer.h" - -#include "DWARFUnit.h" -#include "LogChannelDWARF.h" -#include "SymbolFileDWARF.h" - -using namespace lldb; -using namespace lldb_private; -using namespace std; - -// Parse -// -// Parse all information in the debug_line_data into an internal -// representation. -void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) { - m_lineTableMap.clear(); - lldb::offset_t offset = 0; - LineTable::shared_ptr line_table_sp(new LineTable); - while (debug_line_data.ValidOffset(offset)) { - const lldb::offset_t debug_line_offset = offset; - - if (line_table_sp.get() == nullptr) - break; - - if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) { - // Make sure we don't don't loop infinitely - if (offset <= debug_line_offset) - break; - // DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n", - // debug_line_offset); - m_lineTableMap[debug_line_offset] = line_table_sp; - line_table_sp = std::make_shared<LineTable>(); - } else - ++offset; // Try next byte in line table - } -} - -void DWARFDebugLine::ParseIfNeeded(const DWARFDataExtractor &debug_line_data) { - if (m_lineTableMap.empty()) - Parse(debug_line_data); -} - -// DWARFDebugLine::GetLineTable -DWARFDebugLine::LineTable::shared_ptr -DWARFDebugLine::GetLineTable(const dw_offset_t offset) const { - DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr; - LineTableConstIter pos = m_lineTableMap.find(offset); - if (pos != m_lineTableMap.end()) - line_table_shared_ptr = pos->second; - return line_table_shared_ptr; -} - -// Parse -// -// Parse the entire line table contents calling callback each time a new -// prologue is parsed and every time a new row is to be added to the line -// table. -void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data, - DWARFDebugLine::State::Callback callback, - void *userData) { - lldb::offset_t offset = 0; - if (debug_line_data.ValidOffset(offset)) { - if (!ParseStatementTable(debug_line_data, &offset, callback, userData, nullptr)) - ++offset; // Skip to next byte in .debug_line section - } -} - -namespace { -struct EntryDescriptor { - dw_sleb128_t code; - dw_sleb128_t form; -}; - -static std::vector<EntryDescriptor> -ReadDescriptors(const DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr) { - std::vector<EntryDescriptor> ret; - uint8_t n = debug_line_data.GetU8(offset_ptr); - for (uint8_t i = 0; i < n; ++i) { - EntryDescriptor ent; - ent.code = debug_line_data.GetULEB128(offset_ptr); - ent.form = debug_line_data.GetULEB128(offset_ptr); - ret.push_back(ent); - } - return ret; -} -} // namespace - -// DWARFDebugLine::ParsePrologue -bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, - Prologue *prologue, DWARFUnit *dwarf_cu) { - const lldb::offset_t prologue_offset = *offset_ptr; - - // DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr); - - prologue->Clear(); - uint32_t i; - const char *s; - prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr); - prologue->version = debug_line_data.GetU16(offset_ptr); - if (prologue->version < 2 || prologue->version > 5) - return false; - - if (prologue->version >= 5) { - prologue->address_size = debug_line_data.GetU8(offset_ptr); - prologue->segment_selector_size = debug_line_data.GetU8(offset_ptr); - } - - prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr); - const lldb::offset_t end_prologue_offset = - prologue->prologue_length + *offset_ptr; - prologue->min_inst_length = debug_line_data.GetU8(offset_ptr); - if (prologue->version >= 4) - prologue->maximum_operations_per_instruction = - debug_line_data.GetU8(offset_ptr); - else - prologue->maximum_operations_per_instruction = 1; - prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr); - prologue->line_base = debug_line_data.GetU8(offset_ptr); - prologue->line_range = debug_line_data.GetU8(offset_ptr); - prologue->opcode_base = debug_line_data.GetU8(offset_ptr); - - prologue->standard_opcode_lengths.reserve(prologue->opcode_base - 1); - - for (i = 1; i < prologue->opcode_base; ++i) { - uint8_t op_len = debug_line_data.GetU8(offset_ptr); - prologue->standard_opcode_lengths.push_back(op_len); - } - - if (prologue->version >= 5) { - std::vector<EntryDescriptor> dirEntryFormatV = - ReadDescriptors(debug_line_data, offset_ptr); - uint8_t dirCount = debug_line_data.GetULEB128(offset_ptr); - for (int i = 0; i < dirCount; ++i) { - for (EntryDescriptor &ent : dirEntryFormatV) { - DWARFFormValue value(dwarf_cu, ent.form); - if (ent.code != DW_LNCT_path) { - if (!value.SkipValue(debug_line_data, offset_ptr)) - return false; - continue; - } - - if (!value.ExtractValue(debug_line_data, offset_ptr)) - return false; - prologue->include_directories.push_back(value.AsCString()); - } - } - - std::vector<EntryDescriptor> filesEntryFormatV = - ReadDescriptors(debug_line_data, offset_ptr); - llvm::DenseSet<std::pair<uint64_t, uint64_t>> seen; - uint8_t n = debug_line_data.GetULEB128(offset_ptr); - for (int i = 0; i < n; ++i) { - FileNameEntry entry; - for (EntryDescriptor &ent : filesEntryFormatV) { - DWARFFormValue value(dwarf_cu, ent.form); - if (!value.ExtractValue(debug_line_data, offset_ptr)) - return false; - - switch (ent.code) { - case DW_LNCT_path: - entry.name = value.AsCString(); - break; - case DW_LNCT_directory_index: - entry.dir_idx = value.Unsigned(); - break; - case DW_LNCT_timestamp: - entry.mod_time = value.Unsigned(); - break; - case DW_LNCT_size: - entry.length = value.Unsigned(); - break; - case DW_LNCT_MD5: - assert(value.Unsigned() == 16); - std::uninitialized_copy_n(value.BlockData(), 16, - entry.checksum.Bytes.begin()); - break; - default: - break; - } - } - - if (seen.insert(entry.checksum.words()).second) - prologue->file_names.push_back(entry); - } - } else { - while (*offset_ptr < end_prologue_offset) { - s = debug_line_data.GetCStr(offset_ptr); - if (s && s[0]) - prologue->include_directories.push_back(s); - else - break; - } - - while (*offset_ptr < end_prologue_offset) { - const char *name = debug_line_data.GetCStr(offset_ptr); - if (name && name[0]) { - FileNameEntry fileEntry; - fileEntry.name = name; - fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr); - fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr); - fileEntry.length = debug_line_data.GetULEB128(offset_ptr); - prologue->file_names.push_back(fileEntry); - } else - break; - } - } - - // XXX GNU as is broken for 64-Bit DWARF - if (*offset_ptr != end_prologue_offset) { - Host::SystemLog(Host::eSystemLogWarning, - "warning: parsing line table prologue at 0x%8.8" PRIx64 - " should have ended at 0x%8.8" PRIx64 - " but it ended at 0x%8.8" PRIx64 "\n", - prologue_offset, end_prologue_offset, *offset_ptr); - } - return end_prologue_offset; -} - -bool DWARFDebugLine::ParseSupportFiles( - const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data, - dw_offset_t stmt_list, FileSpecList &support_files, DWARFUnit *dwarf_cu) { - lldb::offset_t offset = stmt_list; - - Prologue prologue; - if (!ParsePrologue(debug_line_data, &offset, &prologue, dwarf_cu)) { - Host::SystemLog(Host::eSystemLogError, "error: parsing line table prologue " - "at 0x%8.8x (parsing ended around " - "0x%8.8" PRIx64 "\n", - stmt_list, offset); - return false; - } - - FileSpec file_spec; - std::string remapped_file; - - for (uint32_t file_idx = 1; - prologue.GetFile(file_idx, dwarf_cu->GetCompilationDirectory(), - dwarf_cu->GetPathStyle(), file_spec); - ++file_idx) { - if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file)) - file_spec.SetFile(remapped_file, FileSpec::Style::native); - support_files.Append(file_spec); - } - return true; -} - -// ParseStatementTable -// -// Parse a single line table (prologue and all rows) and call the callback -// function once for the prologue (row in state will be zero) and each time a -// row is to be added to the line table. -bool DWARFDebugLine::ParseStatementTable( - const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, - DWARFDebugLine::State::Callback callback, void *userData, DWARFUnit *dwarf_cu) { - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE)); - Prologue::shared_ptr prologue(new Prologue()); - - const dw_offset_t debug_line_offset = *offset_ptr; - - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer( - func_cat, "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])", - debug_line_offset); - - if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get(), dwarf_cu)) { - if (log) - log->Error("failed to parse DWARF line table prologue"); - // Restore our offset and return false to indicate failure! - *offset_ptr = debug_line_offset; - return false; - } - - if (log) - prologue->Dump(log); - - const dw_offset_t end_offset = - debug_line_offset + prologue->total_length + - (debug_line_data.GetDWARFSizeofInitialLength()); - - State state(prologue, log, callback, userData); - - while (*offset_ptr < end_offset) { - // DEBUG_PRINTF("0x%8.8x: ", *offset_ptr); - uint8_t opcode = debug_line_data.GetU8(offset_ptr); - - if (opcode == 0) { - // Extended Opcodes always start with a zero opcode followed by a uleb128 - // length so you can skip ones you don't know about - lldb::offset_t ext_offset = *offset_ptr; - dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr); - dw_offset_t arg_size = len - (*offset_ptr - ext_offset); - - // DEBUG_PRINTF("Extended: <%2u> ", len); - uint8_t sub_opcode = debug_line_data.GetU8(offset_ptr); - switch (sub_opcode) { - case DW_LNE_end_sequence: - // Set the end_sequence register of the state machine to true and - // append a row to the matrix using the current values of the state- - // machine registers. Then reset the registers to the initial values - // specified above. Every statement program sequence must end with a - // DW_LNE_end_sequence instruction which creates a row whose address is - // that of the byte after the last target machine instruction of the - // sequence. - state.end_sequence = true; - state.AppendRowToMatrix(*offset_ptr); - state.Reset(); - break; - - case DW_LNE_set_address: - // Takes a single relocatable address as an operand. The size of the - // operand is the size appropriate to hold an address on the target - // machine. Set the address register to the value given by the - // relocatable address. All of the other statement program opcodes that - // affect the address register add a delta to it. This instruction - // stores a relocatable value into it instead. - if (arg_size == 4) - state.address = debug_line_data.GetU32(offset_ptr); - else // arg_size == 8 - state.address = debug_line_data.GetU64(offset_ptr); - break; - - case DW_LNE_define_file: - // Takes 4 arguments. The first is a null terminated string containing - // a source file name. The second is an unsigned LEB128 number - // representing the directory index of the directory in which the file - // was found. The third is an unsigned LEB128 number representing the - // time of last modification of the file. The fourth is an unsigned - // LEB128 number representing the length in bytes of the file. The time - // and length fields may contain LEB128(0) if the information is not - // available. - // - // The directory index represents an entry in the include_directories - // section of the statement program prologue. The index is LEB128(0) if - // the file was found in the current directory of the compilation, - // LEB128(1) if it was found in the first directory in the - // include_directories section, and so on. The directory index is - // ignored for file names that represent full path names. - // - // The files are numbered, starting at 1, in the order in which they - // appear; the names in the prologue come before names defined by the - // DW_LNE_define_file instruction. These numbers are used in the file - // register of the state machine. - { - FileNameEntry fileEntry; - fileEntry.name = debug_line_data.GetCStr(offset_ptr); - fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr); - fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr); - fileEntry.length = debug_line_data.GetULEB128(offset_ptr); - state.prologue->file_names.push_back(fileEntry); - } - break; - - default: - // Length doesn't include the zero opcode byte or the length itself, - // but it does include the sub_opcode, so we have to adjust for that - // below - (*offset_ptr) += arg_size; - break; - } - } else if (opcode < prologue->opcode_base) { - switch (opcode) { - // Standard Opcodes - case DW_LNS_copy: - // Takes no arguments. Append a row to the matrix using the current - // values of the state-machine registers. Then set the basic_block - // register to false. - state.AppendRowToMatrix(*offset_ptr); - break; - - case DW_LNS_advance_pc: - // Takes a single unsigned LEB128 operand, multiplies it by the - // min_inst_length field of the prologue, and adds the result to the - // address register of the state machine. - state.address += - debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length; - break; - - case DW_LNS_advance_line: - // Takes a single signed LEB128 operand and adds that value to the line - // register of the state machine. - state.line += debug_line_data.GetSLEB128(offset_ptr); - break; - - case DW_LNS_set_file: - // Takes a single unsigned LEB128 operand and stores it in the file - // register of the state machine. - state.file = debug_line_data.GetULEB128(offset_ptr); - break; - - case DW_LNS_set_column: - // Takes a single unsigned LEB128 operand and stores it in the column - // register of the state machine. - state.column = debug_line_data.GetULEB128(offset_ptr); - break; - - case DW_LNS_negate_stmt: - // Takes no arguments. Set the is_stmt register of the state machine to - // the logical negation of its current value. - state.is_stmt = !state.is_stmt; - break; - - case DW_LNS_set_basic_block: - // Takes no arguments. Set the basic_block register of the state - // machine to true - state.basic_block = true; - break; - - case DW_LNS_const_add_pc: - // Takes no arguments. Add to the address register of the state machine - // the address increment value corresponding to special opcode 255. The - // motivation for DW_LNS_const_add_pc is this: when the statement - // program needs to advance the address by a small amount, it can use a - // single special opcode, which occupies a single byte. When it needs - // to advance the address by up to twice the range of the last special - // opcode, it can use DW_LNS_const_add_pc followed by a special opcode, - // for a total of two bytes. Only if it needs to advance the address by - // more than twice that range will it need to use both - // DW_LNS_advance_pc and a special opcode, requiring three or more - // bytes. - { - uint8_t adjust_opcode = 255 - prologue->opcode_base; - dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * - prologue->min_inst_length; - state.address += addr_offset; - } - break; - - case DW_LNS_fixed_advance_pc: - // Takes a single uhalf operand. Add to the address register of the - // state machine the value of the (unencoded) operand. This is the only - // extended opcode that takes an argument that is not a variable length - // number. The motivation for DW_LNS_fixed_advance_pc is this: existing - // assemblers cannot emit DW_LNS_advance_pc or special opcodes because - // they cannot encode LEB128 numbers or judge when the computation of a - // special opcode overflows and requires the use of DW_LNS_advance_pc. - // Such assemblers, however, can use DW_LNS_fixed_advance_pc instead, - // sacrificing compression. - state.address += debug_line_data.GetU16(offset_ptr); - break; - - case DW_LNS_set_prologue_end: - // Takes no arguments. Set the prologue_end register of the state - // machine to true - state.prologue_end = true; - break; - - case DW_LNS_set_epilogue_begin: - // Takes no arguments. Set the basic_block register of the state - // machine to true - state.epilogue_begin = true; - break; - - case DW_LNS_set_isa: - // Takes a single unsigned LEB128 operand and stores it in the column - // register of the state machine. - state.isa = debug_line_data.GetULEB128(offset_ptr); - break; - - default: - // Handle any unknown standard opcodes here. We know the lengths of - // such opcodes because they are specified in the prologue as a - // multiple of LEB128 operands for each opcode. - { - uint8_t i; - assert(static_cast<size_t>(opcode - 1) < - prologue->standard_opcode_lengths.size()); - const uint8_t opcode_length = - prologue->standard_opcode_lengths[opcode - 1]; - for (i = 0; i < opcode_length; ++i) - debug_line_data.Skip_LEB128(offset_ptr); - } - break; - } - } else { - // Special Opcodes - - // A special opcode value is chosen based on the amount that needs - // to be added to the line and address registers. The maximum line - // increment for a special opcode is the value of the line_base field in - // the header, plus the value of the line_range field, minus 1 (line base - // + line range - 1). If the desired line increment is greater than the - // maximum line increment, a standard opcode must be used instead of a - // special opcode. The "address advance" is calculated by dividing the - // desired address increment by the minimum_instruction_length field from - // the header. The special opcode is then calculated using the following - // formula: - // - // opcode = (desired line increment - line_base) + (line_range * address - // advance) + opcode_base - // - // If the resulting opcode is greater than 255, a standard opcode must be - // used instead. - // - // To decode a special opcode, subtract the opcode_base from the opcode - // itself to give the adjusted opcode. The amount to increment the - // address register is the result of the adjusted opcode divided by the - // line_range multiplied by the minimum_instruction_length field from the - // header. That is: - // - // address increment = (adjusted opcode / line_range) * - // minimum_instruction_length - // - // The amount to increment the line register is the line_base plus the - // result of the adjusted opcode modulo the line_range. That is: - // - // line increment = line_base + (adjusted opcode % line_range) - - uint8_t adjust_opcode = opcode - prologue->opcode_base; - dw_addr_t addr_offset = - (adjust_opcode / prologue->line_range) * prologue->min_inst_length; - int32_t line_offset = - prologue->line_base + (adjust_opcode % prologue->line_range); - state.line += line_offset; - state.address += addr_offset; - state.AppendRowToMatrix(*offset_ptr); - } - } - - state.Finalize(*offset_ptr); - - return end_offset; -} - -// ParseStatementTableCallback -static void ParseStatementTableCallback(dw_offset_t offset, - const DWARFDebugLine::State &state, - void *userData) { - DWARFDebugLine::LineTable *line_table = (DWARFDebugLine::LineTable *)userData; - if (state.row == DWARFDebugLine::State::StartParsingLineTable) { - // Just started parsing the line table, so lets keep a reference to the - // prologue using the supplied shared pointer - line_table->prologue = state.prologue; - } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) { - // Done parsing line table, nothing to do for the cleanup - } else { - // We have a new row, lets append it - line_table->AppendRow(state); - } -} - -// ParseStatementTable -// -// Parse a line table at offset and populate the LineTable class with the -// prologue and all rows. -bool DWARFDebugLine::ParseStatementTable( - const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr, - LineTable *line_table, DWARFUnit *dwarf_cu) { - return ParseStatementTable(debug_line_data, offset_ptr, - ParseStatementTableCallback, line_table, dwarf_cu); -} - -inline bool DWARFDebugLine::Prologue::IsValid() const { - return SymbolFileDWARF::SupportedVersion(version); -} - -// DWARFDebugLine::Prologue::Dump -void DWARFDebugLine::Prologue::Dump(Log *log) { - uint32_t i; - - log->Printf("Line table prologue:"); - log->Printf(" total_length: 0x%8.8x", total_length); - log->Printf(" version: %u", version); - log->Printf("prologue_length: 0x%8.8x", prologue_length); - log->Printf("min_inst_length: %u", min_inst_length); - log->Printf("default_is_stmt: %u", default_is_stmt); - log->Printf(" line_base: %i", line_base); - log->Printf(" line_range: %u", line_range); - log->Printf(" opcode_base: %u", opcode_base); - - for (i = 0; i < standard_opcode_lengths.size(); ++i) { - log->Printf("standard_opcode_lengths[%s] = %u", DW_LNS_value_to_name(i + 1), - standard_opcode_lengths[i]); - } - - if (!include_directories.empty()) { - for (i = 0; i < include_directories.size(); ++i) { - log->Printf("include_directories[%3u] = '%s'", i + 1, - include_directories[i]); - } - } - - if (!file_names.empty()) { - log->PutCString(" Dir Mod Time File Len File Name"); - log->PutCString(" ---- ---------- ---------- " - "---------------------------"); - for (i = 0; i < file_names.size(); ++i) { - const FileNameEntry &fileEntry = file_names[i]; - log->Printf("file_names[%3u] %4u 0x%8.8x 0x%8.8x %s", i + 1, - fileEntry.dir_idx, fileEntry.mod_time, fileEntry.length, - fileEntry.name); - } - } -} - -// DWARFDebugLine::ParsePrologue::Append -// -// Append the contents of the prologue to the binary stream buffer -// void -// DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const -//{ -// uint32_t i; -// -// buff.Append32(total_length); -// buff.Append16(version); -// buff.Append32(prologue_length); -// buff.Append8(min_inst_length); -// buff.Append8(default_is_stmt); -// buff.Append8(line_base); -// buff.Append8(line_range); -// buff.Append8(opcode_base); -// -// for (i=0; i<standard_opcode_lengths.size(); ++i) -// buff.Append8(standard_opcode_lengths[i]); -// -// for (i=0; i<include_directories.size(); ++i) -// buff.AppendCStr(include_directories[i].c_str()); -// buff.Append8(0); // Terminate the include directory section with empty -// string -// -// for (i=0; i<file_names.size(); ++i) -// { -// buff.AppendCStr(file_names[i].name.c_str()); -// buff.Append32_as_ULEB128(file_names[i].dir_idx); -// buff.Append32_as_ULEB128(file_names[i].mod_time); -// buff.Append32_as_ULEB128(file_names[i].length); -// } -// buff.Append8(0); // Terminate the file names section with empty string -//} - -bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, - const FileSpec &comp_dir, - FileSpec::Style style, - FileSpec &file) const { - uint32_t idx = file_idx - 1; // File indexes are 1 based... - if (idx < file_names.size()) { - file.SetFile(file_names[idx].name, style); - if (file.IsRelative()) { - if (file_names[idx].dir_idx > 0) { - const uint32_t dir_idx = file_names[idx].dir_idx - 1; - if (dir_idx < include_directories.size()) { - file.PrependPathComponent(include_directories[dir_idx]); - if (!file.IsRelative()) - return true; - } - } - - if (comp_dir) - file.PrependPathComponent(comp_dir); - } - return true; - } - return false; -} - -void DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row &state) { - rows.push_back(state); -} - -// Compare function for the binary search in -// DWARFDebugLine::LineTable::LookupAddress() -static bool FindMatchingAddress(const DWARFDebugLine::Row &row1, - const DWARFDebugLine::Row &row2) { - return row1.address < row2.address; -} - -// DWARFDebugLine::LineTable::LookupAddress -uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, - dw_addr_t cu_high_pc) const { - uint32_t index = UINT32_MAX; - if (!rows.empty()) { - // Use the lower_bound algorithm to perform a binary search since we know - // that our line table data is ordered by address. - DWARFDebugLine::Row row; - row.address = address; - Row::const_iterator begin_pos = rows.begin(); - Row::const_iterator end_pos = rows.end(); - Row::const_iterator pos = - lower_bound(begin_pos, end_pos, row, FindMatchingAddress); - if (pos == end_pos) { - if (address < cu_high_pc) - return rows.size() - 1; - } else { - // Rely on fact that we are using a std::vector and we can do pointer - // arithmetic to find the row index (which will be one less that what we - // found since it will find the first position after the current address) - // since std::vector iterators are just pointers to the container type. - index = pos - begin_pos; - if (pos->address > address) { - if (index > 0) - --index; - else - index = UINT32_MAX; - } - } - } - return index; // Failed to find address -} - -// DWARFDebugLine::Row::Row -DWARFDebugLine::Row::Row(bool default_is_stmt) - : address(0), line(1), column(0), file(1), is_stmt(default_is_stmt), - basic_block(false), end_sequence(false), prologue_end(false), - epilogue_begin(false), isa(0) {} - -// Called after a row is appended to the matrix -void DWARFDebugLine::Row::PostAppend() { - basic_block = false; - prologue_end = false; - epilogue_begin = false; -} - -// DWARFDebugLine::Row::Reset -void DWARFDebugLine::Row::Reset(bool default_is_stmt) { - address = 0; - line = 1; - column = 0; - file = 1; - is_stmt = default_is_stmt; - basic_block = false; - end_sequence = false; - prologue_end = false; - epilogue_begin = false; - isa = 0; -} -// DWARFDebugLine::Row::Dump -void DWARFDebugLine::Row::Dump(Log *log) const { - log->Printf("0x%16.16" PRIx64 " %6u %6u %6u %3u %s%s%s%s%s", address, line, - column, file, isa, is_stmt ? " is_stmt" : "", - basic_block ? " basic_block" : "", - prologue_end ? " prologue_end" : "", - epilogue_begin ? " epilogue_begin" : "", - end_sequence ? " end_sequence" : ""); -} - -// Compare function LineTable structures -static bool AddressLessThan(const DWARFDebugLine::Row &a, - const DWARFDebugLine::Row &b) { - return a.address < b.address; -} - -// Insert a row at the correct address if the addresses can be out of order -// which can only happen when we are linking a line table that may have had -// it's contents rearranged. -void DWARFDebugLine::Row::Insert(Row::collection &state_coll, - const Row &state) { - // If we don't have anything yet, or if the address of the last state in our - // line table is less than the current one, just append the current state - if (state_coll.empty() || AddressLessThan(state_coll.back(), state)) { - state_coll.push_back(state); - } else { - // Do a binary search for the correct entry - pair<Row::iterator, Row::iterator> range(equal_range( - state_coll.begin(), state_coll.end(), state, AddressLessThan)); - - // If the addresses are equal, we can safely replace the previous entry - // with the current one if the one it is replacing is an end_sequence - // entry. We currently always place an extra end sequence when ever we exit - // a valid address range for a function in case the functions get - // rearranged by optimizations or by order specifications. These extra end - // sequences will disappear by getting replaced with valid consecutive - // entries within a compile unit if there are no gaps. - if (range.first == range.second) { - state_coll.insert(range.first, state); - } else { - if ((distance(range.first, range.second) == 1) && - range.first->end_sequence == true) { - *range.first = state; - } else { - state_coll.insert(range.second, state); - } - } - } -} - -// DWARFDebugLine::State::State -DWARFDebugLine::State::State(Prologue::shared_ptr &p, Log *l, - DWARFDebugLine::State::Callback cb, void *userData) - : Row(p->default_is_stmt), prologue(p), log(l), callback(cb), - callbackUserData(userData), row(StartParsingLineTable) { - // Call the callback with the initial row state of zero for the prologue - if (callback) - callback(0, *this, callbackUserData); -} - -// DWARFDebugLine::State::Reset -void DWARFDebugLine::State::Reset() { Row::Reset(prologue->default_is_stmt); } - -// DWARFDebugLine::State::AppendRowToMatrix -void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) { - // Each time we are to add an entry into the line table matrix call the - // callback function so that someone can do something with the current state - // of the state machine (like build a line table or dump the line table!) - if (log) { - if (row == 0) { - log->PutCString("Address Line Column File ISA Flags"); - log->PutCString( - "------------------ ------ ------ ------ --- -------------"); - } - Dump(log); - } - - ++row; // Increase the row number before we call our callback for a real row - if (callback) - callback(offset, *this, callbackUserData); - PostAppend(); -} - -// DWARFDebugLine::State::Finalize -void DWARFDebugLine::State::Finalize(dw_offset_t offset) { - // Call the callback with a special row state when we are done parsing a line - // table - row = DoneParsingLineTable; - if (callback) - callback(offset, *this, callbackUserData); -} - -// void -// DWARFDebugLine::AppendLineTableData -//( -// const DWARFDebugLine::Prologue* prologue, -// const DWARFDebugLine::Row::collection& state_coll, -// const uint32_t addr_size, -// BinaryStreamBuf &debug_line_data -//) -//{ -// if (state_coll.empty()) -// { -// // We have no entries, just make an empty line table -// debug_line_data.Append8(0); -// debug_line_data.Append8(1); -// debug_line_data.Append8(DW_LNE_end_sequence); -// } -// else -// { -// DWARFDebugLine::Row::const_iterator pos; -// Row::const_iterator end = state_coll.end(); -// bool default_is_stmt = prologue->default_is_stmt; -// const DWARFDebugLine::Row reset_state(default_is_stmt); -// const DWARFDebugLine::Row* prev_state = &reset_state; -// const int32_t max_line_increment_for_special_opcode = -// prologue->MaxLineIncrementForSpecialOpcode(); -// for (pos = state_coll.begin(); pos != end; ++pos) -// { -// const DWARFDebugLine::Row& curr_state = *pos; -// int32_t line_increment = 0; -// dw_addr_t addr_offset = curr_state.address - prev_state->address; -// dw_addr_t addr_advance = (addr_offset) / prologue->min_inst_length; -// line_increment = (int32_t)(curr_state.line - prev_state->line); -// -// // If our previous state was the reset state, then let's emit the -// // address to keep GDB's DWARF parser happy. If we don't start each -// // sequence with a DW_LNE_set_address opcode, the line table won't -// // get slid properly in GDB. -// -// if (prev_state == &reset_state) -// { -// debug_line_data.Append8(0); // Extended opcode -// debug_line_data.Append32_as_ULEB128(addr_size + 1); // Length of -// opcode bytes -// debug_line_data.Append8(DW_LNE_set_address); -// debug_line_data.AppendMax64(curr_state.address, addr_size); -// addr_advance = 0; -// } -// -// if (prev_state->file != curr_state.file) -// { -// debug_line_data.Append8(DW_LNS_set_file); -// debug_line_data.Append32_as_ULEB128(curr_state.file); -// } -// -// if (prev_state->column != curr_state.column) -// { -// debug_line_data.Append8(DW_LNS_set_column); -// debug_line_data.Append32_as_ULEB128(curr_state.column); -// } -// -// // Don't do anything fancy if we are at the end of a sequence -// // as we don't want to push any extra rows since the -// DW_LNE_end_sequence -// // will push a row itself! -// if (curr_state.end_sequence) -// { -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Now push the end sequence on! -// debug_line_data.Append8(0); -// debug_line_data.Append8(1); -// debug_line_data.Append8(DW_LNE_end_sequence); -// -// prev_state = &reset_state; -// } -// else -// { -// if (line_increment || addr_advance) -// { -// if (line_increment > max_line_increment_for_special_opcode) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// line_increment = 0; -// } -// -// uint32_t special_opcode = (line_increment >= -// prologue->line_base) ? ((line_increment - -// prologue->line_base) + (prologue->line_range * addr_advance) -// + prologue->opcode_base) : 256; -// if (special_opcode > 255) -// { -// // Both the address and line won't fit in one special -// opcode -// // check to see if just the line advance will? -// uint32_t special_opcode_line = ((line_increment >= -// prologue->line_base) && (line_increment != 0)) ? -// ((line_increment - prologue->line_base) + -// prologue->opcode_base) : 256; -// -// -// if (special_opcode_line > 255) -// { -// // Nope, the line advance won't fit by itself, check -// the address increment by itself -// uint32_t special_opcode_addr = addr_advance ? -// ((0 - prologue->line_base) + -// (prologue->line_range * addr_advance) + -// prologue->opcode_base) : 256; -// -// if (special_opcode_addr > 255) -// { -// // Neither the address nor the line will fit in -// a -// // special opcode, we must manually enter both -// then -// // do a DW_LNS_copy to push a row (special -// opcode -// // automatically imply a new row is pushed) -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Now push a row onto the line table manually -// debug_line_data.Append8(DW_LNS_copy); -// -// } -// else -// { -// // The address increment alone will fit into a -// special opcode -// // so modify our line change, then issue a -// special opcode -// // for the address increment and it will push a -// row into the -// // line table -// if (line_increment != 0) -// { -// debug_line_data.Append8(DW_LNS_advance_line); -// debug_line_data.Append32_as_SLEB128(line_increment); -// } -// -// // Advance of line and address will fit into a -// single byte special opcode -// // and this will also push a row onto the line -// table -// debug_line_data.Append8(special_opcode_addr); -// } -// } -// else -// { -// // The line change alone will fit into a special -// opcode -// // so modify our address increment first, then issue -// a -// // special opcode for the line change and it will -// push -// // a row into the line table -// if (addr_advance > 0) -// { -// debug_line_data.Append8(DW_LNS_advance_pc); -// debug_line_data.Append32_as_ULEB128(addr_advance); -// } -// -// // Advance of line and address will fit into a -// single byte special opcode -// // and this will also push a row onto the line table -// debug_line_data.Append8(special_opcode_line); -// } -// } -// else -// { -// // Advance of line and address will fit into a single -// byte special opcode -// // and this will also push a row onto the line table -// debug_line_data.Append8(special_opcode); -// } -// } -// prev_state = &curr_state; -// } -// } -// } -//} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h deleted file mode 100644 index 0d236ca686b5..000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h +++ /dev/null @@ -1,227 +0,0 @@ -//===-- DWARFDebugLine.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 SymbolFileDWARF_DWARFDebugLine_h_ -#define SymbolFileDWARF_DWARFDebugLine_h_ - -#include <map> -#include <string> -#include <vector> - -#include "lldb/Utility/FileSpec.h" -#include "lldb/lldb-private.h" - -#include "DWARFDataExtractor.h" -#include "DWARFDefines.h" - -#include "llvm/Support/MD5.h" - -class DWARFUnit; -class SymbolFileDWARF; - -// DWARFDebugLine -class DWARFDebugLine { -public: - // FileNameEntry - struct FileNameEntry { - FileNameEntry() - : name(nullptr), dir_idx(0), mod_time(0), length(0), checksum() {} - - const char *name; - dw_sleb128_t dir_idx; - dw_sleb128_t mod_time; - dw_sleb128_t length; - llvm::MD5::MD5Result checksum; - }; - - // Prologue - struct Prologue { - - Prologue() - : total_length(0), version(0), prologue_length(0), min_inst_length(0), - default_is_stmt(0), line_base(0), line_range(0), opcode_base(0), - standard_opcode_lengths(), include_directories(), file_names() {} - - typedef std::shared_ptr<Prologue> shared_ptr; - - uint32_t total_length; // The size in bytes of the statement information for - // this compilation unit (not including the - // total_length field itself). - uint16_t - version; // Version identifier for the statement information format. - - uint8_t address_size; - uint8_t segment_selector_size; - - uint32_t prologue_length; // The number of bytes following the - // prologue_length field to the beginning of the - // first byte of the statement program itself. - uint8_t min_inst_length; // The size in bytes of the smallest target machine - // instruction. Statement program opcodes that - // alter the address register first multiply their - // operands by this value. - uint8_t maximum_operations_per_instruction; // New in DWARF4. The maximum - // number of individual - // operations that may be - // encoded in an instruction. - uint8_t default_is_stmt; // The initial value of theis_stmtregister. - int8_t line_base; // This parameter affects the meaning of the special - // opcodes. See below. - uint8_t line_range; // This parameter affects the meaning of the special - // opcodes. See below. - uint8_t opcode_base; // The number assigned to the first special opcode. - std::vector<uint8_t> standard_opcode_lengths; - std::vector<const char *> include_directories; - std::vector<FileNameEntry> file_names; - - int32_t MaxLineIncrementForSpecialOpcode() const { - return line_base + (int8_t)line_range - 1; - } - bool IsValid() const; - // void Append(BinaryStreamBuf& buff) const; - void Dump(lldb_private::Log *log); - void Clear() { - total_length = version = prologue_length = min_inst_length = line_base = - line_range = opcode_base = 0; - line_base = 0; - standard_opcode_lengths.clear(); - include_directories.clear(); - file_names.clear(); - } - bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir, - lldb_private::FileSpec::Style style, - lldb_private::FileSpec &file) const; - }; - - // Standard .debug_line state machine structure - struct Row { - typedef std::vector<Row> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - - Row(bool default_is_stmt = false); - virtual ~Row() {} - void PostAppend(); - void Reset(bool default_is_stmt); - void Dump(lldb_private::Log *log) const; - static void Insert(Row::collection &state_coll, const Row &state); - - dw_addr_t address; // The program-counter value corresponding to a machine - // instruction generated by the compiler. - uint32_t line; // An unsigned integer indicating a source line number. Lines - // are numbered beginning at 1. The compiler may emit the - // value 0 in cases where an instruction cannot be attributed - // to any source line. - uint16_t column; // An unsigned integer indicating a column number within a - // source line. Columns are numbered beginning at 1. The - // value 0 is reserved to indicate that a statement begins - // at the 'left edge' of the line. - uint16_t file; // An unsigned integer indicating the identity of the source - // file corresponding to a machine instruction. - uint8_t is_stmt : 1, // A boolean indicating that the current instruction is - // the beginning of a statement. - basic_block : 1, // A boolean indicating that the current instruction is - // the beginning of a basic block. - end_sequence : 1, // A boolean indicating that the current address is - // that of the first byte after the end of a sequence - // of target machine instructions. - prologue_end : 1, // A boolean indicating that the current address is - // one (of possibly many) where execution should be - // suspended for an entry breakpoint of a function. - epilogue_begin : 1; // A boolean indicating that the current address is - // one (of possibly many) where execution should be - // suspended for an exit breakpoint of a function. - uint32_t isa; // An unsigned integer whose value encodes the applicable - // instruction set architecture for the current instruction. - }; - - // LineTable - struct LineTable { - typedef std::shared_ptr<LineTable> shared_ptr; - - LineTable() : prologue(), rows() {} - - void AppendRow(const DWARFDebugLine::Row &state); - void Clear() { - prologue.reset(); - rows.clear(); - } - - uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const; - - Prologue::shared_ptr prologue; - Row::collection rows; - }; - - // State - struct State : public Row { - typedef void (*Callback)(dw_offset_t offset, const State &state, - void *userData); - - // Special row codes used when calling the callback - enum { StartParsingLineTable = 0, DoneParsingLineTable = -1 }; - - State(Prologue::shared_ptr &prologue_sp, lldb_private::Log *log, - Callback callback, void *userData); - - void AppendRowToMatrix(dw_offset_t offset); - - void Finalize(dw_offset_t offset); - - void Reset(); - - Prologue::shared_ptr prologue; - lldb_private::Log *log; - Callback callback; // Callback function that gets called each time an entry - // is to be added to the matrix - void *callbackUserData; - int row; // The row number that starts at zero for the prologue, and - // increases for each row added to the matrix - private: - DISALLOW_COPY_AND_ASSIGN(State); - }; - - static bool - ParseSupportFiles(const lldb::ModuleSP &module_sp, - const lldb_private::DWARFDataExtractor &debug_line_data, - dw_offset_t stmt_list, - lldb_private::FileSpecList &support_files, - DWARFUnit *dwarf_cu); - static bool - ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, Prologue *prologue, - DWARFUnit *dwarf_cu = nullptr); - static bool - ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, State::Callback callback, - void *userData, DWARFUnit *dwarf_cu); - static bool - ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data, - lldb::offset_t *offset_ptr, LineTable *line_table, - DWARFUnit *dwarf_cu); - static void Parse(const lldb_private::DWARFDataExtractor &debug_line_data, - DWARFDebugLine::State::Callback callback, void *userData); - // static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue, - // const DWARFDebugLine::Row::collection& state_coll, const uint32_t - // addr_size, BinaryStreamBuf &debug_line_data); - - DWARFDebugLine() : m_lineTableMap() {} - - void Parse(const lldb_private::DWARFDataExtractor &debug_line_data); - void ParseIfNeeded(const lldb_private::DWARFDataExtractor &debug_line_data); - LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const; - -protected: - typedef std::map<dw_offset_t, LineTable::shared_ptr> LineTableMap; - typedef LineTableMap::iterator LineTableIter; - typedef LineTableMap::const_iterator LineTableConstIter; - - LineTableMap m_lineTableMap; -}; - -#endif // SymbolFileDWARF_DWARFDebugLine_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 207c71211c9a..0b08fa09f906 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -123,11 +123,6 @@ bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu, return false; } -uint64_t DWARFDebugRanges::GetOffset(size_t Index) const { - lldbassert(false && "DW_FORM_rnglistx is not present before DWARF5"); - return 0; -} - bool DWARFDebugRngLists::ExtractRangeList( const DWARFDataExtractor &data, uint8_t addrSize, lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h index baf2667f0afe..c398259056b3 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -24,7 +24,6 @@ public: virtual void Extract(lldb_private::DWARFContext &context) = 0; virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const = 0; - virtual uint64_t GetOffset(size_t Index) const = 0; }; class DWARFDebugRanges final : public DWARFDebugRangesBase { @@ -34,7 +33,6 @@ public: void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; - uint64_t GetOffset(size_t Index) const override; static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor &debug_ranges_data, @@ -62,7 +60,7 @@ public: void Extract(lldb_private::DWARFContext &context) override; bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override; - uint64_t GetOffset(size_t Index) const override; + uint64_t GetOffset(size_t Index) const; protected: bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index d0d70dd5123e..6501ac27f27d 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -23,7 +23,7 @@ class DWARFDeclContext { public: struct Entry { - Entry() : tag(0), name(nullptr) {} + Entry() : tag(llvm::dwarf::DW_TAG_null), name(nullptr) {} Entry(dw_tag_t t, const char *n) : tag(t), name(n) {} bool NameMatches(const Entry &rhs) const { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp index 3bf0bb088227..2ae1bbc9f507 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp @@ -59,6 +59,8 @@ const char *DW_OP_value_to_name(uint32_t val) { } DRC_class DW_OP_value_to_class(uint32_t val) { + // FIXME: If we just used llvm's DWARFExpression printer, we could delete + // all this code (and more in lldb's DWARFExpression.cpp). switch (val) { case 0x03: return DRC_ONEOPERAND; @@ -358,6 +360,8 @@ DRC_class DW_OP_value_to_class(uint32_t val) { return DRC_DWARFv3 | DRC_ONEOPERAND; case 0x9a: return DRC_DWARFv3 | DRC_ONEOPERAND; + case 0xa3: /* DW_OP_entry_value */ + return DRC_TWOOPERANDS; case 0xf0: return DRC_ZEROOPERANDS; /* DW_OP_APPLE_uninit */ case 0xe0: diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 33e83d1fe57f..9964cf4b893c 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -438,7 +438,7 @@ lldb::ByteOrder DWARFUnit::GetByteOrder() const { return m_dwarf.GetObjectFile()->GetByteOrder(); } -TypeSystem *DWARFUnit::GetTypeSystem() { +llvm::Expected<TypeSystem &> DWARFUnit::GetTypeSystem() { return m_dwarf.GetTypeSystemForLanguage(GetLanguageType()); } @@ -540,19 +540,15 @@ void DWARFUnit::ParseProducerInfo() { } else if (strstr(producer_cstr, "clang")) { static RegularExpression g_clang_version_regex( llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); - RegularExpression::Match regex_match(3); + llvm::SmallVector<llvm::StringRef, 4> matches; if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), - ®ex_match)) { - std::string str; - if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) - m_producer_version_major = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); - if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) - m_producer_version_minor = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); - if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) - m_producer_version_update = - StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); + &matches)) { + m_producer_version_major = + StringConvert::ToUInt32(matches[1].str().c_str(), UINT32_MAX, 10); + m_producer_version_minor = + StringConvert::ToUInt32(matches[2].str().c_str(), UINT32_MAX, 10); + m_producer_version_update = + StringConvert::ToUInt32(matches[3].str().c_str(), UINT32_MAX, 10); } m_producer = eProducerClang; } else if (strstr(producer_cstr, "GNU")) @@ -870,7 +866,7 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const { llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) const { - const DWARFDebugRangesBase *debug_rnglists = m_dwarf.GetDebugRngLists(); + const DWARFDebugRngLists *debug_rnglists = m_dwarf.GetDebugRngLists(); if (!debug_rnglists) return llvm::make_error<llvm::object::GenericBinaryError>( "No debug_rnglists section"); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 8aa1e449f3ed..87e0de283de4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -153,7 +153,7 @@ public: lldb::ByteOrder GetByteOrder() const; - lldb_private::TypeSystem *GetTypeSystem(); + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystem(); const DWARFDebugAranges &GetFunctionAranges(); diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index 9746ad76c930..007ef2e05e59 100644 --- a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -24,7 +24,7 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, return llvm::make_error<llvm::StringError>("debug info null", llvm::inconvertibleErrorCode()); } - auto index_up = llvm::make_unique<DebugNames>(debug_names.GetAsLLVM(), + auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVM(), debug_str.GetAsLLVM()); if (llvm::Error E = index_up->extract()) return std::move(E); @@ -105,7 +105,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, if (!regex.Execute(nte.getString())) continue; - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { if (entry_or->tag() != DW_TAG_variable) @@ -125,7 +125,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, uint64_t cu_offset = cu.GetOffset(); for (const DebugNames::NameIndex &ni: *m_debug_names_up) { for (DebugNames::NameTableEntry nte: ni) { - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { if (entry_or->tag() != DW_TAG_variable) @@ -248,7 +248,7 @@ void DebugNamesDWARFIndex::GetFunctions(const RegularExpression ®ex, if (!regex.Execute(nte.getString())) continue; - uint32_t entry_offset = nte.getEntryOffset(); + uint64_t entry_offset = nte.getEntryOffset(); llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { Tag tag = entry_or->tag(); diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index 62b0ad37a9fc..88a29f4a2672 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -125,7 +125,7 @@ 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) { // 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 + // the atom type for the array, in this case we have an array of DIE offsets. AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4); } @@ -208,9 +208,10 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data, const uint32_t atom_count = data.GetU32(&offset); if (atom_count == 0x00060003u) { - // Old format, deal with contents of old pre-release format - while (data.GetU32(&offset)) + // Old format, deal with contents of old pre-release format. + while (data.GetU32(&offset)) { /* do nothing */; + } // Hardcode to the only known value for now. AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4); @@ -226,7 +227,7 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data, size_t DWARFMappedHash::Prologue::GetByteSize() const { // Add an extra count to the atoms size for the zero termination Atom that - // gets written to disk + // gets written to disk. return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); } @@ -286,7 +287,7 @@ bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data, break; default: - // We can always skip atoms we don't know about + // We can always skip atoms we don't know about. break; } } @@ -308,8 +309,8 @@ DWARFMappedHash::MemoryTable::GetStringForKeyType(KeyType key) const { bool DWARFMappedHash::MemoryTable::ReadHashData(uint32_t hash_data_offset, HashData &hash_data) const { lldb::offset_t offset = hash_data_offset; - offset += 4; // Skip string table offset that contains offset of hash name in - // .debug_str + // Skip string table offset that contains offset of hash name in .debug_str. + offset += 4; const uint32_t count = m_data.GetU32(&offset); if (count > 0) { hash_data.resize(count); @@ -335,7 +336,7 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( return eResultEndOfHashData; // There definitely should be a string for this string offset, if there - // isn't, there is something wrong, return and error + // isn't, there is something wrong, return and error. const char *strp_cstr = m_string_table.PeekCStr(pair.key); if (strp_cstr == nullptr) { *hash_data_offset_ptr = UINT32_MAX; @@ -345,9 +346,8 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( const uint32_t count = m_data.GetU32(hash_data_offset_ptr); const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && - m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, - min_total_hash_data_size)) { + if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, + min_total_hash_data_size)) { // We have at least one HashData entry, and we have enough data to parse at // least "count" HashData entries. @@ -370,21 +370,22 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( if (match) pair.value.push_back(die_info); } else { - // Something went wrong while reading the data + // Something went wrong while reading the data. *hash_data_offset_ptr = UINT32_MAX; return eResultError; } } } // Return the correct response depending on if the string matched or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup - // results! - else - return eResultKeyMismatch; // The key doesn't match, this function will - // get called - // again for the next key/value or the key terminator which in our case is - // a zero .debug_str offset. + if (match) { + // The key (cstring) matches and we have lookup results! + return eResultKeyMatch; + } else { + // The key doesn't match, this function will get called again for the + // next key/value or the key terminator which in our case is a zero + // .debug_str offset. + return eResultKeyMismatch; + } } else { *hash_data_offset_ptr = UINT32_MAX; return eResultError; @@ -402,7 +403,7 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( return eResultEndOfHashData; // There definitely should be a string for this string offset, if there - // isn't, there is something wrong, return and error + // isn't, there is something wrong, return and error. const char *strp_cstr = m_string_table.PeekCStr(pair.key); if (strp_cstr == nullptr) return eResultError; @@ -410,9 +411,8 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( const uint32_t count = m_data.GetU32(hash_data_offset_ptr); const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); - if (count > 0 && - m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, - min_total_hash_data_size)) { + if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr, + min_total_hash_data_size)) { const bool match = regex.Execute(llvm::StringRef(strp_cstr)); if (!match && m_header.header_data.HashDataHasFixedByteSize()) { @@ -438,14 +438,15 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( } } // Return the correct response depending on if the string matched or not... - if (match) - return eResultKeyMatch; // The key (cstring) matches and we have lookup - // results! - else - return eResultKeyMismatch; // The key doesn't match, this function will - // get called - // again for the next key/value or the key terminator which in our case is - // a zero .debug_str offset. + if (match) { + // The key (cstring) matches and we have lookup results! + return eResultKeyMatch; + } else { + // The key doesn't match, this function will get called again for the + // next key/value or the key terminator which in our case is a zero + // .debug_str offset. + return eResultKeyMismatch; + } } else { *hash_data_offset_ptr = UINT32_MAX; return eResultError; @@ -466,7 +467,7 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex( if (prev_hash_data_offset == hash_data_offset) break; - // Check the result of getting our hash data + // Check the result of getting our hash data. switch (hash_result) { case eResultKeyMatch: case eResultKeyMismatch: diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index a01612b59528..56d9bc548877 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -24,37 +24,41 @@ class DWARFMappedHash { public: enum AtomType : uint16_t { eAtomTypeNULL = 0u, - eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding - eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that - // contains the item in question - eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 - // (if no tags exceed 255) or DW_FORM_data2 - eAtomTypeNameFlags = 4u, // Flags from enum NameFlags - eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags, - eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name - // (since all hash entries are basename only) - // For example a type like "std::vector<int>::iterator" would have a name of - // "iterator" - // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not - // have to pull - // in debug info for a type when we know the fully qualified name. + /// DIE offset, check form for encoding. + eAtomTypeDIEOffset = 1u, + /// DIE offset of the compiler unit header that contains the item in + /// question. + eAtomTypeCUOffset = 2u, + /// DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed + /// 255) or DW_FORM_data2. + eAtomTypeTag = 3u, + // Flags from enum NameFlags. + eAtomTypeNameFlags = 4u, + // Flags from enum TypeFlags. + eAtomTypeTypeFlags = 5u, + /// A 32 bit hash of the full qualified name (since all hash entries are + /// basename only) For example a type like "std::vector<int>::iterator" + /// would have a name of "iterator" and a 32 bit hash for + /// "std::vector<int>::iterator" to allow us to not have to pull in debug + /// info for a type when we know the fully qualified name. + eAtomTypeQualNameHash = 6u }; - // Bit definitions for the eAtomTypeTypeFlags flags + /// Bit definitions for the eAtomTypeTypeFlags flags. enum TypeFlags { - // Always set for C++, only set for ObjC if this is the - // @implementation for class + /// Always set for C++, only set for ObjC if this is the + /// @implementation for class. eTypeFlagClassIsImplementation = (1u << 1) }; struct DIEInfo { dw_offset_t die_offset = DW_INVALID_OFFSET; - dw_tag_t tag = 0; + dw_tag_t tag = llvm::dwarf::DW_TAG_null; - /// Any flags for this DIEInfo + /// Any flags for this DIEInfo. uint32_t type_flags = 0; - /// A 32 bit hash of the fully qualified name + /// A 32 bit hash of the fully qualified name. uint32_t qualified_name_hash = 0; DIEInfo() = default; @@ -94,7 +98,7 @@ public: bool HashDataHasFixedByteSize() const; - // DIE offset base so die offsets in hash_data can be CU relative + /// 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; @@ -113,8 +117,8 @@ public: lldb::offset_t *offset_ptr, DIEInfo &hash_data) const; }; - // A class for reading and using a saved hash table from a block of data - // in memory + /// A class for reading and using a saved hash table from a block of data in + /// memory. class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray> { diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index e2ddcfc5d64b..c982d59c2830 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -8,6 +8,7 @@ #include "SymbolFileDWARF.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" @@ -43,7 +44,7 @@ #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" @@ -58,7 +59,6 @@ #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" -#include "DWARFDebugLine.h" #include "DWARFDebugMacro.h" #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" @@ -72,6 +72,7 @@ #include "SymbolFileDWARFDwo.h" #include "SymbolFileDWARFDwp.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Support/FileSystem.h" #include <algorithm> @@ -113,18 +114,12 @@ using namespace lldb_private; namespace { -static constexpr PropertyDefinition g_properties[] = { - {"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr, - {}, - "If the DW_AT_comp_dir matches any of these paths the symbolic " - "links will be resolved at DWARF parse time."}, - {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, {}, - "Ignore indexes present in the object files and always index DWARF " - "manually."}}; +#define LLDB_PROPERTIES_symbolfiledwarf +#include "SymbolFileDWARFProperties.inc" enum { - ePropertySymLinkPaths, - ePropertyIgnoreIndexes, +#define LLDB_PROPERTIES_symbolfiledwarf +#include "SymbolFileDWARFPropertiesEnum.inc" }; class PluginProperties : public Properties { @@ -135,7 +130,7 @@ public: PluginProperties() { m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_properties); + m_collection_sp->Initialize(g_symbolfiledwarf_properties); } FileSpecList GetSymLinkPaths() { @@ -159,7 +154,66 @@ static const SymbolFileDWARFPropertiesSP &GetGlobalPluginProperties() { return g_settings_sp; } -} // anonymous namespace end +} // namespace + +static const llvm::DWARFDebugLine::LineTable * +ParseLLVMLineTable(lldb_private::DWARFContext &context, + llvm::DWARFDebugLine &line, dw_offset_t line_offset, + dw_offset_t unit_offset) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + + llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM(); + llvm::DWARFContext &ctx = context.GetAsLLVM(); + llvm::Expected<const llvm::DWARFDebugLine::LineTable *> line_table = + line.getOrParseLineTable( + data, line_offset, ctx, nullptr, [&](llvm::Error e) { + LLDB_LOG_ERROR(log, std::move(e), + "SymbolFileDWARF::ParseLineTable failed to parse"); + }); + + if (!line_table) { + LLDB_LOG_ERROR(log, line_table.takeError(), + "SymbolFileDWARF::ParseLineTable failed to parse"); + return nullptr; + } + return *line_table; +} + +static FileSpecList ParseSupportFilesFromPrologue( + const lldb::ModuleSP &module, + const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style, + llvm::StringRef compile_dir = {}, FileSpec first_file = {}) { + FileSpecList support_files; + support_files.Append(first_file); + + const size_t number_of_files = prologue.FileNames.size(); + for (size_t idx = 1; idx <= number_of_files; ++idx) { + std::string original_file; + if (!prologue.getFileNameByIndex( + idx, compile_dir, + llvm::DILineInfoSpecifier::FileLineInfoKind::Default, original_file, + style)) { + // Always add an entry so the indexes remain correct. + support_files.EmplaceBack(); + continue; + } + + std::string remapped_file; + if (!prologue.getFileNameByIndex( + idx, compile_dir, + llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + remapped_file, style)) { + // Always add an entry so the indexes remain correct. + support_files.EmplaceBack(original_file, style); + continue; + } + + module->RemapSourceFile(llvm::StringRef(original_file), remapped_file); + support_files.EmplaceBack(remapped_file, style); + } + + return support_files; +} FileSpecList SymbolFileDWARF::GetSymlinkPaths() { return GetGlobalPluginProperties()->GetSymLinkPaths(); @@ -197,20 +251,16 @@ const char *SymbolFileDWARF::GetPluginDescriptionStatic() { return "DWARF and DWARF3 debug symbol file reader."; } -SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileDWARF(obj_file, +SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileDWARF(std::move(objfile_sp), /*dwo_section_list*/ nullptr); } -TypeList *SymbolFileDWARF::GetTypeList() { - // This method can be called without going through the symbol vendor so we - // need to lock the module. +TypeList &SymbolFileDWARF::GetTypeList() { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) return debug_map_symfile->GetTypeList(); - else - return m_obj_file->GetModule()->GetTypeList(); + return SymbolFile::GetTypeList(); } void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, dw_offset_t max_die_offset, uint32_t type_mask, @@ -264,6 +314,8 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer) != 0; break; + default: + break; } if (add_type) { @@ -283,11 +335,11 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, } } -size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, - TypeClass type_mask, TypeList &type_list) +void SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, + TypeClass type_mask, TypeList &type_list) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); TypeSet type_set; CompileUnit *comp_unit = nullptr; @@ -297,8 +349,8 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, if (comp_unit) { dwarf_cu = GetDWARFCompileUnit(comp_unit); - if (dwarf_cu == nullptr) - return 0; + if (!dwarf_cu) + return; GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(), dwarf_cu->GetNextUnitOffset(), type_mask, type_set); } else { @@ -315,16 +367,13 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, } std::set<CompilerType> compiler_type_set; - size_t num_types_added = 0; for (Type *type : type_set) { CompilerType compiler_type = type->GetForwardCompilerType(); if (compiler_type_set.find(compiler_type) == compiler_type_set.end()) { compiler_type_set.insert(compiler_type); type_list.Insert(type->shared_from_this()); - ++num_types_added; } } - return num_types_added; } // Gets the first parent that is a lexical block, function or inlined @@ -342,19 +391,21 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) { case DW_TAG_inlined_subroutine: case DW_TAG_lexical_block: return die; + default: + break; } } return DWARFDIE(); } -SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile, +SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp, SectionList *dwo_section_list) - : SymbolFile(objfile), + : SymbolFile(std::move(objfile_sp)), UserID(0x7fffffff00000000), // Used by SymbolFileDWARFDebugMap to // when this class parses .o files to // contain the .o file index/ID m_debug_map_module_wp(), m_debug_map_symfile(nullptr), - m_context(objfile->GetModule()->GetSectionList(), dwo_section_list), + m_context(m_objfile_sp->GetModule()->GetSectionList(), dwo_section_list), m_data_debug_loc(), m_abbr(), m_info(), m_fetched_external_modules(false), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_unique_ast_type_map() {} @@ -374,17 +425,17 @@ UniqueDWARFASTTypeMap &SymbolFileDWARF::GetUniqueDWARFASTTypeMap() { return m_unique_ast_type_map; } -TypeSystem *SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - TypeSystem *type_system; - if (debug_map_symfile) { - type_system = debug_map_symfile->GetTypeSystemForLanguage(language); - } else { - type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); +llvm::Expected<TypeSystem &> +SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) { + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) + return debug_map_symfile->GetTypeSystemForLanguage(language); + + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); } - return type_system; + return type_system_or_err; } void SymbolFileDWARF::InitializeObject() { @@ -420,7 +471,7 @@ void SymbolFileDWARF::InitializeObject() { } } - m_index = llvm::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), + m_index = std::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), DebugInfo()); } @@ -430,9 +481,9 @@ bool SymbolFileDWARF::SupportedVersion(uint16_t version) { uint32_t SymbolFileDWARF::CalculateAbilities() { uint32_t abilities = 0; - if (m_obj_file != nullptr) { + if (m_objfile_sp != nullptr) { const Section *section = nullptr; - const SectionList *section_list = m_obj_file->GetSectionList(); + const SectionList *section_list = m_objfile_sp->GetSectionList(); if (section_list == nullptr) return 0; @@ -462,10 +513,12 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { abbrev->GetUnsupportedForms(invalid_forms); if (!invalid_forms.empty()) { StreamString error; - error.Printf("unsupported DW_FORM value%s:", invalid_forms.size() > 1 ? "s" : ""); + error.Printf("unsupported DW_FORM value%s:", + invalid_forms.size() > 1 ? "s" : ""); for (auto form : invalid_forms) error.Printf(" %#x", form); - m_obj_file->GetModule()->ReportWarning("%s", error.GetString().str().c_str()); + m_objfile_sp->GetModule()->ReportWarning( + "%s", error.GetString().str().c_str()); return 0; } } @@ -477,10 +530,10 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { debug_line_file_size = section->GetFileSize(); } else { const char *symfile_dir_cstr = - m_obj_file->GetFileSpec().GetDirectory().GetCString(); + m_objfile_sp->GetFileSpec().GetDirectory().GetCString(); if (symfile_dir_cstr) { if (strcasestr(symfile_dir_cstr, ".dsym")) { - if (m_obj_file->GetType() == ObjectFile::eTypeDebugInfo) { + if (m_objfile_sp->GetType() == ObjectFile::eTypeDebugInfo) { // We have a dSYM file that didn't have a any debug info. If the // string table has a size of 1, then it was made from an // executable with no debug info, or from an executable that was @@ -489,7 +542,7 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { section_list->FindSectionByType(eSectionTypeDWARFDebugStr, true) .get(); if (section && section->GetFileSize() == 1) { - m_obj_file->GetModule()->ReportWarning( + m_objfile_sp->GetModule()->ReportWarning( "empty dSYM file detected, dSYM was created with an " "executable with no debug info."); } @@ -519,7 +572,7 @@ SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type, void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { - ModuleSP module_sp(m_obj_file->GetModule()); + ModuleSP module_sp(m_objfile_sp->GetModule()); const SectionList *section_list = module_sp->GetSectionList(); if (!section_list) return; @@ -529,7 +582,7 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, return; data.Clear(); - m_obj_file->ReadSectionData(section_sp.get(), data); + m_objfile_sp->ReadSectionData(section_sp.get(), data); } const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() { @@ -556,7 +609,7 @@ DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { if (debug_abbrev_data.GetByteSize() == 0) return nullptr; - auto abbr = llvm::make_unique<DWARFDebugAbbrev>(); + auto abbr = std::make_unique<DWARFDebugAbbrev>(); llvm::Error error = abbr->parse(debug_abbrev_data); if (error) { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); @@ -579,7 +632,7 @@ DWARFDebugInfo *SymbolFileDWARF::DebugInfo() { Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); if (m_context.getOrLoadDebugInfoData().GetByteSize() > 0) - m_info = llvm::make_unique<DWARFDebugInfo>(*this, m_context); + m_info = std::make_unique<DWARFDebugInfo>(*this, m_context); } return m_info.get(); } @@ -604,7 +657,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { return nullptr; } -DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { +DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() { if (!m_ranges) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, @@ -619,7 +672,7 @@ DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRanges() { return m_ranges.get(); } -DWARFDebugRangesBase *SymbolFileDWARF::GetDebugRngLists() { +DWARFDebugRngLists *SymbolFileDWARF::GetDebugRngLists() { if (!m_rnglists) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, @@ -648,7 +701,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { cu_sp = m_debug_map_symfile->GetCompileUnit(this); dwarf_cu.SetUserData(cu_sp.get()); } else { - ModuleSP module_sp(m_obj_file->GetModule()); + ModuleSP module_sp(m_objfile_sp->GetModule()); if (module_sp) { const DWARFDIE cu_die = dwarf_cu.DIE(); if (cu_die) { @@ -677,8 +730,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { dwarf_cu.SetUserData(cu_sp.get()); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - dwarf_cu.GetID(), cu_sp); + SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp); } } } @@ -715,7 +767,7 @@ llvm::Optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { return m_lldb_cu_to_dwarf_unit[cu_idx]; } -uint32_t SymbolFileDWARF::GetNumCompileUnits() { +uint32_t SymbolFileDWARF::CalculateNumCompileUnits() { DWARFDebugInfo *info = DebugInfo(); if (!info) return 0; @@ -741,17 +793,21 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, const DWARFDIE &die) { ASSERT_MODULE_LOCK(this); - if (die.IsValid()) { - TypeSystem *type_system = - GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - - if (type_system) { - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); - if (dwarf_ast) - return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); - } + if (!die.IsValid()) + return nullptr; + + auto type_system_or_err = + GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse function"); + return nullptr; } - return nullptr; + DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); + if (!dwarf_ast) + return nullptr; + + return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); } bool SymbolFileDWARF::FixupAddress(Address &addr) { @@ -763,7 +819,7 @@ bool SymbolFileDWARF::FixupAddress(Address &addr) { return true; } lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetLanguageType(); @@ -772,7 +828,7 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (!dwarf_cu) return 0; @@ -790,21 +846,23 @@ size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { return functions_added; } +void SymbolFileDWARF::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) { + UpdateExternalModuleListIfNeeded(); + + for (auto &p : m_external_type_modules) { + ModuleSP module = p.second; + f(module); + for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) + module->GetCompileUnitAtIndex(i)->ForEachExternalModule(f); + } +} + bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { - ASSERT_MODULE_LOCK(this); - if (DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit)) { - const dw_offset_t stmt_list = unit->GetLineTableOffset(); - if (stmt_list != DW_INVALID_OFFSET) { - // All file indexes in DWARF are one based and a file of index zero is - // supposed to be the compile unit itself. - support_files.Append(comp_unit); - return DWARFDebugLine::ParseSupportFiles(comp_unit.GetModule(), - m_context.getOrLoadLineData(), - stmt_list, support_files, unit); - } - } - return false; + if (!comp_unit.GetLineTable()) + ParseLineTable(comp_unit); + return true; } FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { @@ -833,16 +891,26 @@ SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { auto iter_bool = m_type_unit_support_files.try_emplace(offset); FileSpecList &list = iter_bool.first->second; if (iter_bool.second) { - list.Append(FileSpec()); - DWARFDebugLine::ParseSupportFiles(GetObjectFile()->GetModule(), - m_context.getOrLoadLineData(), offset, - list, &tu); + uint64_t line_table_offset = offset; + llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM(); + llvm::DWARFContext &ctx = m_context.GetAsLLVM(); + llvm::DWARFDebugLine::Prologue prologue; + llvm::Error error = prologue.parse(data, &line_table_offset, ctx); + if (error) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG_ERROR(log, std::move(error), + "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse " + "the line table prologue"); + } else { + list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), + prologue, tu.GetPathStyle()); + } } return list; } bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetIsOptimized(); @@ -852,7 +920,7 @@ bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { bool SymbolFileDWARF::ParseImportedModules( const lldb_private::SymbolContext &sc, std::vector<SourceModule> &imported_modules) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); assert(sc.comp_unit); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (!dwarf_cu) @@ -901,102 +969,63 @@ bool SymbolFileDWARF::ParseImportedModules( return true; } -struct ParseDWARFLineTableCallbackInfo { - LineTable *line_table; - std::unique_ptr<LineSequence> sequence_up; - lldb::addr_t addr_mask; -}; - -// ParseStatementTableCallback -static void ParseDWARFLineTableCallback(dw_offset_t offset, - const DWARFDebugLine::State &state, - void *userData) { - if (state.row == DWARFDebugLine::State::StartParsingLineTable) { - // Just started parsing the line table - } else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) { - // Done parsing line table, nothing to do for the cleanup - } else { - ParseDWARFLineTableCallbackInfo *info = - (ParseDWARFLineTableCallbackInfo *)userData; - LineTable *line_table = info->line_table; - - // If this is our first time here, we need to create a sequence container. - if (!info->sequence_up) { - info->sequence_up.reset(line_table->CreateLineSequenceContainer()); - assert(info->sequence_up.get()); - } - line_table->AppendLineEntryToSequence( - info->sequence_up.get(), state.address & info->addr_mask, state.line, - state.column, state.file, state.is_stmt, state.basic_block, - state.prologue_end, state.epilogue_begin, state.end_sequence); - if (state.end_sequence) { - // First, put the current sequence into the line table. - line_table->InsertSequence(info->sequence_up.get()); - // Then, empty it to prepare for the next sequence. - info->sequence_up->Clear(); - } - } -} - bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (comp_unit.GetLineTable() != nullptr) return true; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); - if (dwarf_cu) { - const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); - if (dwarf_cu_die) { - const dw_offset_t cu_line_offset = - dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, - DW_INVALID_OFFSET); - if (cu_line_offset != DW_INVALID_OFFSET) { - std::unique_ptr<LineTable> line_table_up(new LineTable(&comp_unit)); - if (line_table_up) { - ParseDWARFLineTableCallbackInfo info; - info.line_table = line_table_up.get(); - - /* - * MIPS: - * The SymbolContext may not have a valid target, thus we may not be - * able - * to call Address::GetOpcodeLoadAddress() which would clear the bit - * #0 - * for MIPS. Use ArchSpec to clear the bit #0. - */ - switch (GetObjectFile()->GetArchitecture().GetMachine()) { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - info.addr_mask = ~((lldb::addr_t)1); - break; - default: - info.addr_mask = ~((lldb::addr_t)0); - break; - } + if (!dwarf_cu) + return false; - lldb::offset_t offset = cu_line_offset; - DWARFDebugLine::ParseStatementTable( - m_context.getOrLoadLineData(), &offset, - ParseDWARFLineTableCallback, &info, dwarf_cu); - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); - if (debug_map_symfile) { - // We have an object file that has a line table with addresses that - // are not linked. We need to link the line table and convert the - // addresses that are relative to the .o file into addresses for - // the main executable. - comp_unit.SetLineTable( - debug_map_symfile->LinkOSOLineTable(this, line_table_up.get())); - } else { - comp_unit.SetLineTable(line_table_up.release()); - return true; - } - } - } + const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); + if (!dwarf_cu_die) + return false; + + const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned( + DW_AT_stmt_list, DW_INVALID_OFFSET); + if (cu_line_offset == DW_INVALID_OFFSET) + return false; + + llvm::DWARFDebugLine line; + const llvm::DWARFDebugLine::LineTable *line_table = ParseLLVMLineTable( + m_context, line, cu_line_offset, dwarf_cu->GetOffset()); + + if (!line_table) + return false; + + // FIXME: Rather than parsing the whole line table and then copying it over + // into LLDB, we should explore using a callback to populate the line table + // while we parse to reduce memory usage. + std::unique_ptr<LineTable> line_table_up = + std::make_unique<LineTable>(&comp_unit); + LineSequence *sequence = line_table_up->CreateLineSequenceContainer(); + for (auto &row : line_table->Rows) { + line_table_up->AppendLineEntryToSequence( + sequence, row.Address.Address, row.Line, row.Column, row.File, + row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin, + row.EndSequence); + if (row.EndSequence) { + line_table_up->InsertSequence(sequence); + sequence = line_table_up->CreateLineSequenceContainer(); } } - return false; + + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) { + // We have an object file that has a line table with addresses that are not + // linked. We need to link the line table and convert the addresses that + // are relative to the .o file into addresses for the main executable. + comp_unit.SetLineTable( + debug_map_symfile->LinkOSOLineTable(this, line_table_up.get())); + } else { + comp_unit.SetLineTable(line_table_up.release()); + } + + comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue( + comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(), + dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit))); + + return true; } lldb_private::DebugMacrosSP @@ -1022,7 +1051,7 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { } bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu == nullptr) @@ -1114,7 +1143,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( "0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64 ") which has a base that is less than the function's low PC " "0x%" PRIx64 ". Please file a bug and attach the file at the " - "start of this error message", + "start of this error message", block->GetID(), range_base, range.GetRangeEnd(), subprogram_low_pc); } @@ -1188,15 +1217,10 @@ bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) { } void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) { - TypeSystem *type_system = decl_ctx.GetTypeSystem(); - DWARFASTParser *ast_parser = type_system->GetDWARFParser(); - std::vector<DWARFDIE> decl_ctx_die_list = - ast_parser->GetDIEForDeclContext(decl_ctx); - - for (DWARFDIE decl_ctx_die : decl_ctx_die_list) - for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; - decl = decl.GetSibling()) - ast_parser->GetDeclForUIDFromDWARF(decl); + auto *type_system = decl_ctx.GetTypeSystem(); + if (type_system != nullptr) + type_system->GetDWARFParser()->EnsureAllDIEsInDeclContextHaveBeenParsed( + decl_ctx); } user_id_t SymbolFileDWARF::GetUID(DIERef ref) { @@ -1281,8 +1305,6 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) { CompilerDeclContext SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { - // This method can be called without going through the symbol vendor so we - // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIE(). See comments inside the @@ -1293,8 +1315,6 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { } Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { - // This method can be called without going through the symbol vendor so we - // need to lock the module. std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIE(). See comments inside the @@ -1341,8 +1361,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, // Get the type, which could be a forward declaration if (log) GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " - "resolve parent forward type for 0x%8.8x", + log, + "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' " + "resolve parent forward type for 0x%8.8x", die.GetOffset(), die.GetTagAsCString(), die.GetName(), decl_ctx_die.GetOffset()); } break; @@ -1504,7 +1525,6 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) { ->GetDIE(die_ref); } - DWARFDebugInfo *debug_info = DebugInfo(); if (debug_info) return debug_info->GetDIE(die_ref); @@ -1567,7 +1587,7 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (dwo_obj_file == nullptr) return nullptr; - return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); + return std::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); } void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -1607,7 +1627,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { } } dwo_module_spec.GetArchitecture() = - m_obj_file->GetModule()->GetArchitecture(); + m_objfile_sp->GetModule()->GetArchitecture(); // When LLDB loads "external" modules it looks at the presence of // DW_AT_GNU_dwo_name. However, when the already created module @@ -1621,8 +1641,8 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { // printed. However, as one can notice in this case we don't // actually need to try to load the already loaded module // (corresponding to .dwo) so we simply skip it. - if (m_obj_file->GetFileSpec().GetFileNameExtension() == ".dwo" && - llvm::StringRef(m_obj_file->GetFileSpec().GetPath()) + if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" && + llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath()) .endswith(dwo_module_spec.GetFileSpec().GetPath())) { continue; } @@ -1694,6 +1714,7 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::" @@ -1837,6 +1858,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, bool check_inlines, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 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; @@ -1849,7 +1871,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *dc_cu, full_match); if (check_inlines || file_spec_matches_cu_file_spec) { - SymbolContext sc(m_obj_file->GetModule()); + SymbolContext sc(m_objfile_sp->GetModule()); sc.comp_unit = dc_cu; uint32_t file_idx = UINT32_MAX; @@ -1961,9 +1983,16 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( } TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); - TypeSystem *type_system = GetTypeSystemForLanguage( + auto type_system_or_err = GetTypeSystemForLanguage( decl_ctx_type_system->GetMinimumLanguage(nullptr)); - if (decl_ctx_type_system == type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), + "Unable to match namespace decl using TypeSystem"); + return false; + } + + if (decl_ctx_type_system == &type_system_or_err.get()) return true; // The type systems match, return true // The namespace AST was valid, and it does not match... @@ -1976,9 +2005,10 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( return false; } -uint32_t SymbolFileDWARF::FindGlobalVariables( +void SymbolFileDWARF::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) @@ -1990,11 +2020,11 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( max_matches); if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); @@ -2012,7 +2042,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( const size_t num_die_matches = die_offsets.size(); if (num_die_matches) { SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); assert(sc.module_sp); // Loop invariant: Variables up to this index have been checked for context @@ -2081,12 +2111,12 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( name.GetCString(), static_cast<const void *>(parent_decl_ctx), max_matches, num_matches); } - return num_matches; } -uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, - uint32_t max_matches, - VariableList &variables) { +void SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, + uint32_t max_matches, + VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { @@ -2098,8 +2128,8 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, } DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); @@ -2108,7 +2138,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, m_index->GetGlobalVariables(regex, die_offsets); SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); assert(sc.module_sp); const size_t num_matches = die_offsets.size(); @@ -2132,9 +2162,6 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, m_index->ReportInvalidDIERef(die_ref, regex.GetText()); } } - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, @@ -2210,10 +2237,12 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx, return false; } -uint32_t SymbolFileDWARF::FindFunctions( - ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARF::FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + FunctionNameType name_type_mask, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (name = '%s')", name.AsCString()); @@ -2226,21 +2255,17 @@ uint32_t SymbolFileDWARF::FindFunctions( if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindFunctions (name=\"%s\", " - "name_type_mask=0x%x, append=%u, sc_list)", - name.GetCString(), name_type_mask, append); + log, + "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, sc_list)", + name.GetCString(), name_type_mask); } - // If we aren't appending the results to this list, then clear the list - if (!append) - sc_list.Clear(); - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; // If name is empty then we won't find anything. if (name.IsEmpty()) - return 0; + return; // Remember how many sc_list are in the list before we search in case we are // appending the results to a variable list. @@ -2255,7 +2280,7 @@ uint32_t SymbolFileDWARF::FindFunctions( std::vector<DWARFDIE> dies; m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies); - for (const DWARFDIE &die: dies) { + for (const DWARFDIE &die : dies) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); } @@ -2265,18 +2290,18 @@ uint32_t SymbolFileDWARF::FindFunctions( if (log && num_matches > 0) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindFunctions (name=\"%s\", " - "name_type_mask=0x%x, include_inlines=%d, append=%u, sc_list) => " - "%u", - name.GetCString(), name_type_mask, include_inlines, append, + log, + "SymbolFileDWARF::FindFunctions (name=\"%s\", " + "name_type_mask=0x%x, include_inlines=%d, sc_list) => %u", + name.GetCString(), name_type_mask, include_inlines, num_matches); } - return num_matches; } -uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (regex = '%s')", regex.GetText().str().c_str()); @@ -2285,22 +2310,13 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, if (log) { GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", - regex.GetText().str().c_str(), append); + log, "SymbolFileDWARF::FindFunctions (regex=\"%s\", sc_list)", + regex.GetText().str().c_str()); } - // If we aren't appending the results to this list, then clear the list - if (!append) - sc_list.Clear(); - DWARFDebugInfo *info = DebugInfo(); if (!info) - return 0; - - // Remember how many sc_list are in the list before we search in case we are - // appending the results to a variable list. - uint32_t original_size = sc_list.GetSize(); + return; DIEArray offsets; m_index->GetFunctions(regex, offsets); @@ -2315,9 +2331,6 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); } - - // Return the number of variable that were appended to the list - return sc_list.GetSize() - original_size; } void SymbolFileDWARF::GetMangledNamesForFunction( @@ -2345,156 +2358,141 @@ void SymbolFileDWARF::GetMangledNamesForFunction( } } -uint32_t SymbolFileDWARF::FindTypes( +void SymbolFileDWARF::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { - // If we aren't appending the results to this list, then clear the list - if (!append) - types.Clear(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Make sure we haven't already searched this SymbolFile before... if (searched_symbol_files.count(this)) - return 0; - else - searched_symbol_files.insert(this); + return; + + searched_symbol_files.insert(this); DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; + if (!info) + return; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { if (parent_decl_ctx) GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "%p (\"%s\"), append=%u, max_matches=%u, type_list)", + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " + "%p (\"%s\"), max_matches=%u, type_list)", name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches); + parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches); else GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " - "NULL, append=%u, max_matches=%u, type_list)", - name.GetCString(), append, max_matches); + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " + "NULL, max_matches=%u, type_list)", + name.GetCString(), max_matches); } if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; DIEArray die_offsets; m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - const uint32_t initial_types_size = types.GetSize(); - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - if (types.GetSize() >= max_matches) - break; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } - } - const uint32_t num_matches = types.GetSize() - initial_types_size; - if (log && num_matches) { - if (parent_decl_ctx) { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u", - name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), append, max_matches, - num_matches); - } else { - GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " - "= NULL, append=%u, max_matches=%u, type_list) => %u", - name.GetCString(), append, max_matches, num_matches); + for (size_t i = 0; i < num_die_matches; ++i) { + const DIERef &die_ref = die_offsets[i]; + DWARFDIE die = GetDIE(die_ref); + if (die) { + if (!DIEInDeclContext(parent_decl_ctx, die)) + continue; // The containing decl contexts don't match + + Type *matching_type = ResolveType(die, true, true); + if (matching_type) { + // We found a type pointer, now find the shared pointer form our type + // list + types.InsertUnique(matching_type->shared_from_this()); + if (types.GetSize() >= max_matches) + break; } + } else { + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); } - return num_matches; - } else { + } + + // Next search through the reachable Clang modules. This only applies for + // DWARF objects compiled with -gmodules that haven't been processed by + // dsymutil. + if (num_die_matches < max_matches) { UpdateExternalModuleListIfNeeded(); - for (const auto &pair : m_external_type_modules) { - ModuleSP external_module_sp = pair.second; - if (external_module_sp) { - SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); - if (sym_vendor) { - const uint32_t num_external_matches = - sym_vendor->FindTypes(name, parent_decl_ctx, append, max_matches, - searched_symbol_files, types); - if (num_external_matches) - return num_external_matches; - } - } - } + for (const auto &pair : m_external_type_modules) + if (ModuleSP external_module_sp = pair.second) + if (SymbolFile *sym_file = external_module_sp->GetSymbolFile()) + sym_file->FindTypes(name, parent_decl_ctx, max_matches, + searched_symbol_files, types); } - return 0; + if (log && types.GetSize()) { + if (parent_decl_ctx) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " + "= %p (\"%s\"), max_matches=%u, type_list) => %u", + name.GetCString(), static_cast<const void *>(parent_decl_ctx), + parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches, + types.GetSize()); + } else { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " + "= NULL, max_matches=%u, type_list) => %u", + name.GetCString(), max_matches, types.GetSize()); + } + } } -size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - if (!append) - types.Clear(); - - if (context.empty()) - return 0; +void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (pattern.empty()) + return; - ConstString name = context.back().name; + ConstString name = pattern.back().name; if (!name) - return 0; + return; DIEArray die_offsets; m_index->GetTypes(name, die_offsets); const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - size_t num_matches = 0; - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); + for (size_t i = 0; i < num_die_matches; ++i) { + const DIERef &die_ref = die_offsets[i]; + DWARFDIE die = GetDIE(die_ref); - if (die) { - std::vector<CompilerContext> die_context; - die.GetDeclContext(die_context); - if (die_context != context) - continue; - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - ++num_matches; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } + if (!die) { + m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); + continue; } - return num_matches; + if (!languages[die.GetCU()->GetLanguageType()]) + continue; + + llvm::SmallVector<CompilerContext, 4> die_context; + die.GetDeclContext(die_context); + if (!contextMatches(die_context, pattern)) + continue; + + if (Type *matching_type = ResolveType(die, true, true)) + // We found a type pointer, now find the shared pointer form our type + // list. + types.InsertUnique(matching_type->shared_from_this()); } - return 0; } CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext *parent_decl_ctx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { @@ -2536,8 +2534,9 @@ SymbolFileDWARF::FindNamespace(ConstString name, } if (log && namespace_decl_ctx) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => " - "CompilerDeclContext(%p/%p) \"%s\"", + log, + "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => " + "CompilerDeclContext(%p/%p) \"%s\"", name.GetCString(), static_cast<const void *>(namespace_decl_ctx.GetTypeSystem()), static_cast<const void *>(namespace_decl_ctx.GetOpaqueDeclContext()), @@ -2632,11 +2631,10 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) { return DWARFDIE(); } -Symbol * -SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { +Symbol *SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { Symbol *objc_class_symbol = nullptr; - if (m_obj_file) { - Symtab *symtab = m_obj_file->GetSymtab(); + if (m_objfile_sp) { + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { objc_class_symbol = symtab->FindFirstSymbolWithNameAndType( objc_class_name, eSymbolTypeObjCClass, Symtab::eDebugNo, @@ -2653,8 +2651,7 @@ SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { // worry about the debug map // DWARF file // if we are doing darwin DWARF in .o file debugging. -bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( - DWARFUnit *cu) { +bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu) { if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) { m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type()) @@ -2681,8 +2678,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type( // This function can be used when a DIE is found that is a forward declaration // DIE and we want to try and find a type that has the complete definition. TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( - const DWARFDIE &die, ConstString type_name, - bool must_be_implementation) { + const DWARFDIE &die, ConstString type_name, bool must_be_implementation) { TypeSP type_sp; @@ -2727,7 +2723,7 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( DEBUG_PRINTF("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", die.GetID(), - m_obj_file->GetFileSpec().GetFilename().AsCString( + m_objfile_sp->GetFileSpec().GetFilename().AsCString( "<Unknown>"), type_die.GetID(), type_cu->GetID()); @@ -2849,8 +2845,9 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( DWARF_LOG_LOOKUPS)); if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" - "s, qualified-name='%s')", + log, + "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%" + "s, qualified-name='%s')", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName()); } @@ -2863,10 +2860,18 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( // use this to ensure any matches we find are in a language that this // type system supports const LanguageType language = dwarf_decl_ctx.GetLanguage(); - TypeSystem *type_system = (language == eLanguageTypeUnknown) - ? nullptr - : GetTypeSystemForLanguage(language); - + TypeSystem *type_system = nullptr; + if (language != eLanguageTypeUnknown) { + auto type_system_or_err = GetTypeSystemForLanguage(language); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Cannot get TypeSystem for language {}", + Language::GetNameForLanguageType(language)); + } else { + type_system = &type_system_or_err.get(); + } + } if (num_matches) { for (size_t i = 0; i < num_matches; ++i) { const DIERef &die_ref = die_offsets[i]; @@ -2916,9 +2921,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( if (log) { GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') trying die=0x%8.8x (%s)", + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') trying die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), type_dwarf_decl_ctx.GetQualifiedName()); @@ -2937,9 +2943,10 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( std::string qualified_name; type_die.GetQualifiedName(qualified_name); GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') ignoring die=0x%8.8x (%s)", + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') ignoring die=0x%8.8x (%s)", DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), qualified_name.c_str()); @@ -2960,21 +2967,21 @@ TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, if (!die) return {}; - TypeSystem *type_system = + auto type_system_or_err = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); - if (!type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse type"); return {}; + } - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); + DWARFASTParser *dwarf_ast = type_system_or_err->GetDWARFParser(); if (!dwarf_ast) return {}; - Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); - TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr); + TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr); if (type_sp) { - TypeList *type_list = GetTypeList(); - if (type_list) - type_list->Insert(type_sp); + GetTypeList().Insert(type_sp); if (die.Tag() == DW_TAG_subprogram) { std::string scope_qualified_name(GetDeclContextForUID(die.GetID()) @@ -2995,12 +3002,21 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc, bool parse_siblings, bool parse_children) { size_t types_added = 0; DWARFDIE die = orig_die; + while (die) { + const dw_tag_t tag = die.Tag(); bool type_is_new = false; - if (ParseType(sc, die, &type_is_new).get()) { - if (type_is_new) - ++types_added; - } + + Tag dwarf_tag = static_cast<Tag>(tag); + + // TODO: Currently ParseTypeFromDWARF(...) which is called by ParseType(...) + // does not handle DW_TAG_subrange_type. It is not clear if this is a bug or + // not. + if (isType(dwarf_tag) && tag != DW_TAG_subrange_type) + ParseType(sc, die, &type_is_new); + + if (type_is_new) + ++types_added; if (parse_children && die.HasChildren()) { if (die.Tag() == DW_TAG_subprogram) { @@ -3020,7 +3036,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc, } size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompileUnit *comp_unit = func.GetCompileUnit(); lldbassert(comp_unit); @@ -3040,7 +3056,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { } size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t types_added = 0; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) { @@ -3056,7 +3072,7 @@ size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { } size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { - ASSERT_MODULE_LOCK(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (sc.comp_unit != nullptr) { DWARFDebugInfo *info = DebugInfo(); if (info == nullptr) @@ -3193,15 +3209,18 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location = DWARFExpression(module, debug_info_data, die.GetCU(), - block_offset, block_length); + location = DWARFExpression( + module, + DataExtractor(debug_info_data, block_offset, block_length), + die.GetCU()); } else if (DWARFFormValue::IsDataForm(form_value.Form())) { // Retrieve the value as a data expression. uint32_t data_offset = attributes.DIEOffsetAtIndex(i); if (auto data_length = form_value.GetFixedSize()) - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - data_offset, *data_length); + location = DWARFExpression( + module, + DataExtractor(debug_info_data, data_offset, *data_length), + die.GetCU()); else { const uint8_t *data_pointer = form_value.BlockData(); if (data_pointer) { @@ -3217,17 +3236,21 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (form_value.Form() == DW_FORM_strp) { uint32_t data_offset = attributes.DIEOffsetAtIndex(i); if (auto data_length = form_value.GetFixedSize()) - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - data_offset, *data_length); + location = DWARFExpression(module, + DataExtractor(debug_info_data, + data_offset, + *data_length), + die.GetCU()); } else { const char *str = form_value.AsCString(); uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart(); uint32_t string_length = strlen(str) + 1; - location = - DWARFExpression(module, debug_info_data, die.GetCU(), - string_offset, string_length); + location = DWARFExpression(module, + DataExtractor(debug_info_data, + string_offset, + string_length), + die.GetCU()); } } } @@ -3241,17 +3264,15 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); uint32_t block_length = form_value.Unsigned(); - location = DWARFExpression(module, data, die.GetCU(), - block_offset, block_length); + location = DWARFExpression( + module, DataExtractor(data, block_offset, block_length), + die.GetCU()); } else { - const DWARFDataExtractor &debug_loc_data = DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - die.GetCU(), debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - location = DWARFExpression(module, debug_loc_data, die.GetCU(), - debug_loc_offset, loc_list_length); + DataExtractor data = DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + location = DWARFExpression(module, data, die.GetCU()); assert(func_low_pc != LLDB_INVALID_ADDRESS); location.SetLocationListSlide( func_low_pc - @@ -3522,6 +3543,8 @@ SymbolFileDWARF::FindBlockContainingSpecification( spec_block_die_offset) return die; } break; + default: + break; } // Give the concrete function die specified by "func_die_offset", find the @@ -3577,8 +3600,7 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, } else { GetObjectFile()->GetModule()->ReportError( "parent 0x%8.8" PRIx64 " %s with no valid compile unit in " - "symbol context for 0x%8.8" PRIx64 - " %s.\n", + "symbol context for 0x%8.8" PRIx64 " %s.\n", sc_parent_die.GetID(), sc_parent_die.GetTagAsCString(), orig_die.GetID(), orig_die.GetTagAsCString()); } @@ -3654,9 +3676,57 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, return vars_added; } +/// Collect call site parameters in a DW_TAG_call_site DIE. +static CallSiteParameterArray +CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { + CallSiteParameterArray parameters; + for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid(); + child = child.GetSibling()) { + if (child.Tag() != DW_TAG_call_site_parameter) + continue; + + llvm::Optional<DWARFExpression> LocationInCallee = {}; + llvm::Optional<DWARFExpression> LocationInCaller = {}; + + DWARFAttributes attributes; + const size_t num_attributes = child.GetAttributes(attributes); + + // Parse the location at index \p attr_index within this call site parameter + // DIE, or return None on failure. + auto parse_simple_location = + [&](int attr_index) -> llvm::Optional<DWARFExpression> { + DWARFFormValue form_value; + if (!attributes.ExtractFormValueAtIndex(attr_index, form_value)) + return {}; + if (!DWARFFormValue::IsBlockForm(form_value.Form())) + return {}; + auto data = child.GetData(); + uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint32_t block_length = form_value.Unsigned(); + return DWARFExpression(module, + DataExtractor(data, block_offset, block_length), + child.GetCU()); + }; + + for (size_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attr == DW_AT_location) + LocationInCallee = parse_simple_location(i); + if (attr == DW_AT_call_value) + LocationInCaller = parse_simple_location(i); + } + + if (LocationInCallee && LocationInCaller) { + CallSiteParameter param = {*LocationInCallee, *LocationInCaller}; + parameters.push_back(param); + } + } + return parameters; +} + /// Collect call graph edges present in a function DIE. static std::vector<lldb_private::CallEdge> -CollectCallEdges(DWARFDIE function_die) { +CollectCallEdges(ModuleSP module, DWARFDIE function_die) { // Check if the function has a supported call site-related attribute. // TODO: In the future it may be worthwhile to support call_all_source_calls. uint64_t has_call_edges = @@ -3693,9 +3763,28 @@ CollectCallEdges(DWARFDIE function_die) { addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc, LLDB_INVALID_ADDRESS); + // Extract call site parameters. + CallSiteParameterArray parameters = + CollectCallSiteParameters(module, child); + LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})", call_origin.GetPubname(), return_pc); - call_edges.emplace_back(call_origin.GetMangledName(), return_pc); + if (log && parameters.size()) { + for (const CallSiteParameter ¶m : parameters) { + StreamString callee_loc_desc, caller_loc_desc; + param.LocationInCallee.GetDescription(&callee_loc_desc, + eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, nullptr); + param.LocationInCaller.GetDescription(&caller_loc_desc, + eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, nullptr); + LLDB_LOG(log, "CollectCallEdges: \tparam: {0} => {1}", + callee_loc_desc.GetString(), caller_loc_desc.GetString()); + } + } + + call_edges.emplace_back(call_origin.GetMangledName(), return_pc, + std::move(parameters)); } return call_edges; } @@ -3704,7 +3793,7 @@ std::vector<lldb_private::CallEdge> SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) { DWARFDIE func_die = GetDIE(func_id.GetID()); if (func_die.IsValid()) - return CollectCallEdges(func_die); + return CollectCallEdges(GetObjectFile()->GetModule(), func_die); return {}; } @@ -3713,11 +3802,17 @@ ConstString SymbolFileDWARF::GetPluginName() { return GetPluginNameStatic(); } uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; } -void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); } +void SymbolFileDWARF::Dump(lldb_private::Stream &s) { + SymbolFile::Dump(s); + m_index->Dump(s); +} void SymbolFileDWARF::DumpClangAST(Stream &s) { - TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); - ClangASTContext *clang = llvm::dyn_cast_or_null<ClangASTContext>(ts); + auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (!ts_or_err) + return; + ClangASTContext *clang = + llvm::dyn_cast_or_null<ClangASTContext>(&ts_or_err.get()); if (!clang) return; clang->Dump(s); @@ -3727,10 +3822,8 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); if (module_sp) { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - if (sym_vendor) - m_debug_map_symfile = - (SymbolFileDWARFDebugMap *)sym_vendor->GetSymbolFile(); + m_debug_map_symfile = + (SymbolFileDWARFDebugMap *)module_sp->GetSymbolFile(); } } return m_debug_map_symfile; @@ -3746,9 +3839,9 @@ SymbolFileDWARF::GetLocationListFormat() const { SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { llvm::call_once(m_dwp_symfile_once_flag, [this]() { ModuleSpec module_spec; - module_spec.GetFileSpec() = m_obj_file->GetFileSpec(); + module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec(); module_spec.GetSymbolFileSpec() = - FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp"); + FileSpec(m_objfile_sp->GetFileSpec().GetPath() + ".dwp"); FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dwp_filespec = diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 018af47305f4..04cb11d426be 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -46,7 +46,8 @@ class DWARFDebugAranges; class DWARFDebugInfo; class DWARFDebugInfoEntry; class DWARFDebugLine; -class DWARFDebugRangesBase; +class DWARFDebugRanges; +class DWARFDebugRngLists; class DWARFDeclContext; class DWARFFormValue; class DWARFTypeUnit; @@ -78,13 +79,13 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); static lldb_private::FileSpecList GetSymlinkPaths(); // Constructors and Destructors - SymbolFileDWARF(lldb_private::ObjectFile *ofile, + SymbolFileDWARF(lldb::ObjectFileSP objfile_sp, lldb_private::SectionList *dwo_section_list); ~SymbolFileDWARF() override; @@ -95,10 +96,6 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -108,6 +105,10 @@ public: bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref<void(lldb::ModuleSP)> f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; @@ -156,47 +157,46 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; void GetMangledNamesForFunction( const std::string &scope_qualified_name, std::vector<lldb_private::ConstString> &mangled_names) override; - uint32_t + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector<lldb_private::CompilerContext> &context, - bool append, lldb_private::TypeMap &types) override; + void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, + lldb_private::LanguageSet languages, + lldb_private::TypeMap &types) override; - lldb_private::TypeList *GetTypeList() override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; - - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( @@ -223,8 +223,8 @@ public: const DWARFDebugInfo *DebugInfo() const; - DWARFDebugRangesBase *GetDebugRanges(); - DWARFDebugRangesBase *GetDebugRngLists(); + DWARFDebugRanges *GetDebugRanges(); + DWARFDebugRngLists *GetDebugRngLists(); const lldb_private::DWARFDataExtractor &DebugLocData(); @@ -331,6 +331,12 @@ protected: bool DeclContextMatchesThisSymbolFile( const lldb_private::CompilerDeclContext *decl_ctx); + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + + lldb_private::TypeList &GetTypeList() override; + virtual DWARFUnit * GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit); @@ -477,8 +483,8 @@ protected: typedef std::set<lldb::user_id_t> DIERefSet; typedef llvm::StringMap<DIERefSet> NameToOffsetMap; NameToOffsetMap m_function_scope_qualified_name_map; - std::unique_ptr<DWARFDebugRangesBase> m_ranges; - std::unique_ptr<DWARFDebugRangesBase> m_rnglists; + std::unique_ptr<DWARFDebugRanges> m_ranges; + std::unique_ptr<DWARFDebugRngLists> m_rnglists; UniqueDWARFASTTypeMap m_unique_ast_type_map; DIEToTypePtr m_die_to_type; DIEToVariableSP m_die_to_variable_sp; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 8ec64dbaf764..a50d4e460bae 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -41,7 +41,7 @@ using namespace lldb_private; // Subclass lldb_private::Module so we can intercept the // "Module::GetObjectFile()" (so we can fixup the object file sections) and -// also for "Module::GetSymbolVendor()" (so we can fixup the symbol file id. +// also for "Module::GetSymbolFile()" (so we can fixup the symbol file id. const SymbolFileDWARFDebugMap::FileRangeMap & SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( @@ -60,11 +60,11 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap( return file_range_map; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); - if (log) - log->Printf( - "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')", - static_cast<void *>(this), - oso_module->GetSpecificationDescription().c_str()); + LLDB_LOGF( + log, + "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')", + static_cast<void *>(this), + oso_module->GetSpecificationDescription().c_str()); std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos; if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) { @@ -173,12 +173,12 @@ public: ~DebugMapModule() override = default; - SymbolVendor * - GetSymbolVendor(bool can_create = true, - lldb_private::Stream *feedback_strm = nullptr) override { + SymbolFile * + GetSymbolFile(bool can_create = true, + lldb_private::Stream *feedback_strm = nullptr) override { // Scope for locker if (m_symfile_up.get() || !can_create) - return m_symfile_up.get(); + return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr; ModuleSP exe_module_sp(m_exe_module_wp.lock()); if (exe_module_sp) { @@ -186,30 +186,28 @@ public: ObjectFile *oso_objfile = GetObjectFile(); if (oso_objfile) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - SymbolVendor *symbol_vendor = - Module::GetSymbolVendor(can_create, feedback_strm); - if (symbol_vendor) { + if (SymbolFile *symfile = + Module::GetSymbolFile(can_create, feedback_strm)) { // Set a pointer to this class to set our OSO DWARF file know that // the DWARF is being used along with a debug map and that it will // have the remapped sections that we do below. SymbolFileDWARF *oso_symfile = - SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF( - symbol_vendor->GetSymbolFile()); + SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symfile); if (!oso_symfile) return nullptr; ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); - SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor(); + SymbolFile *exe_symfile = exe_module_sp->GetSymbolFile(); - if (exe_objfile && exe_sym_vendor) { + if (exe_objfile && exe_symfile) { oso_symfile->SetDebugMapModule(exe_module_sp); // Set the ID of the symbol file DWARF to the index of the OSO // shifted left by 32 bits to provide a unique prefix for any // UserID's that get created in the symbol file. oso_symfile->SetID(((uint64_t)m_cu_idx + 1ull) << 32ull); } - return symbol_vendor; + return symfile; } } } @@ -239,13 +237,13 @@ const char *SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() { return "DWARF and DWARF3 debug symbol file reader (debug map)."; } -SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileDWARFDebugMap(obj_file); +SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileDWARFDebugMap(std::move(objfile_sp)); } -SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFile *ofile) - : SymbolFile(ofile), m_flags(), m_compile_unit_infos(), m_func_indexes(), - m_glob_indexes(), +SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)), m_flags(), m_compile_unit_infos(), + m_func_indexes(), m_glob_indexes(), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {} SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() {} @@ -260,12 +258,12 @@ void SymbolFileDWARFDebugMap::InitOSO() { // If the object file has been stripped, there is no sense in looking further // as all of the debug symbols for the debug map will not be available - if (m_obj_file->IsStripped()) + if (m_objfile_sp->IsStripped()) return; // Also make sure the file type is some sort of executable. Core files, debug // info files (dSYM), object files (.o files), and stub libraries all can - switch (m_obj_file->GetType()) { + switch (m_objfile_sp->GetType()) { case ObjectFile::eTypeInvalid: case ObjectFile::eTypeCoreFile: case ObjectFile::eTypeDebugInfo: @@ -286,7 +284,7 @@ void SymbolFileDWARFDebugMap::InitOSO() { // these files exist and also contain valid DWARF. If we get any of that then // we return the abilities of the first N_OSO's DWARF. - Symtab *symtab = m_obj_file->GetSymtab(); + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP)); @@ -352,7 +350,7 @@ void SymbolFileDWARFDebugMap::InitOSO() { // The sibling index can't be less that or equal to the current index // "i" if (sibling_idx == UINT32_MAX) { - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO in symbol with UID %u has invalid sibling in debug map, " "please file a bug and attach the binary listed in this error", so_symbol->GetID()); @@ -363,28 +361,27 @@ void SymbolFileDWARFDebugMap::InitOSO() { m_compile_unit_infos[i].first_symbol_id = so_symbol->GetID(); m_compile_unit_infos[i].last_symbol_id = last_symbol->GetID(); - if (log) - log->Printf("Initialized OSO 0x%8.8x: file=%s", i, - oso_symbol->GetName().GetCString()); + LLDB_LOGF(log, "Initialized OSO 0x%8.8x: file=%s", i, + oso_symbol->GetName().GetCString()); } } else { if (oso_symbol == nullptr) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_OSO symbol[%u] can't be found, please file a bug and attach " "the binary listed in this error", oso_idx); else if (so_symbol == nullptr) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO not found for N_OSO symbol[%u], please file a bug and " "attach the binary listed in this error", oso_idx); else if (so_symbol->GetType() != eSymbolTypeSourceFile) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_SO has incorrect symbol type (%u) for N_OSO symbol[%u], " "please file a bug and attach the binary listed in this error", so_symbol->GetType(), oso_idx); else if (oso_symbol->GetType() != eSymbolTypeSourceFile) - m_obj_file->GetModule()->ReportError( + m_objfile_sp->GetModule()->ReportError( "N_OSO has incorrect symbol type (%u) for N_OSO symbol[%u], " "please file a bug and attach the binary listed in this error", oso_symbol->GetType(), oso_idx); @@ -421,7 +418,11 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( // than the one from the CU. auto oso_mod_time = std::chrono::time_point_cast<std::chrono::seconds>( FileSystem::Instance().GetModificationTime(oso_file)); - if (oso_mod_time != comp_unit_info->oso_mod_time) { + // A timestamp of 0 means that the linker was in deterministic mode. In + // that case, we should skip the check against the filesystem last + // modification timestamp, since it will never match. + if (comp_unit_info->oso_mod_time != llvm::sys::TimePoint<>() && + oso_mod_time != comp_unit_info->oso_mod_time) { obj_file->GetModule()->ReportError( "debug map object file '%s' has changed (actual time is " "%s, debug map time is %s" @@ -448,7 +449,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( // since .o files for "i386-apple-ios" will historically show up as "i386 // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or // LC_VERSION_MIN_IPHONEOS load command... - oso_arch.SetTriple(m_obj_file->GetModule() + oso_arch.SetTriple(m_objfile_sp->GetModule() ->GetArchitecture() .GetTriple() .getArchName() @@ -534,12 +535,8 @@ SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) { SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo( CompileUnitInfo *comp_unit_info) { - Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info); - if (oso_module) { - SymbolVendor *sym_vendor = oso_module->GetSymbolVendor(); - if (sym_vendor) - return GetSymbolFileAsSymbolFileDWARF(sym_vendor->GetSymbolFile()); - } + if (Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info)) + return GetSymbolFileAsSymbolFileDWARF(oso_module->GetSymbolFile()); return nullptr; } @@ -562,7 +559,7 @@ uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() { return 0; } -uint32_t SymbolFileDWARFDebugMap::GetNumCompileUnits() { +uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() { InitOSO(); return m_compile_unit_infos.size(); } @@ -581,13 +578,12 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) { lldb::user_id_t cu_id = 0; m_compile_unit_infos[cu_idx].compile_unit_sp = std::make_shared<CompileUnit>( - m_obj_file->GetModule(), nullptr, so_file_spec, cu_id, + m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id, eLanguageTypeUnknown, eLazyBoolCalculate); if (m_compile_unit_infos[cu_idx].compile_unit_sp) { - // Let our symbol vendor know about this compile unit - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cu_idx, m_compile_unit_infos[cu_idx].compile_unit_sp); + SetCompileUnitAtIndex(cu_idx, + m_compile_unit_infos[cu_idx].compile_unit_sp); } } } @@ -625,6 +621,7 @@ size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule( lldb::LanguageType SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseLanguage(comp_unit); @@ -632,6 +629,7 @@ SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseFunctions(comp_unit); @@ -639,6 +637,7 @@ size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseLineTable(comp_unit); @@ -646,14 +645,24 @@ bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) { } bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseDebugMacros(comp_unit); return false; } +void SymbolFileDWARFDebugMap::ForEachExternalModule( + CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); + if (oso_dwarf) + oso_dwarf->ForEachExternalModule(comp_unit, f); +} + bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseSupportFiles(comp_unit, support_files); @@ -661,6 +670,7 @@ bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, } bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseIsOptimized(comp_unit); @@ -669,6 +679,7 @@ bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) { bool SymbolFileDWARFDebugMap::ParseImportedModules( const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); if (oso_dwarf) return oso_dwarf->ParseImportedModules(sc, imported_modules); @@ -676,6 +687,7 @@ bool SymbolFileDWARFDebugMap::ParseImportedModules( } size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompileUnit *comp_unit = func.GetCompileUnit(); if (!comp_unit) return 0; @@ -687,6 +699,7 @@ size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) { } size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) return oso_dwarf->ParseTypes(comp_unit); @@ -695,6 +708,7 @@ size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); if (oso_dwarf) return oso_dwarf->ParseVariablesForContext(sc); @@ -702,6 +716,7 @@ SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) { } Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) @@ -738,8 +753,9 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t resolved_flags = 0; - Symtab *symtab = m_obj_file->GetSymtab(); + Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { const addr_t exe_file_addr = exe_so_addr.GetFileAddress(); @@ -766,7 +782,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, Address oso_so_addr; if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) { resolved_flags |= - oso_module->GetSymbolVendor()->ResolveSymbolContext( + oso_module->GetSymbolFile()->ResolveSymbolContext( oso_so_addr, resolve_scope, sc); } } @@ -780,6 +796,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( const FileSpec &file_spec, uint32_t line, bool check_inlines, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint32_t initial = sc_list.GetSize(); const uint32_t cu_count = GetNumCompileUnits(); @@ -807,12 +824,11 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( return sc_list.GetSize() - initial; } -uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( +void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &indexes, // Indexes into the symbol table that match "name" uint32_t max_matches, VariableList &variables) { - const uint32_t original_size = variables.GetSize(); const size_t match_count = indexes.size(); for (size_t i = 0; i < match_count; ++i) { uint32_t oso_idx; @@ -821,28 +837,26 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables( if (comp_unit_info) { SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) { - if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, - variables)) - if (variables.GetSize() > max_matches) - break; + oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, + variables); + if (variables.GetSize() > max_matches) + break; } } } - return variables.GetSize() - original_size; } -uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables( +void SymbolFileDWARFDebugMap::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { - - // Remember how many variables are in the list before we search. - const uint32_t original_size = variables.GetSize(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t total_matches = 0; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - const uint32_t oso_matches = oso_dwarf->FindGlobalVariables( - name, parent_decl_ctx, max_matches, variables); + const uint32_t old_size = variables.GetSize(); + oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches, + variables); + const uint32_t oso_matches = variables.GetSize() - old_size; if (oso_matches > 0) { total_matches += oso_matches; @@ -861,22 +875,18 @@ uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables( return false; }); - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } -uint32_t -SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression ®ex, - uint32_t max_matches, - VariableList &variables) { - // Remember how many variables are in the list before we search. - const uint32_t original_size = variables.GetSize(); - +void SymbolFileDWARFDebugMap::FindGlobalVariables( + const RegularExpression ®ex, uint32_t max_matches, + VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t total_matches = 0; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - const uint32_t oso_matches = - oso_dwarf->FindGlobalVariables(regex, max_matches, variables); + const uint32_t old_size = variables.GetSize(); + oso_dwarf->FindGlobalVariables(regex, max_matches, variables); + + const uint32_t oso_matches = variables.GetSize() - old_size; if (oso_matches > 0) { total_matches += oso_matches; @@ -895,9 +905,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression ®ex, return false; }); - - // Return the number of variable that were appended to the list - return variables.GetSize() - original_size; } int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex( @@ -993,71 +1000,58 @@ static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp, } } -uint32_t SymbolFileDWARFDebugMap::FindFunctions( +void SymbolFileDWARFDebugMap::FindFunctions( ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::FindFunctions (name = %s)", name.GetCString()); - uint32_t initial_size = 0; - if (append) - initial_size = sc_list.GetSize(); - else - sc_list.Clear(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - if (oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, - include_inlines, true, sc_list)) { - RemoveFunctionsWithModuleNotEqualTo(m_obj_file->GetModule(), sc_list, + oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, + include_inlines, sc_list); + if (!sc_list.IsEmpty()) { + RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list, sc_idx); } return false; }); - - return sc_list.GetSize() - initial_size; } -uint32_t SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression ®ex, - bool include_inlines, - bool append, - SymbolContextList &sc_list) { +void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')", regex.GetText().str().c_str()); - uint32_t initial_size = 0; - if (append) - initial_size = sc_list.GetSize(); - else - sc_list.Clear(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { uint32_t sc_idx = sc_list.GetSize(); - if (oso_dwarf->FindFunctions(regex, include_inlines, true, sc_list)) { - RemoveFunctionsWithModuleNotEqualTo(m_obj_file->GetModule(), sc_list, + oso_dwarf->FindFunctions(regex, include_inlines, sc_list); + if (!sc_list.IsEmpty()) { + RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list, sc_idx); } return false; }); - - return sc_list.GetSize() - initial_size; } -size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - TypeList &type_list) { +void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + TypeList &type_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)", type_mask); - uint32_t initial_size = type_list.GetSize(); SymbolFileDWARF *oso_dwarf = nullptr; if (sc_scope) { SymbolContext sc; @@ -1075,7 +1069,6 @@ size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, return false; }); } - return type_list.GetSize() - initial_size; } std::vector<lldb_private::CallEdge> @@ -1124,7 +1117,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( // N_SO. SymbolFileDWARF *oso_dwarf = nullptr; TypeSP type_sp; - ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile(); + ObjectFile *module_objfile = m_objfile_sp->GetModule()->GetObjectFile(); if (module_objfile) { Symtab *symtab = module_objfile->GetSymtab(); if (symtab) { @@ -1177,23 +1170,17 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( return TypeSP(); } -uint32_t SymbolFileDWARFDebugMap::FindTypes( +void SymbolFileDWARFDebugMap::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { - if (!append) - types.Clear(); - - const uint32_t initial_types_size = types.GetSize(); - + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes(name, parent_decl_ctx, append, max_matches, + oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches, searched_symbol_files, types); return types.GetSize() >= max_matches; }); - - return types.GetSize() - initial_types_size; } // @@ -1212,6 +1199,7 @@ uint32_t SymbolFileDWARFDebugMap::FindTypes( CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace( lldb_private::ConstString name, const CompilerDeclContext *parent_decl_ctx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompilerDeclContext matching_namespace; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { @@ -1284,8 +1272,7 @@ void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf, cu_sp.get()); } else { m_compile_unit_infos[cu_idx].compile_unit_sp = cu_sp; - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cu_idx, cu_sp); + SetCompileUnitAtIndex(cu_idx, cu_sp); } } } @@ -1388,8 +1375,8 @@ bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address &addr) { if (addr_module == exe_module) return true; // Address is already in terms of the main executable module - CompileUnitInfo *cu_info = GetCompileUnitInfo(GetSymbolFileAsSymbolFileDWARF( - addr_module->GetSymbolVendor()->GetSymbolFile())); + CompileUnitInfo *cu_info = GetCompileUnitInfo( + GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolFile())); if (cu_info) { const lldb::addr_t oso_file_addr = addr.GetFileAddress(); const FileRangeMap::Entry *oso_range_entry = diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index afc6142e8231..7adee1b356ce 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -34,19 +34,16 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFileDWARFDebugMap(lldb_private::ObjectFile *ofile); + SymbolFileDWARFDebugMap(lldb::ObjectFileSP objfile_sp); ~SymbolFileDWARFDebugMap() override; uint32_t CalculateAbilities() override; void InitializeObject() override; // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -56,6 +53,10 @@ public: bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + void + ForEachExternalModule(lldb_private::CompileUnit &comp_unit, + llvm::function_ref<void(lldb::ModuleSP)> f) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) override; @@ -91,34 +92,34 @@ public: bool check_inlines, lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; lldb_private::CompilerDeclContext FindNamespace( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; std::vector<lldb_private::CallEdge> ParseCallEdgesInFunction(lldb_private::UserID func_id) override; @@ -174,6 +175,9 @@ protected: // Protected Member Functions void InitOSO(); + uint32_t CalculateNumCompileUnits() override; + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + static uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) { return (uint32_t)((uid >> 32ull) - 1ull); } @@ -232,7 +236,7 @@ protected: static int SymbolContainsSymbolWithID(lldb::user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info); - uint32_t PrivateFindGlobalVariables( + void PrivateFindGlobalVariables( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, const std::vector<uint32_t> &name_symbol_indexes, uint32_t max_matches, diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index c5b54b65ea29..b0f7e813d4f8 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -23,21 +23,21 @@ using namespace lldb_private; SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu) - : SymbolFileDWARF(objfile.get(), objfile->GetSectionList( - /*update_module_section_list*/ false)), - m_obj_file_sp(objfile), m_base_dwarf_cu(dwarf_cu) { + : SymbolFileDWARF(objfile, objfile->GetSectionList( + /*update_module_section_list*/ false)), + m_base_dwarf_cu(dwarf_cu) { SetID(((lldb::user_id_t)dwarf_cu.GetID()) << 32); } void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { const SectionList *section_list = - m_obj_file->GetSectionList(false /* update_module_section_list */); + m_objfile_sp->GetSectionList(false /* update_module_section_list */); if (section_list) { SectionSP section_sp(section_list->FindSectionByType(sect_type, true)); if (section_sp) { - if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) + if (m_objfile_sp->ReadSectionData(section_sp.get(), data) != 0) return; data.Clear(); @@ -140,7 +140,7 @@ SymbolFileDWARFDwo::GetLocationListFormat() const { return DWARFExpression::SplitDwarfLocationList; } -TypeSystem * +llvm::Expected<TypeSystem &> SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { return GetBaseSymbolFile().GetTypeSystemForLanguage(language); } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 9b2f3bb84c4f..ad290cdcf65e 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -30,7 +30,7 @@ public: size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, DIEArray &method_die_offsets) override; - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; DWARFDIE @@ -71,7 +71,6 @@ protected: DWARFCompileUnit *ComputeCompileUnit(); - lldb::ObjectFileSP m_obj_file_sp; DWARFCompileUnit &m_base_dwarf_cu; DWARFCompileUnit *m_cu = nullptr; }; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td new file mode 100644 index 000000000000..ef6ae3498588 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFProperties.td @@ -0,0 +1,12 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "symbolfiledwarf" in { + def SymLinkPaths: Property<"comp-dir-symlink-paths", "FileSpecList">, + Global, + DefaultStringValue<"">, + Desc<"If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time.">; + def IgnoreIndexes: Property<"ignore-file-indexes", "Boolean">, + Global, + DefaultFalse, + Desc<"Ignore indexes present in the object files and always index DWARF manually.">; +} diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 8da7e2226266..4862fea8d079 100644 --- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -55,6 +55,8 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, case DW_TAG_partial_unit: done = true; break; + default: + break; } } parent_arg_die = parent_arg_die.GetParent(); diff --git a/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp index 1838204e4ca6..830d78f81679 100644 --- a/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp +++ b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp @@ -130,7 +130,7 @@ CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) { if (!stream_data) { llvm::pdb::ModuleDebugStreamRef debug_stream(descriptor, nullptr); - cci = llvm::make_unique<CompilandIndexItem>(PdbCompilandId{ modi }, debug_stream, std::move(descriptor)); + cci = std::make_unique<CompilandIndexItem>(PdbCompilandId{ modi }, debug_stream, std::move(descriptor)); return *cci; } @@ -139,7 +139,7 @@ CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) { cantFail(debug_stream.reload()); - cci = llvm::make_unique<CompilandIndexItem>( + cci = std::make_unique<CompilandIndexItem>( PdbCompilandId{modi}, std::move(debug_stream), std::move(descriptor)); ParseExtendedInfo(m_index, *cci); diff --git a/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index 3d8bfb058721..6aaff06cc134 100644 --- a/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -122,7 +122,7 @@ static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, DataBufferSP buffer = std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); DataExtractor extractor(buffer, byte_order, address_size, byte_size); - DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize()); + DWARFExpression result(module, extractor, nullptr); result.SetRegisterKind(register_kind); return result; @@ -247,6 +247,6 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( .take_front(size); buffer->CopyData(bytes.data(), size); DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size); - DWARFExpression result(nullptr, extractor, nullptr, 0, size); + DWARFExpression result(nullptr, extractor, nullptr); return result; } diff --git a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 4991be8e70ce..986b0b785d87 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -121,13 +121,6 @@ AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) { return false; } -static ClangASTContext &GetClangASTContext(ObjectFile &obj) { - TypeSystem *ts = - obj.GetModule()->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - lldbassert(ts); - return static_cast<ClangASTContext &>(*ts); -} - static llvm::Optional<clang::CallingConv> TranslateCallingConvention(llvm::codeview::CallingConvention conv) { using CC = llvm::codeview::CallingConvention; @@ -209,8 +202,8 @@ static bool IsAnonymousNamespaceName(llvm::StringRef name) { return name == "`anonymous namespace'" || name == "`anonymous-namespace'"; } -PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index) - : m_index(index), m_clang(GetClangASTContext(obj)) { +PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index, ClangASTContext &clang) + : m_index(index), m_clang(clang) { BuildParentMap(); } @@ -465,9 +458,9 @@ clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) { } } -clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { +llvm::Optional<CompilerDecl> PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { if (clang::Decl *result = TryGetDecl(uid)) - return result; + return ToCompilerDecl(*result); clang::Decl *result = nullptr; switch (uid.kind()) { @@ -480,13 +473,13 @@ clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) { result = tag; break; } - return nullptr; + return llvm::None; } default: - return nullptr; + return llvm::None; } m_uid_to_decl[toOpaqueUid(uid)] = result; - return result; + return ToCompilerDecl(*result); } clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) { @@ -494,8 +487,10 @@ clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) { if (uid.asCompilandSym().offset == 0) return FromCompilerDeclContext(GetTranslationUnitDecl()); } - - clang::Decl *decl = GetOrCreateDeclForUid(uid); + auto option = GetOrCreateDeclForUid(uid); + if (!option) + return nullptr; + clang::Decl *decl = FromCompilerDecl(option.getValue()); if (!decl) return nullptr; @@ -1089,7 +1084,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id, CompilerType param_type_ct(&m_clang, qt.getAsOpaquePtr()); clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration( &function_decl, param_name.str().c_str(), param_type_ct, - clang::SC_None); + clang::SC_None, true); lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0); m_uid_to_decl[toOpaqueUid(param_uid)] = param; diff --git a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h index 67d024741e0d..a4242e90810d 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h +++ b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h @@ -51,11 +51,12 @@ struct DeclStatus { class PdbAstBuilder { public: // Constructors and Destructors - PdbAstBuilder(ObjectFile &obj, PdbIndex &index); + PdbAstBuilder(ObjectFile &obj, PdbIndex &index, ClangASTContext &clang); lldb_private::CompilerDeclContext GetTranslationUnitDecl(); - clang::Decl *GetOrCreateDeclForUid(PdbSymUid uid); + llvm::Optional<lldb_private::CompilerDecl> + GetOrCreateDeclForUid(PdbSymUid uid); clang::DeclContext *GetOrCreateDeclContextForUid(PdbSymUid uid); clang::DeclContext *GetParentDeclContext(PdbSymUid uid); @@ -76,7 +77,7 @@ public: CompilerDecl ToCompilerDecl(clang::Decl &decl); CompilerType ToCompilerType(clang::QualType qt); CompilerDeclContext ToCompilerDeclContext(clang::DeclContext &context); - clang::Decl * FromCompilerDecl(CompilerDecl decl); + clang::Decl *FromCompilerDecl(CompilerDecl decl); clang::DeclContext *FromCompilerDeclContext(CompilerDeclContext context); ClangASTContext &clang() { return m_clang; } diff --git a/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp index 79dd010ff311..a7bc23519710 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp +++ b/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp @@ -51,54 +51,23 @@ static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::A return npdb::GetLLDBRegisterNumber(arch_type, reg_id); } -static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program, - llvm::BumpPtrAllocator &alloc, - llvm::StringRef ®ister_name, - Node *&ast) { - // lvalue of assignment is always first token - // rvalue program goes next - std::tie(register_name, program) = getToken(program); - if (register_name.empty()) - return false; - - ast = Parse(program, alloc); - return ast != nullptr; -} - -static Node *ParseFPOProgram(llvm::StringRef program, +static Node *ResolveFPOProgram(llvm::StringRef program, llvm::StringRef register_name, llvm::Triple::ArchType arch_type, llvm::BumpPtrAllocator &alloc) { - llvm::DenseMap<llvm::StringRef, Node *> dependent_programs; - - size_t cur = 0; - while (true) { - size_t assign_index = program.find('=', cur); - if (assign_index == llvm::StringRef::npos) { - llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos); - if (!tail.trim().empty()) { - // missing assign operator - return nullptr; - } - break; - } - llvm::StringRef assignment_program = program.slice(cur, assign_index); - - llvm::StringRef lvalue_name; - Node *rvalue_ast = nullptr; - if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name, - rvalue_ast)) { - return nullptr; - } - - lldbassert(rvalue_ast); + std::vector<std::pair<llvm::StringRef, Node *>> parsed = + postfix::ParseFPOProgram(program, alloc); + for (auto it = parsed.begin(), end = parsed.end(); it != end; ++it) { // Emplace valid dependent subtrees to make target assignment independent // from predecessors. Resolve all other SymbolNodes as registers. bool success = - ResolveSymbols(rvalue_ast, [&](SymbolNode &symbol) -> Node * { - if (Node *node = dependent_programs.lookup(symbol.GetName())) - return node; + ResolveSymbols(it->second, [&](SymbolNode &symbol) -> Node * { + for (const auto &pair : llvm::make_range(parsed.begin(), it)) { + if (pair.first == symbol.GetName()) + return pair.second; + } + uint32_t reg_num = ResolveLLDBRegisterNum(symbol.GetName().drop_front(1), arch_type); @@ -110,13 +79,10 @@ static Node *ParseFPOProgram(llvm::StringRef program, if (!success) return nullptr; - if (lvalue_name == register_name) { + if (it->first == register_name) { // found target assignment program - no need to parse further - return rvalue_ast; + return it->second; } - - dependent_programs[lvalue_name] = rvalue_ast; - cur = assign_index + 1; } return nullptr; @@ -127,7 +93,7 @@ bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( llvm::Triple::ArchType arch_type, Stream &stream) { llvm::BumpPtrAllocator node_alloc; Node *target_program = - ParseFPOProgram(program, register_name, arch_type, node_alloc); + ResolveFPOProgram(program, register_name, arch_type, node_alloc); if (target_program == nullptr) { return false; } diff --git a/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 1f5c97da81cf..fc047e25a2f4 100644 --- a/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -641,14 +641,14 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( llvm::StringRef program; if (GetFrameDataProgram(index, ranges, program)) { result.location = - MakeVFrameRelLocationExpression(program, loc.Offset, module); + MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module); result.ranges = std::move(ranges); } else { // invalid variable } } else { result.location = - MakeRegRelLocationExpression(base_reg, loc.Offset, module); + MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module); result.ranges = std::move(ranges); } } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) { diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index e27d4699ae2f..33b8da3b543b 100644 --- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/StreamBuffer.h" #include "lldb/Core/StreamFile.h" #include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompileUnit.h" @@ -30,6 +29,7 @@ #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Utility/Log.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" @@ -90,10 +90,10 @@ static std::unique_ptr<PDBFile> loadPDBFile(std::string PdbPath, std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); llvm::StringRef Path = Buffer->getBufferIdentifier(); - auto Stream = llvm::make_unique<llvm::MemoryBufferByteStream>( + auto Stream = std::make_unique<llvm::MemoryBufferByteStream>( std::move(Buffer), llvm::support::little); - auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), Allocator); + auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator); if (auto EC = File->parseFileHeaders()) { llvm::consumeError(std::move(EC)); return nullptr; @@ -119,6 +119,8 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { } OwningBinary<Binary> binary = std::move(*expected_binary); + // TODO: Avoid opening the PE/COFF binary twice by reading this information + // directly from the lldb_private::ObjectFile. auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary()); if (!obj) return nullptr; @@ -264,27 +266,27 @@ const char *SymbolFileNativePDB::GetPluginDescriptionStatic() { return "Microsoft PDB debug symbol cross-platform file reader."; } -SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileNativePDB(obj_file); +SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileNativePDB(std::move(objfile_sp)); } -SymbolFileNativePDB::SymbolFileNativePDB(ObjectFile *object_file) - : SymbolFile(object_file) {} +SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)) {} SymbolFileNativePDB::~SymbolFileNativePDB() {} uint32_t SymbolFileNativePDB::CalculateAbilities() { uint32_t abilities = 0; - if (!m_obj_file) + if (!m_objfile_sp) return 0; if (!m_index) { // Lazily load and match the PDB file, but only do this once. std::unique_ptr<PDBFile> file_up = - loadMatchingPDBFile(m_obj_file->GetFileSpec().GetPath(), m_allocator); + loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(), m_allocator); if (!file_up) { - auto module_sp = m_obj_file->GetModule(); + auto module_sp = m_objfile_sp->GetModule(); if (!module_sp) return 0; // See if any symbol file is specified through `--symfile` option. @@ -317,19 +319,24 @@ uint32_t SymbolFileNativePDB::CalculateAbilities() { } void SymbolFileNativePDB::InitializeObject() { - m_obj_load_address = m_obj_file->GetBaseAddress().GetFileAddress(); + m_obj_load_address = m_objfile_sp->GetBaseAddress().GetFileAddress(); m_index->SetLoadAddress(m_obj_load_address); m_index->ParseSectionContribs(); - TypeSystem *ts = m_obj_file->GetModule()->GetTypeSystemForLanguage( + auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage( lldb::eLanguageTypeC_plus_plus); - if (ts) - ts->SetSymbolFile(this); - - m_ast = llvm::make_unique<PdbAstBuilder>(*m_obj_file, *m_index); + if (auto err = ts_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Failed to initialize"); + } else { + ts_or_err->SetSymbolFile(this); + auto *clang = llvm::cast_or_null<ClangASTContext>(&ts_or_err.get()); + lldbassert(clang); + m_ast = std::make_unique<PdbAstBuilder>(*m_objfile_sp, *m_index, *clang); + } } -uint32_t SymbolFileNativePDB::GetNumCompileUnits() { +uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() { const DbiModuleList &modules = m_index->dbi().modules(); uint32_t count = modules.getModuleCount(); if (count == 0) @@ -430,11 +437,10 @@ SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) { FileSpec fs(source_file_name); CompUnitSP cu_sp = - std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, fs, + std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, fs, toOpaqueUid(cci.m_id), lang, optimized); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - cci.m_id.modi, cu_sp); + SetCompileUnitAtIndex(cci.m_id.modi, cu_sp); return cu_sp; } @@ -730,7 +736,7 @@ TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) { TypeSP type = CreateAndCacheType(type_id); if (type) - m_obj_file->GetModule()->GetTypeList()->Insert(type); + GetTypeList().Insert(type); return type; } @@ -900,6 +906,7 @@ lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) { } lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid uid(comp_unit.GetID()); lldbassert(uid.kind() == PdbSymUidKind::Compiland); @@ -915,6 +922,7 @@ lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) { void SymbolFileNativePDB::AddSymbols(Symtab &symtab) { return; } size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid uid{comp_unit.GetID()}; lldbassert(uid.kind() == PdbSymUidKind::Compiland); uint16_t modi = uid.asCompiland().modi; @@ -948,6 +956,7 @@ static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) { uint32_t SymbolFileNativePDB::ResolveSymbolContext( const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t resolved_flags = 0; lldb::addr_t file_addr = addr.GetFileAddress(); @@ -1052,12 +1061,13 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { // all at once, even if all it really needs is line info for a specific // function. In the future it would be nice if it could set the sc.m_function // member, and we could only get the line info for the function in question. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid cu_id(comp_unit.GetID()); lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); CompilandIndexItem *cci = m_index->compilands().GetCompiland(cu_id.asCompiland().modi); lldbassert(cci); - auto line_table = llvm::make_unique<LineTable>(&comp_unit); + auto line_table = std::make_unique<LineTable>(&comp_unit); // This is basically a copy of the .debug$S subsections from all original COFF // object files merged together with address relocations applied. We are @@ -1130,6 +1140,7 @@ bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) { bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid cu_id(comp_unit.GetID()); lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); CompilandIndexItem *cci = @@ -1160,6 +1171,7 @@ bool SymbolFileNativePDB::ParseImportedModules( } size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); GetOrCreateBlock(PdbSymUid(func.GetID()).asCompilandSym()); // FIXME: Parse child blocks return 1; @@ -1167,9 +1179,10 @@ size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); } -uint32_t SymbolFileNativePDB::FindGlobalVariables( +void SymbolFileNativePDB::FindGlobalVariables( ConstString name, const CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName( @@ -1191,16 +1204,16 @@ uint32_t SymbolFileNativePDB::FindGlobalVariables( continue; } } - return variables.GetSize(); } -uint32_t SymbolFileNativePDB::FindFunctions( +void SymbolFileNativePDB::FindFunctions( ConstString name, const CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // For now we only support lookup by method name. if (!(name_type_mask & eFunctionNameTypeMethod)) - return 0; + return; using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; @@ -1225,45 +1238,34 @@ uint32_t SymbolFileNativePDB::FindFunctions( sc_list.Append(sc); } - - return sc_list.GetSize(); } -uint32_t SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, - bool include_inlines, bool append, - SymbolContextList &sc_list) { - return 0; -} +void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, + bool include_inlines, + SymbolContextList &sc_list) {} -uint32_t SymbolFileNativePDB::FindTypes( +void SymbolFileNativePDB::FindTypes( ConstString name, const CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { - if (!append) - types.Clear(); + uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!name) - return 0; + return; searched_symbol_files.clear(); searched_symbol_files.insert(this); // There is an assumption 'name' is not a regex - size_t match_count = FindTypesByName(name.GetStringRef(), max_matches, types); - - return match_count; + FindTypesByName(name.GetStringRef(), max_matches, types); } -size_t -SymbolFileNativePDB::FindTypes(const std::vector<CompilerContext> &context, - bool append, TypeMap &types) { - return 0; -} +void SymbolFileNativePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, TypeMap &types) {} -size_t SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, - uint32_t max_matches, - TypeMap &types) { +void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, + uint32_t max_matches, + TypeMap &types) { - size_t match_count = 0; std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name); if (max_matches > 0 && max_matches < matches.size()) matches.resize(max_matches); @@ -1274,17 +1276,16 @@ size_t SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, continue; types.Insert(type); - ++match_count; } - return match_count; } size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Only do the full type scan the first time. if (m_done_full_type_scan) return 0; - size_t old_count = m_obj_file->GetModule()->GetTypeList()->GetSize(); + const size_t old_count = GetTypeList().GetSize(); LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); // First process the entire TPI stream. @@ -1314,7 +1315,7 @@ size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) { GetOrCreateTypedef(global); } - size_t new_count = m_obj_file->GetModule()->GetTypeList()->GetSize(); + const size_t new_count = GetTypeList().GetSize(); m_done_full_type_scan = true; @@ -1476,6 +1477,7 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { } size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); lldbassert(sc.function || sc.comp_unit); VariableListSP variables; @@ -1506,9 +1508,10 @@ size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { } CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) { - clang::Decl *decl = m_ast->GetOrCreateDeclForUid(PdbSymUid(uid)); - - return m_ast->ToCompilerDecl(*decl); + if (auto decl = m_ast->GetOrCreateDeclForUid(uid)) + return decl.getValue(); + else + return CompilerDecl(); } CompilerDeclContext @@ -1528,6 +1531,7 @@ SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { } Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto iter = m_types.find(type_uid); // lldb should not be passing us non-sensical type uids. the only way it // could have a type uid in the first place is if we handed it out, in which @@ -1561,11 +1565,9 @@ bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { return m_ast->CompleteType(qt); } -size_t SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, - TypeClass type_mask, - lldb_private::TypeList &type_list) { - return 0; -} +void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, + TypeClass type_mask, + lldb_private::TypeList &type_list) {} CompilerDeclContext SymbolFileNativePDB::FindNamespace(ConstString name, @@ -1573,13 +1575,14 @@ SymbolFileNativePDB::FindNamespace(ConstString name, return {}; } -TypeSystem * +llvm::Expected<TypeSystem &> SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { - auto type_system = - m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); - return type_system; + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); + } + return type_system_or_err; } ConstString SymbolFileNativePDB::GetPluginName() { diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 20daff219a0a..ca7de0e7d1ed 100644 --- a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -9,7 +9,6 @@ #ifndef LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H #define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H -#include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/SymbolFile.h" #include "llvm/ADT/DenseMap.h" @@ -35,7 +34,6 @@ struct UnionRecord; } // namespace llvm namespace lldb_private { -class ClangASTImporter; namespace npdb { class PdbAstBuilder; @@ -55,10 +53,10 @@ public: static const char *GetPluginDescriptionStatic(); - static SymbolFile *CreateInstance(ObjectFile *obj_file); + static SymbolFile *CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFileNativePDB(ObjectFile *ofile); + SymbolFileNativePDB(lldb::ObjectFileSP objfile_sp); ~SymbolFileNativePDB() override; @@ -68,13 +66,9 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - void ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -94,10 +88,10 @@ public: size_t ParseBlocksRecursive(Function &func) override; - uint32_t FindGlobalVariables(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - uint32_t max_matches, - VariableList &variables) override; + void FindGlobalVariables(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + VariableList &variables) override; size_t ParseVariablesForContext(const SymbolContext &sc) override; @@ -120,28 +114,27 @@ public: lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; - size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, - TypeList &type_list) override; + void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, + TypeList &type_list) override; - uint32_t FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, - bool include_inlines, bool append, - SymbolContextList &sc_list) override; + void FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, SymbolContextList &sc_list) override; - uint32_t FindFunctions(const RegularExpression ®ex, bool include_inlines, - bool append, SymbolContextList &sc_list) override; + void FindFunctions(const RegularExpression ®ex, bool include_inlines, + SymbolContextList &sc_list) override; - uint32_t FindTypes(ConstString name, - const CompilerDeclContext *parent_decl_ctx, bool append, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(ConstString name, const CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, + llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeMap &types) override; - size_t FindTypes(const std::vector<CompilerContext> &context, bool append, - TypeMap &types) override; + void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, + TypeMap &types) override; - TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override; + llvm::Expected<TypeSystem &> + GetTypeSystemForLanguage(lldb::LanguageType language) override; CompilerDeclContext FindNamespace(ConstString name, @@ -157,9 +150,12 @@ public: void DumpClangAST(Stream &s) override; private: + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - size_t FindTypesByName(llvm::StringRef name, uint32_t max_matches, - TypeMap &types); + void FindTypesByName(llvm::StringRef name, uint32_t max_matches, + TypeMap &types); lldb::TypeSP CreateModifierType(PdbTypeSymId type_id, const llvm::codeview::ModifierRecord &mr, diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 82cfcfbb040f..47c4ad088494 100644 --- a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -120,24 +120,31 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast, return clang_ast.GetBasicType(eBasicTypeBool); case PDB_BuiltinType::Long: if (width == ast->getTypeSize(ast->LongTy)) - return CompilerType(ast, ast->LongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->LongTy.getAsOpaquePtr()); if (width == ast->getTypeSize(ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->LongLongTy.getAsOpaquePtr()); break; case PDB_BuiltinType::ULong: if (width == ast->getTypeSize(ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->UnsignedLongTy.getAsOpaquePtr()); if (width == ast->getTypeSize(ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->UnsignedLongLongTy.getAsOpaquePtr()); break; case PDB_BuiltinType::WCharT: if (width == ast->getTypeSize(ast->WCharTy)) - return CompilerType(ast, ast->WCharTy); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->WCharTy.getAsOpaquePtr()); break; case PDB_BuiltinType::Char16: - return CompilerType(ast, ast->Char16Ty); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->Char16Ty.getAsOpaquePtr()); case PDB_BuiltinType::Char32: - return CompilerType(ast, ast->Char32Ty); + return CompilerType(ClangASTContext::GetASTContext(ast), + ast->Char32Ty.getAsOpaquePtr()); case PDB_BuiltinType::Float: // Note: types `long double` and `double` have same bit size in MSVC and // there is no information in the PDB to distinguish them. So when falling @@ -940,7 +947,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration( decl, nullptr, arg_type->GetForwardCompilerType(), - clang::SC_None); + clang::SC_None, true); if (param) params.push_back(param); } diff --git a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index 1c17bf6563b3..42bf1b34c956 100644 --- a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp @@ -174,7 +174,7 @@ DWARFExpression ConvertPDBLocationToDWARFExpression( DataBufferSP buffer = std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); DataExtractor extractor(buffer, byte_order, address_size, byte_size); - DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize()); + DWARFExpression result(module, extractor, nullptr); result.SetRegisterKind(register_kind); return result; diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 17dfcdaceb9c..854e735b5f83 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -24,6 +24,7 @@ #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/Variable.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" #include "llvm/DebugInfo/PDB/GenericError.h" @@ -118,29 +119,28 @@ const char *SymbolFilePDB::GetPluginDescriptionStatic() { } lldb_private::SymbolFile * -SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) { - return new SymbolFilePDB(obj_file); +SymbolFilePDB::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFilePDB(std::move(objfile_sp)); } -SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file) - : SymbolFile(object_file), m_session_up(), m_global_scope_up(), - m_cached_compile_unit_count(0) {} +SymbolFilePDB::SymbolFilePDB(lldb::ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)), m_session_up(), m_global_scope_up() {} SymbolFilePDB::~SymbolFilePDB() {} uint32_t SymbolFilePDB::CalculateAbilities() { uint32_t abilities = 0; - if (!m_obj_file) + if (!m_objfile_sp) return 0; if (!m_session_up) { // Lazily load and match the PDB file, but only do this once. - std::string exePath = m_obj_file->GetFileSpec().GetPath(); + std::string exePath = m_objfile_sp->GetFileSpec().GetPath(); auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath), m_session_up); if (error) { llvm::consumeError(std::move(error)); - auto module_sp = m_obj_file->GetModule(); + auto module_sp = m_objfile_sp->GetModule(); if (!module_sp) return 0; // See if any symbol file is specified through `--symfile` option. @@ -183,7 +183,8 @@ uint32_t SymbolFilePDB::CalculateAbilities() { } void SymbolFilePDB::InitializeObject() { - lldb::addr_t obj_load_address = m_obj_file->GetBaseAddress().GetFileAddress(); + lldb::addr_t obj_load_address = + m_objfile_sp->GetBaseAddress().GetFileAddress(); lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS); m_session_up->setLoadAddress(obj_load_address); if (!m_global_scope_up) @@ -191,33 +192,30 @@ void SymbolFilePDB::InitializeObject() { lldbassert(m_global_scope_up.get()); } -uint32_t SymbolFilePDB::GetNumCompileUnits() { - if (m_cached_compile_unit_count == 0) { - auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); - if (!compilands) - return 0; +uint32_t SymbolFilePDB::CalculateNumCompileUnits() { + auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); + if (!compilands) + return 0; - // The linker could link *.dll (compiland language = LINK), or import - // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be - // found as a child of the global scope (PDB executable). Usually, such - // compilands contain `thunk` symbols in which we are not interested for - // now. However we still count them in the compiland list. If we perform - // any compiland related activity, like finding symbols through - // llvm::pdb::IPDBSession methods, such compilands will all be searched - // automatically no matter whether we include them or not. - m_cached_compile_unit_count = compilands->getChildCount(); - - // The linker can inject an additional "dummy" compilation unit into the - // PDB. Ignore this special compile unit for our purposes, if it is there. - // It is always the last one. - auto last_compiland_up = - compilands->getChildAtIndex(m_cached_compile_unit_count - 1); - lldbassert(last_compiland_up.get()); - std::string name = last_compiland_up->getName(); - if (name == "* Linker *") - --m_cached_compile_unit_count; - } - return m_cached_compile_unit_count; + // The linker could link *.dll (compiland language = LINK), or import + // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be + // found as a child of the global scope (PDB executable). Usually, such + // compilands contain `thunk` symbols in which we are not interested for + // now. However we still count them in the compiland list. If we perform + // any compiland related activity, like finding symbols through + // llvm::pdb::IPDBSession methods, such compilands will all be searched + // automatically no matter whether we include them or not. + uint32_t compile_unit_count = compilands->getChildCount(); + + // The linker can inject an additional "dummy" compilation unit into the + // PDB. Ignore this special compile unit for our purposes, if it is there. + // It is always the last one. + auto last_compiland_up = compilands->getChildAtIndex(compile_unit_count - 1); + lldbassert(last_compiland_up.get()); + std::string name = last_compiland_up->getName(); + if (name == "* Linker *") + --compile_unit_count; + return compile_unit_count; } void SymbolFilePDB::GetCompileUnitIndex( @@ -261,6 +259,7 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) { } lldb::LanguageType SymbolFilePDB::ParseLanguage(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return lldb::eLanguageTypeUnknown; @@ -302,11 +301,15 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, comp_unit.AddFunction(func_sp); LanguageType lang = ParseLanguage(comp_unit); - TypeSystem *type_system = GetTypeSystemForLanguage(lang); - if (!type_system) + auto type_system_or_err = GetTypeSystemForLanguage(lang); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse PDBFunc"); return nullptr; + } + ClangASTContext *clang_type_system = - llvm::dyn_cast_or_null<ClangASTContext>(type_system); + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return nullptr; clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func); @@ -315,6 +318,7 @@ SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, } size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t func_added = 0; auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) @@ -333,6 +337,7 @@ size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) { } bool SymbolFilePDB::ParseLineTable(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (comp_unit.GetLineTable()) return true; return ParseCompileUnitLineTable(comp_unit, 0); @@ -351,6 +356,7 @@ bool SymbolFilePDB::ParseSupportFiles( // second time seems like a waste. Unfortunately, there's no good way around // this short of a moderate refactor since SymbolVendor depends on being able // to cache this list. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return false; @@ -428,6 +434,7 @@ static size_t ParseFunctionBlocksForPDBSymbol( } size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t num_added = 0; auto uid = func.GetID(); auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); @@ -440,6 +447,7 @@ size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) { } size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t num_added = 0; auto compiland = GetPDBCompilandByUID(comp_unit.GetID()); @@ -492,6 +500,7 @@ size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!sc.comp_unit) return 0; @@ -540,14 +549,21 @@ SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { } lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); auto find_result = m_types.find(type_uid); if (find_result != m_types.end()) return find_result->second.get(); - TypeSystem *type_system = + auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to ResolveTypeUID"); + return nullptr; + } + ClangASTContext *clang_type_system = - llvm::dyn_cast_or_null<ClangASTContext>(type_system); + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return nullptr; PDBASTParser *pdb = clang_type_system->GetPDBParser(); @@ -561,9 +577,7 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type); if (result) { m_types.insert(std::make_pair(type_uid, result)); - auto type_list = GetTypeList(); - if (type_list) - type_list->Insert(result); + GetTypeList().Insert(result); } return result.get(); } @@ -577,8 +591,17 @@ bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { std::lock_guard<std::recursive_mutex> guard( GetObjectFile()->GetModule()->GetMutex()); - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get dynamic array info for UID"); + return false; + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); + if (!clang_ast_ctx) return false; @@ -590,8 +613,16 @@ bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { } lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get decl for UID"); + return CompilerDecl(); + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return CompilerDecl(); @@ -612,8 +643,16 @@ lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { lldb_private::CompilerDeclContext SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DeclContext for UID"); + return CompilerDeclContext(); + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return CompilerDeclContext(); @@ -634,8 +673,16 @@ SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { lldb_private::CompilerDeclContext SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DeclContext containing UID"); + return CompilerDeclContext(); + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return CompilerDeclContext(); @@ -655,8 +702,16 @@ SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { void SymbolFilePDB::ParseDeclsForContext( lldb_private::CompilerDeclContext decl_ctx) { - ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( - GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to parse decls for context"); + return; + } + + ClangASTContext *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_ast_ctx) return; @@ -672,6 +727,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); uint32_t resolved_flags = 0; if (resolve_scope & eSymbolContextCompUnit || resolve_scope & eSymbolContextVariable || @@ -680,7 +736,7 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, resolve_scope & eSymbolContextLineEntry) { auto cu_sp = GetCompileUnitContainsAddress(so_addr); if (!cu_sp) { - if (resolved_flags | eSymbolContextVariable) { + if (resolved_flags & eSymbolContextVariable) { // TODO: Resolve variables } return 0; @@ -732,6 +788,7 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, uint32_t SymbolFilePDB::ResolveSymbolContext( const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const size_t old_size = sc_list.GetSize(); if (resolve_scope & lldb::eSymbolContextCompUnit) { // Locate all compilation units with line numbers referencing the specified @@ -1040,18 +1097,19 @@ SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc, return num_added; } -uint32_t SymbolFilePDB::FindGlobalVariables( +void SymbolFilePDB::FindGlobalVariables( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; if (name.IsEmpty()) - return 0; + return; auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); if (!results) - return 0; + return; uint32_t matches = 0; size_t old_size = variables.GetSize(); @@ -1061,7 +1119,7 @@ uint32_t SymbolFilePDB::FindGlobalVariables( break; SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); lldbassert(sc.module_sp.get()); if (!name.GetStringRef().equals( @@ -1080,19 +1138,17 @@ uint32_t SymbolFilePDB::FindGlobalVariables( ParseVariables(sc, *pdb_data, &variables); matches = variables.GetSize() - old_size; } - - return matches; } -uint32_t -SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) { +void SymbolFilePDB::FindGlobalVariables( + const lldb_private::RegularExpression ®ex, uint32_t max_matches, + lldb_private::VariableList &variables) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!regex.IsValid()) - return 0; + return; auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); if (!results) - return 0; + return; uint32_t matches = 0; size_t old_size = variables.GetSize(); @@ -1106,7 +1162,7 @@ SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, if (!regex.Execute(var_name)) continue; SymbolContext sc; - sc.module_sp = m_obj_file->GetModule(); + sc.module_sp = m_objfile_sp->GetModule(); lldbassert(sc.module_sp.get()); sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get(); @@ -1117,8 +1173,6 @@ SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, ParseVariables(sc, *pdb_data, &variables); matches = variables.GetSize() - old_size; } - - return matches; } bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func, @@ -1240,23 +1294,21 @@ void SymbolFilePDB::CacheFunctionNames() { m_func_base_names.SizeToFit(); } -uint32_t SymbolFilePDB::FindFunctions( +void SymbolFilePDB::FindFunctions( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - FunctionNameType name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, lldb_private::SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0); if (name_type_mask == eFunctionNameTypeNone) - return 0; + return; if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; if (name.IsEmpty()) - return 0; + return; - auto old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeFull || name_type_mask & eFunctionNameTypeBase || name_type_mask & eFunctionNameTypeMethod) { @@ -1286,26 +1338,20 @@ uint32_t SymbolFilePDB::FindFunctions( ResolveFn(m_func_base_names); ResolveFn(m_func_method_names); } - if (name_type_mask & eFunctionNameTypeBase) { + if (name_type_mask & eFunctionNameTypeBase) ResolveFn(m_func_base_names); - } - if (name_type_mask & eFunctionNameTypeMethod) { + if (name_type_mask & eFunctionNameTypeMethod) ResolveFn(m_func_method_names); - } } - return sc_list.GetSize() - old_size; } -uint32_t -SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) { - if (!append) - sc_list.Clear(); +void SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!regex.IsValid()) - return 0; + return; - auto old_size = sc_list.GetSize(); CacheFunctionNames(); std::set<uint32_t> resolved_ids; @@ -1322,8 +1368,6 @@ SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, }; ResolveFn(m_func_full_names); ResolveFn(m_func_base_names); - - return sc_list.GetSize() - old_size; } void SymbolFilePDB::GetMangledNamesForFunction( @@ -1339,7 +1383,7 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { if (!results) return; - auto section_list = m_obj_file->GetSectionList(); + auto section_list = m_objfile_sp->GetSectionList(); if (!section_list) return; @@ -1361,7 +1405,6 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { symtab.AddSymbol( Symbol(pub_symbol->getSymIndexId(), // symID pub_symbol->getName().c_str(), // name - true, // name_is_mangled pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type true, // external false, // is_debug @@ -1380,34 +1423,39 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { symtab.Finalize(); } -uint32_t SymbolFilePDB::FindTypes( +void SymbolFilePDB::FindTypes( lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, + const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) { - if (!append) - types.Clear(); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!name) - return 0; + return; if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return 0; + return; searched_symbol_files.clear(); searched_symbol_files.insert(this); // There is an assumption 'name' is not a regex FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types); - - return types.GetSize(); } void SymbolFilePDB::DumpClangAST(Stream &s) { - auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - auto clang = llvm::dyn_cast_or_null<ClangASTContext>(type_system); - if (!clang) + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to dump ClangAST"); + return; + } + + auto *clang_type_system = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); + if (!clang_type_system) return; - clang->Dump(s); + clang_type_system->Dump(s); } void SymbolFilePDB::FindTypesByRegex( @@ -1514,15 +1562,9 @@ void SymbolFilePDB::FindTypesByName( } } -size_t SymbolFilePDB::FindTypes( - const std::vector<lldb_private::CompilerContext> &contexts, bool append, - lldb_private::TypeMap &types) { - return 0; -} - -lldb_private::TypeList *SymbolFilePDB::GetTypeList() { - return m_obj_file->GetModule()->GetTypeList(); -} +void SymbolFilePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern, + LanguageSet languages, + lldb_private::TypeMap &types) {} void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, uint32_t type_mask, @@ -1574,17 +1616,17 @@ void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection); } -size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, - TypeClass type_mask, - lldb_private::TypeList &type_list) { +void SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, + TypeClass type_mask, + lldb_private::TypeList &type_list) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); TypeCollection type_collection; - uint32_t old_size = type_list.GetSize(); CompileUnit *cu = sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr; if (cu) { auto compiland_up = GetPDBCompilandByUID(cu->GetID()); if (!compiland_up) - return 0; + return; GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection); } else { for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { @@ -1600,21 +1642,29 @@ size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, type->GetForwardCompilerType(); type_list.Insert(type->shared_from_this()); } - return type_list.GetSize() - old_size; } -lldb_private::TypeSystem * +llvm::Expected<lldb_private::TypeSystem &> SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { - auto type_system = - m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); - return type_system; + auto type_system_or_err = + m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); + if (type_system_or_err) { + type_system_or_err->SetSymbolFile(this); + } + return type_system_or_err; } PDBASTParser *SymbolFilePDB::GetPDBAstParser() { - auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get PDB AST parser"); + return nullptr; + } + + auto *clang_type_system = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return nullptr; @@ -1625,8 +1675,18 @@ PDBASTParser *SymbolFilePDB::GetPDBAstParser() { lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx) { - auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); - auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + auto type_system_or_err = + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to find namespace {}", + name.AsCString()); + return CompilerDeclContext(); + } + + auto *clang_type_system = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); if (!clang_type_system) return CompilerDeclContext(); @@ -1644,7 +1704,7 @@ lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( if (!namespace_decl) return CompilerDeclContext(); - return CompilerDeclContext(type_system, + return CompilerDeclContext(clang_type_system, static_cast<clang::DeclContext *>(namespace_decl)); } @@ -1688,7 +1748,7 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, // Don't support optimized code for now, DebugInfoPDB does not return this // information. LazyBool optimized = eLazyBoolNo; - auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, + auto cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, path.c_str(), id, lang, optimized); if (!cu_sp) @@ -1698,8 +1758,7 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, if (index == UINT32_MAX) GetCompileUnitIndex(*compiland_up, index); lldbassert(index != UINT32_MAX); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(index, - cu_sp); + SetCompileUnitAtIndex(index, cu_sp); return cu_sp; } @@ -1715,7 +1774,7 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit, // to do a mapping so that we can hand out indices. llvm::DenseMap<uint32_t, uint32_t> index_map; BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map); - auto line_table = llvm::make_unique<LineTable>(&comp_unit); + auto line_table = std::make_unique<LineTable>(&comp_unit); // Find contributions to `compiland` from all source and header files. std::string path = comp_unit.GetPath(); @@ -1925,9 +1984,17 @@ bool SymbolFilePDB::DeclContextMatchesThisSymbolFile( TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); if (!decl_ctx_type_system) return false; - TypeSystem *type_system = GetTypeSystemForLanguage( + auto type_system_or_err = GetTypeSystemForLanguage( decl_ctx_type_system->GetMinimumLanguage(nullptr)); - if (decl_ctx_type_system == type_system) + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR( + lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), + "Unable to determine if DeclContext matches this symbol file"); + return false; + } + + if (decl_ctx_type_system == &type_system_or_err.get()) return true; // The type systems match, return true return false; diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index ba3099aaec4d..df717bbbbdb0 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -35,10 +35,10 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFilePDB(lldb_private::ObjectFile *ofile); + SymbolFilePDB(lldb::ObjectFileSP objfile_sp); ~SymbolFilePDB() override; @@ -48,10 +48,6 @@ public: // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -103,25 +99,25 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; - uint32_t + void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t max_matches, lldb_private::VariableList &variables) override; - uint32_t FindGlobalVariables(const lldb_private::RegularExpression ®ex, - uint32_t max_matches, - lldb_private::VariableList &variables) override; + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; - uint32_t - FindFunctions(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext *parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, - bool append, lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; - uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, - bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; void GetMangledNamesForFunction( const std::string &scope_qualified_name, @@ -129,26 +125,25 @@ public: void AddSymbols(lldb_private::Symtab &symtab) override; - uint32_t + void FindTypes(lldb_private::ConstString name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - bool append, uint32_t max_matches, + uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector<lldb_private::CompilerContext> &context, - bool append, lldb_private::TypeMap &types) override; + void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, + lldb_private::LanguageSet languages, + lldb_private::TypeMap &types) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types); - lldb_private::TypeList *GetTypeList() override; - - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; - lldb_private::TypeSystem * + llvm::Expected<lldb_private::TypeSystem &> GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( @@ -173,6 +168,10 @@ private: }; using SecContribsMap = std::map<uint32_t, std::vector<SecContribInfo>>; + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + lldb::CompUnitSP ParseCompileUnitForUID(uint32_t id, uint32_t index = UINT32_MAX); @@ -245,7 +244,6 @@ private: std::vector<lldb::TypeSP> m_builtin_types; std::unique_ptr<llvm::pdb::IPDBSession> m_session_up; std::unique_ptr<llvm::pdb::PDBSymbolExe> m_global_scope_up; - uint32_t m_cached_compile_unit_count; lldb_private::UniqueCStringMap<uint32_t> m_func_full_names; lldb_private::UniqueCStringMap<uint32_t> m_func_base_names; diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index a1b21e51b0fe..62da76581c3e 100644 --- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -43,26 +43,24 @@ const char *SymbolFileSymtab::GetPluginDescriptionStatic() { return "Reads debug symbols from an object file's symbol table."; } -SymbolFile *SymbolFileSymtab::CreateInstance(ObjectFile *obj_file) { - return new SymbolFileSymtab(obj_file); +SymbolFile *SymbolFileSymtab::CreateInstance(ObjectFileSP objfile_sp) { + return new SymbolFileSymtab(std::move(objfile_sp)); } -size_t SymbolFileSymtab::GetTypes(SymbolContextScope *sc_scope, - TypeClass type_mask, - lldb_private::TypeList &type_list) { - return 0; -} +void SymbolFileSymtab::GetTypes(SymbolContextScope *sc_scope, + TypeClass type_mask, + lldb_private::TypeList &type_list) {} -SymbolFileSymtab::SymbolFileSymtab(ObjectFile *obj_file) - : SymbolFile(obj_file), m_source_indexes(), m_func_indexes(), +SymbolFileSymtab::SymbolFileSymtab(ObjectFileSP objfile_sp) + : SymbolFile(std::move(objfile_sp)), m_source_indexes(), m_func_indexes(), m_code_indexes(), m_objc_class_name_to_index() {} SymbolFileSymtab::~SymbolFileSymtab() {} uint32_t SymbolFileSymtab::CalculateAbilities() { uint32_t abilities = 0; - if (m_obj_file) { - const Symtab *symtab = m_obj_file->GetSymtab(); + if (m_objfile_sp) { + const Symtab *symtab = m_objfile_sp->GetSymtab(); if (symtab) { // The snippet of code below will get the indexes the module symbol table // entries that are code, data, or function related (debug info), sort @@ -104,7 +102,7 @@ uint32_t SymbolFileSymtab::CalculateAbilities() { return abilities; } -uint32_t SymbolFileSymtab::GetNumCompileUnits() { +uint32_t SymbolFileSymtab::CalculateNumCompileUnits() { // If we don't have any source file symbols we will just have one compile // unit for the entire object file if (m_source_indexes.empty()) @@ -122,10 +120,10 @@ CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) { // unit for the entire object file if (idx < m_source_indexes.size()) { const Symbol *cu_symbol = - m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); + m_objfile_sp->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) - cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, - cu_symbol->GetName().AsCString(), 0, + cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, + cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, eLazyBoolNo); } return cu_sp; @@ -136,12 +134,13 @@ lldb::LanguageType SymbolFileSymtab::ParseLanguage(CompileUnit &comp_unit) { } size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); size_t num_added = 0; // We must at least have a valid compile unit - const Symtab *symtab = m_obj_file->GetSymtab(); + const Symtab *symtab = m_objfile_sp->GetSymtab(); const Symbol *curr_symbol = nullptr; const Symbol *next_symbol = nullptr; - // const char *prefix = m_obj_file->SymbolPrefix(); + // const char *prefix = m_objfile_sp->SymbolPrefix(); // if (prefix == NULL) // prefix == ""; // @@ -246,12 +245,13 @@ bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) { uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { - if (m_obj_file->GetSymtab() == nullptr) + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (m_objfile_sp->GetSymtab() == nullptr) return 0; uint32_t resolved_flags = 0; if (resolve_scope & eSymbolContextSymbol) { - sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress( + sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress( so_addr.GetFileAddress()); if (sc.symbol) resolved_flags |= eSymbolContextSymbol; diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index bc9a531419ae..2ac4660f0125 100644 --- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -18,7 +18,7 @@ class SymbolFileSymtab : public lldb_private::SymbolFile { public: // Constructors and Destructors - SymbolFileSymtab(lldb_private::ObjectFile *obj_file); + SymbolFileSymtab(lldb::ObjectFileSP objfile_sp); ~SymbolFileSymtab() override; @@ -32,15 +32,11 @@ public: static const char *GetPluginDescriptionStatic(); static lldb_private::SymbolFile * - CreateInstance(lldb_private::ObjectFile *obj_file); + CreateInstance(lldb::ObjectFileSP objfile_sp); uint32_t CalculateAbilities() override; // Compile Unit function calls - uint32_t GetNumCompileUnits() override; - - lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::LanguageType ParseLanguage(lldb_private::CompileUnit &comp_unit) override; @@ -75,9 +71,9 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - lldb::TypeClass type_mask, - lldb_private::TypeList &type_list) override; + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; // PluginInterface protocol lldb_private::ConstString GetPluginName() override; @@ -85,6 +81,10 @@ public: uint32_t GetPluginVersion() override; protected: + uint32_t CalculateNumCompileUnits() override; + + lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; + typedef std::map<lldb_private::ConstString, lldb::TypeSP> TypeMap; lldb_private::Symtab::IndexCollection m_source_indexes; diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index f279af61a131..e61e5763fabb 100644 --- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -10,6 +10,7 @@ #include <string.h> +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -61,99 +62,86 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, if (!module_sp) return nullptr; - ObjectFile *obj_file = module_sp->GetObjectFile(); + ObjectFileELF *obj_file = + llvm::dyn_cast_or_null<ObjectFileELF>(module_sp->GetObjectFile()); if (!obj_file) return nullptr; - static ConstString obj_file_elf("elf"); - ConstString obj_name = obj_file->GetPluginName(); - if (obj_name != obj_file_elf) - return nullptr; - lldb_private::UUID uuid = obj_file->GetUUID(); if (!uuid) return nullptr; - // Get the .gnu_debuglink file (if specified). - FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths(); - - // If the module specified a filespec, use it first. - FileSpec debug_symbol_fspec(module_sp->GetSymbolFileFileSpec()); - if (debug_symbol_fspec) - file_spec_list.Insert(0, debug_symbol_fspec); - - // If we have no debug symbol files, then nothing to do. - if (file_spec_list.IsEmpty()) + // If the main object file already contains debug info, then we are done. + if (obj_file->GetSectionList()->FindSectionByType( + lldb::eSectionTypeDWARFDebugInfo, true)) return nullptr; + // If the module specified a filespec, use that. + FileSpec fspec = module_sp->GetSymbolFileFileSpec(); + // Otherwise, try gnu_debuglink, if one exists. + if (!fspec) + fspec = obj_file->GetDebugLink().getValueOr(FileSpec()); + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolVendorELF::CreateInstance (module = %s)", module_sp->GetFileSpec().GetPath().c_str()); - for (size_t idx = 0; idx < file_spec_list.GetSize(); ++idx) { - ModuleSpec module_spec; - const FileSpec fspec = file_spec_list.GetFileSpecAtIndex(idx); - - module_spec.GetFileSpec() = obj_file->GetFileSpec(); - FileSystem::Instance().Resolve(module_spec.GetFileSpec()); - module_spec.GetSymbolFileSpec() = fspec; - module_spec.GetUUID() = uuid; - FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); - FileSpec dsym_fspec = - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); - if (dsym_fspec) { - DataBufferSP dsym_file_data_sp; - lldb::offset_t dsym_file_data_offset = 0; - ObjectFileSP dsym_objfile_sp = - ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, - FileSystem::Instance().GetByteSize(dsym_fspec), - dsym_file_data_sp, dsym_file_data_offset); - if (dsym_objfile_sp) { - // This objfile is for debugging purposes. Sadly, ObjectFileELF won't - // be able to figure this out consistently as the symbol file may not - // have stripped the code sections, etc. - dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); - - SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp); - if (symbol_vendor) { - // Get the module unified section list and add our debug sections to - // that. - SectionList *module_section_list = module_sp->GetSectionList(); - SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); - - static const SectionType g_sections[] = { - eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, - eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, - eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, - eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, - eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, - eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, - eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, - eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink, - }; - for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); - ++idx) { - SectionType section_type = g_sections[idx]; - SectionSP section_sp( - objfile_section_list->FindSectionByType(section_type, true)); - if (section_sp) { - SectionSP module_section_sp( - module_section_list->FindSectionByType(section_type, true)); - if (module_section_sp) - module_section_list->ReplaceSection(module_section_sp->GetID(), - section_sp); - else - module_section_list->AddSection(section_sp); - } - } - - symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); - return symbol_vendor; - } - } + ModuleSpec module_spec; + + module_spec.GetFileSpec() = obj_file->GetFileSpec(); + FileSystem::Instance().Resolve(module_spec.GetFileSpec()); + module_spec.GetSymbolFileSpec() = fspec; + module_spec.GetUUID() = uuid; + FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); + FileSpec dsym_fspec = + Symbols::LocateExecutableSymbolFile(module_spec, search_paths); + if (!dsym_fspec) + return nullptr; + + DataBufferSP dsym_file_data_sp; + lldb::offset_t dsym_file_data_offset = 0; + ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin( + module_sp, &dsym_fspec, 0, FileSystem::Instance().GetByteSize(dsym_fspec), + dsym_file_data_sp, dsym_file_data_offset); + if (!dsym_objfile_sp) + return nullptr; + + // This objfile is for debugging purposes. Sadly, ObjectFileELF won't + // be able to figure this out consistently as the symbol file may not + // have stripped the code sections, etc. + dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo); + + SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp); + + // Get the module unified section list and add our debug sections to + // that. + SectionList *module_section_list = module_sp->GetSectionList(); + SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList(); + + static const SectionType g_sections[] = { + eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, + eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, + eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, + eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, + eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, + eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, + eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink, + }; + for (SectionType section_type : g_sections) { + if (SectionSP section_sp = + objfile_section_list->FindSectionByType(section_type, true)) { + if (SectionSP module_section_sp = + module_section_list->FindSectionByType(section_type, true)) + module_section_list->ReplaceSection(module_section_sp->GetID(), + section_sp); + else + module_section_list->AddSection(section_sp); } } - return nullptr; + + symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); + return symbol_vendor; } // PluginInterface protocol diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 43041ca1bb2f..bf6f60a2d26c 100644 --- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -1328,6 +1328,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( unwind_plan.SetSourceName("assembly insn profiling"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); return true; } @@ -1370,7 +1371,6 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( int row_id = 1; bool unwind_plan_updated = false; UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row)); - m_cur_insn = data + offset; // After a mid-function epilogue we will need to re-insert the original // unwind rules so unwinds work for the remainder of the function. These @@ -1380,19 +1380,17 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( while (offset < size) { m_cur_insn = data + offset; int insn_len; - if (!instruction_length(m_cur_insn, insn_len, size - offset) - || insn_len == 0 - || insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) || + insn_len == 0 || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction. break; } // Advance offsets. offset += insn_len; - m_cur_insn = data + offset; // offset is pointing beyond the bounds of the function; stop looping. - if (offset >= size) + if (offset >= size) continue; if (reinstate_unwind_state) { @@ -1546,16 +1544,18 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( // [0x5d] pop %rbp/%ebp // => [0xc3] ret if (pop_rbp_pattern_p() || leave_pattern_p()) { - offset += 1; - row->SetOffset(offset); - row->GetCFAValue().SetIsRegisterPlusOffset( - first_row->GetCFAValue().GetRegisterNumber(), m_wordsize); - - UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); - unwind_plan.InsertRow(new_row); - unwind_plan_updated = true; - reinstate_unwind_state = true; - continue; + m_cur_insn++; + if (ret_pattern_p()) { + row->SetOffset(offset); + row->GetCFAValue().SetIsRegisterPlusOffset( + first_row->GetCFAValue().GetRegisterNumber(), m_wordsize); + + UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); + unwind_plan.InsertRow(new_row); + unwind_plan_updated = true; + reinstate_unwind_state = true; + continue; + } } } else { // CFA register is not sp or fp. |