diff options
Diffstat (limited to 'lldb/source/Plugins')
32 files changed, 564 insertions, 122 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 9f77fbc..214e260 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1991,7 +1991,7 @@ void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context, const bool is_artificial = false; CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType( - copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr, + copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", /*asm_label=*/{}, method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 3995bc0..e5a1d2d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -894,7 +894,7 @@ ClangExpressionParser::ClangExpressionParser( m_llvm_context = std::make_unique<LLVMContext>(); m_code_generator.reset(CreateLLVMCodeGen( m_compiler->getDiagnostics(), module_name, - &m_compiler->getVirtualFileSystem(), m_compiler->getHeaderSearchOpts(), + m_compiler->getVirtualFileSystemPtr(), m_compiler->getHeaderSearchOpts(), m_compiler->getPreprocessorOpts(), m_compiler->getCodeGenOpts(), *m_llvm_context)); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index 06f3a7e..ff9ed9c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -260,9 +260,8 @@ TokenVerifier::TokenVerifier(std::string body) { // Let's build the actual source code Clang needs and setup some utility // objects. - llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs()); DiagnosticOptions diags_opts; - DiagnosticsEngine diags(diag_ids, diags_opts); + DiagnosticsEngine diags(DiagnosticIDs::create(), diags_opts); clang::SourceManager SM(diags, file_mgr); auto buf = llvm::MemoryBuffer::getMemBuffer(body); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 2f838b3..d54f072 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -747,7 +747,7 @@ ClangModulesDeclVendor::Create(Target &target) { // Make sure clang uses the same VFS as LLDB. instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem()); - instance->setDiagnostics(diagnostics_engine.get()); + instance->setDiagnostics(diagnostics_engine); std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction); diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp index 2adde02..5e429a9 100644 --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -1807,7 +1807,7 @@ RISCVSingleStepBreakpointLocationsPredictor::GetBreakpointLocations( Log *log = GetLog(LLDBLog::Unwind); LLDB_LOGF(log, "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find " - "corresponding load reserve insturuction", + "corresponding load reserve instruction", __FUNCTION__); return {*pc + (inst->is_rvc ? 2u : 4u)}; } @@ -1839,7 +1839,7 @@ RISCVSingleStepBreakpointLocationsPredictor::HandleAtomicSequence( EmulateInstructionRISCV *riscv_emulator = static_cast<EmulateInstructionRISCV *>(m_emulator_up.get()); - // Handle instructions between LR and SC. According to unprivilleged + // Handle instructions between LR and SC. According to unprivileged // RISC-V ISA there can be at most 16 instructions in the sequence. lldb::addr_t entry_pc = pc; // LR instruction address @@ -1872,7 +1872,7 @@ RISCVSingleStepBreakpointLocationsPredictor::HandleAtomicSequence( Log *log = GetLog(LLDBLog::Unwind); LLDB_LOGF(log, "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find " - "corresponding store conditional insturuction", + "corresponding store conditional instruction", __FUNCTION__); return {entry_pc + (lr_inst->is_rvc ? 2u : 4u)}; } diff --git a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp index 8cc5714..9cb5ea3 100644 --- a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp +++ b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp @@ -162,9 +162,8 @@ void ClangHighlighter::Highlight(const HighlightStyle &options, // Let's build the actual source code Clang needs and setup some utility // objects. std::string full_source = previous_lines.str() + line.str(); - llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs()); DiagnosticOptions diags_opts; - DiagnosticsEngine diags(diag_ids, diags_opts); + DiagnosticsEngine diags(DiagnosticIDs::create(), diags_opts); clang::SourceManager SM(diags, file_mgr); auto buf = llvm::MemoryBuffer::getMemBuffer(full_source); diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt index ff8a3c7..779b97e 100644 --- a/lldb/source/Plugins/Process/wasm/CMakeLists.txt +++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt @@ -1,5 +1,6 @@ add_lldb_library(lldbPluginProcessWasm PLUGIN ProcessWasm.cpp + RegisterContextWasm.cpp ThreadWasm.cpp UnwindWasm.cpp diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp index 5eeabec..580e8c1 100644 --- a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp @@ -131,3 +131,36 @@ ProcessWasm::GetWasmCallStack(lldb::tid_t tid) { return call_stack_pcs; } + +llvm::Expected<lldb::DataBufferSP> +ProcessWasm::GetWasmVariable(WasmVirtualRegisterKinds kind, int frame_index, + int index) { + StreamString packet; + switch (kind) { + case eWasmTagLocal: + packet.Printf("qWasmLocal:"); + break; + case eWasmTagGlobal: + packet.Printf("qWasmGlobal:"); + break; + case eWasmTagOperandStack: + packet.PutCString("qWasmStackValue:"); + break; + case eWasmTagNotAWasmLocation: + return llvm::createStringError("not a Wasm location"); + } + packet.Printf("%d;%d", frame_index, index); + + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != + GDBRemoteCommunication::PacketResult::Success) + return llvm::createStringError("failed to send Wasm variable"); + + if (!response.IsNormalResponse()) + return llvm::createStringError("failed to get response for Wasm variable"); + + WritableDataBufferSP buffer_sp( + new DataBufferHeap(response.GetStringRef().size() / 2, 0)); + response.GetHexBytes(buffer_sp->GetData(), '\xcc'); + return buffer_sp; +} diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h index bab14a8..22effe7 100644 --- a/lldb/source/Plugins/Process/wasm/ProcessWasm.h +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" +#include "Utility/WasmVirtualRegisters.h" namespace lldb_private { namespace wasm { @@ -71,12 +72,19 @@ public: /// Retrieve the current call stack from the WebAssembly remote process. llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack(lldb::tid_t tid); + /// Query the value of a WebAssembly variable from the WebAssembly + /// remote process. + llvm::Expected<lldb::DataBufferSP> + GetWasmVariable(WasmVirtualRegisterKinds kind, int frame_index, int index); + protected: std::shared_ptr<process_gdb_remote::ThreadGDBRemote> CreateThread(lldb::tid_t tid) override; private: friend class UnwindWasm; + friend class ThreadWasm; + process_gdb_remote::GDBRemoteDynamicRegisterInfoSP &GetRegisterInfo() { return m_register_info_sp; } diff --git a/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp new file mode 100644 index 0000000..b468171 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// 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 "RegisterContextWasm.h" +#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h" +#include "ProcessWasm.h" +#include "ThreadWasm.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Error.h" +#include <memory> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_gdb_remote; +using namespace lldb_private::wasm; + +RegisterContextWasm::RegisterContextWasm( + wasm::ThreadWasm &thread, uint32_t concrete_frame_idx, + GDBRemoteDynamicRegisterInfoSP reg_info_sp) + : GDBRemoteRegisterContext(thread, concrete_frame_idx, reg_info_sp, false, + false) {} + +RegisterContextWasm::~RegisterContextWasm() = default; + +uint32_t RegisterContextWasm::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + return num; +} + +size_t RegisterContextWasm::GetRegisterCount() { + // Wasm has no registers. + return 0; +} + +const RegisterInfo *RegisterContextWasm::GetRegisterInfoAtIndex(size_t reg) { + uint32_t tag = GetWasmVirtualRegisterTag(reg); + if (tag == eWasmTagNotAWasmLocation) + return m_reg_info_sp->GetRegisterInfoAtIndex( + GetWasmVirtualRegisterIndex(reg)); + + auto it = m_register_map.find(reg); + if (it == m_register_map.end()) { + WasmVirtualRegisterKinds kind = static_cast<WasmVirtualRegisterKinds>(tag); + std::tie(it, std::ignore) = m_register_map.insert( + {reg, std::make_unique<WasmVirtualRegisterInfo>( + kind, GetWasmVirtualRegisterIndex(reg))}); + } + return it->second.get(); +} + +size_t RegisterContextWasm::GetRegisterSetCount() { return 0; } + +const RegisterSet *RegisterContextWasm::GetRegisterSet(size_t reg_set) { + // Wasm has no registers. + return nullptr; +} + +bool RegisterContextWasm::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + // The only real registers is the PC. + if (reg_info->name) + return GDBRemoteRegisterContext::ReadRegister(reg_info, value); + + // Read the virtual registers. + ThreadWasm *thread = static_cast<ThreadWasm *>(&GetThread()); + ProcessWasm *process = static_cast<ProcessWasm *>(thread->GetProcess().get()); + if (!thread) + return false; + + uint32_t frame_index = m_concrete_frame_idx; + WasmVirtualRegisterInfo *wasm_reg_info = + static_cast<WasmVirtualRegisterInfo *>( + const_cast<RegisterInfo *>(reg_info)); + + llvm::Expected<DataBufferSP> maybe_buffer = process->GetWasmVariable( + wasm_reg_info->kind, frame_index, wasm_reg_info->index); + if (!maybe_buffer) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Process), maybe_buffer.takeError(), + "Failed to read Wasm local: {0}"); + return false; + } + + DataBufferSP buffer_sp = *maybe_buffer; + DataExtractor reg_data(buffer_sp, process->GetByteOrder(), + process->GetAddressByteSize()); + wasm_reg_info->byte_size = buffer_sp->GetByteSize(); + wasm_reg_info->encoding = lldb::eEncodingUint; + + Status error = value.SetValueFromData( + *reg_info, reg_data, reg_info->byte_offset, /*partial_data_ok=*/false); + return error.Success(); +} + +void RegisterContextWasm::InvalidateAllRegisters() {} + +bool RegisterContextWasm::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + // The only real registers is the PC. + if (reg_info->name) + return GDBRemoteRegisterContext::WriteRegister(reg_info, value); + return false; +} diff --git a/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h new file mode 100644 index 0000000..7e63eb8 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_WASM_REGISTERCONTEXTWASM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_REGISTERCONTEXTWASM_H + +#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h" +#include "ThreadWasm.h" +#include "Utility/WasmVirtualRegisters.h" +#include "lldb/lldb-private-types.h" +#include <unordered_map> + +namespace lldb_private { +namespace wasm { + +class RegisterContextWasm; + +typedef std::shared_ptr<RegisterContextWasm> RegisterContextWasmSP; + +struct WasmVirtualRegisterInfo : public RegisterInfo { + WasmVirtualRegisterKinds kind; + uint32_t index; + + WasmVirtualRegisterInfo(WasmVirtualRegisterKinds kind, uint32_t index) + : RegisterInfo(), kind(kind), index(index) {} +}; + +class RegisterContextWasm + : public process_gdb_remote::GDBRemoteRegisterContext { +public: + RegisterContextWasm( + wasm::ThreadWasm &thread, uint32_t concrete_frame_idx, + process_gdb_remote::GDBRemoteDynamicRegisterInfoSP reg_info_sp); + + ~RegisterContextWasm() override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const RegisterSet *GetRegisterSet(size_t reg_set) override; + + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) override; + + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) override; + +private: + std::unordered_map<size_t, std::unique_ptr<WasmVirtualRegisterInfo>> + m_register_map; +}; + +} // namespace wasm +} // namespace lldb_private + +#endif diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp index a6553ff..0666b75 100644 --- a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp @@ -9,6 +9,7 @@ #include "ThreadWasm.h" #include "ProcessWasm.h" +#include "RegisterContextWasm.h" #include "UnwindWasm.h" #include "lldb/Target/Target.h" @@ -32,3 +33,19 @@ llvm::Expected<std::vector<lldb::addr_t>> ThreadWasm::GetWasmCallStack() { } return llvm::createStringError("no process"); } + +lldb::RegisterContextSP +ThreadWasm::CreateRegisterContextForFrame(StackFrame *frame) { + uint32_t concrete_frame_idx = 0; + ProcessSP process_sp(GetProcess()); + ProcessWasm *wasm_process = static_cast<ProcessWasm *>(process_sp.get()); + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) + return std::make_shared<RegisterContextWasm>( + *this, concrete_frame_idx, wasm_process->GetRegisterInfo()); + + return GetUnwinder().CreateRegisterContextForFrame(frame); +} diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h index 1c90f58..c2f5762 100644 --- a/lldb/source/Plugins/Process/wasm/ThreadWasm.h +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h @@ -25,6 +25,9 @@ public: /// Retrieve the current call stack from the WebAssembly remote process. llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack(); + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override; + protected: Unwind &GetUnwinder() override; diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 81c6731..591fded 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -738,9 +738,29 @@ size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) { LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size()); - for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) + for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) { ResolveTypeUID(uid); + // Remove the CTF type because we don't need it anymore, except for record + // types which we may need to complete later. + auto ctf_type_it = m_ctf_types.find(uid); + if (ctf_type_it != m_ctf_types.end()) { + CTFType *ctf_type = ctf_type_it->second.get(); + if (!llvm::isa<CTFRecord>(ctf_type)) + m_ctf_types.erase(uid); + } + } + +#ifndef NDEBUG + // Verify that the only CTF types left at this point are record types. + for (auto &t : m_ctf_types) { + CTFType *ctf_type = t.second.get(); + assert(ctf_type && "invalid type in m_ctf_types"); + assert(llvm::isa<CTFRecord>(ctf_type) && "leaking non record type"); + } + +#endif + LLDB_LOG(log, "Created {0} CTF types", m_types.size()); return m_types.size(); @@ -994,6 +1014,8 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { CTFType *ctf_type = ctf_type_it->second.get(); assert(ctf_type && "m_ctf_types should only contain valid CTF types"); + assert(ctf_type->uid == type_uid && + "CTF type UID doesn't match UID in m_ctf_types"); Log *log = GetLog(LLDBLog::Symbols); @@ -1015,11 +1037,6 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { m_types[type_uid] = type_sp; - // Except for record types which we'll need to complete later, we don't need - // the CTF type anymore. - if (!isa<CTFRecord>(ctf_type)) - m_ctf_types.erase(type_uid); - return type_sp.get(); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index 4bfbb4d..9762ead 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/Function.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/Support/DJB.h" using namespace lldb; @@ -275,7 +276,7 @@ void AppleDWARFIndex::GetNamespaces( void AppleDWARFIndex::GetFunctions( const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) { + llvm::function_ref<IterationAction(DWARFDIE die)> callback) { if (!m_apple_names_up) return; @@ -288,15 +289,16 @@ void AppleDWARFIndex::GetFunctions( ReportInvalidDIERef(die_ref, name); continue; } - if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, callback)) + if (ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, callback) == + IterationAction::Stop) return; } } void AppleDWARFIndex::GetFunctions( const RegularExpression ®ex, - llvm::function_ref<bool(DWARFDIE die)> callback) { - return GetGlobalVariables(regex, callback); + llvm::function_ref<IterationAction(DWARFDIE die)> callback) { + return GetGlobalVariables(regex, IterationActionAdaptor(callback)); } void AppleDWARFIndex::Dump(Stream &s) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h index 73de75b..c0f0eb6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h @@ -61,12 +61,13 @@ public: llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetNamespaces(ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(const Module::LookupInfo &lookup_info, - SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(const RegularExpression ®ex, - llvm::function_ref<bool(DWARFDIE die)> callback) override; + void GetFunctions( + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref<IterationAction(DWARFDIE die)> callback) override; + void GetFunctions( + const RegularExpression ®ex, + llvm::function_ref<IterationAction(DWARFDIE die)> callback) override; void Dump(Stream &s) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ba65f50..781c1c6c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -24,6 +24,7 @@ #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/Expression.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" @@ -249,6 +250,47 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram, return cv_quals; } +static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) { + char const *name = die.GetMangledName(/*substitute_name_allowed*/ false); + if (!name) + return {}; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (!dwarf) + return {}; + + auto get_module_id = [&](SymbolFile *sym) { + if (!sym) + return LLDB_INVALID_UID; + + auto *obj = sym->GetMainObjectFile(); + if (!obj) + return LLDB_INVALID_UID; + + auto module_sp = obj->GetModule(); + if (!module_sp) + return LLDB_INVALID_UID; + + return module_sp->GetID(); + }; + + lldb::user_id_t module_id = get_module_id(dwarf->GetDebugMapSymfile()); + if (module_id == LLDB_INVALID_UID) + module_id = get_module_id(dwarf); + + if (module_id == LLDB_INVALID_UID) + return {}; + + const auto die_id = die.GetID(); + if (die_id == LLDB_INVALID_UID) + return {}; + + return FunctionCallLabel{/*module_id=*/module_id, + /*symbol_id=*/die_id, + /*.lookup_name=*/name} + .toString(); +} + TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, const DWARFDIE &die, Log *log) { @@ -1231,7 +1273,7 @@ std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod( clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), - attrs.mangled_name, clang_type, accessibility, attrs.is_virtual, + MakeLLDBFuncAsmLabel(die), clang_type, accessibility, attrs.is_virtual, is_static, attrs.is_inline, attrs.is_explicit, is_attr_used, attrs.is_artificial); @@ -1384,7 +1426,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, GetOwningClangModule(die), name, clang_type, attrs.storage, - attrs.is_inline); + attrs.is_inline, MakeLLDBFuncAsmLabel(die)); std::free(name_buf); if (has_template_params) { @@ -1394,7 +1436,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type, - attrs.storage, attrs.is_inline); + attrs.storage, attrs.is_inline, /*asm_label=*/{}); clang::FunctionTemplateDecl *func_template_decl = m_ast.CreateFunctionTemplateDecl( containing_decl_ctx, GetOwningClangModule(die), @@ -1406,20 +1448,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, lldbassert(function_decl); if (function_decl) { - // Attach an asm(<mangled_name>) label to the FunctionDecl. - // This ensures that clang::CodeGen emits function calls - // using symbols that are mangled according to the DW_AT_linkage_name. - // If we didn't do this, the external symbols wouldn't exactly - // match the mangled name LLDB knows about and the IRExecutionUnit - // would have to fall back to searching object files for - // approximately matching function names. The motivating - // example is generating calls to ABI-tagged template functions. - // This is done separately for member functions in - // AddMethodToCXXRecordType. - if (attrs.mangled_name) - function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( - m_ast.getASTContext(), attrs.mangled_name, /*literal=*/false)); - LinkDeclContextToDIE(function_decl, die); const clang::FunctionProtoType *function_prototype( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp index 30c890d..a806506 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" #include "lldb/Target/Language.h" +#include "lldb/lldb-private-enumerations.h" using namespace lldb_private; using namespace lldb; @@ -23,10 +24,10 @@ using namespace lldb_private::plugin::dwarf; DWARFIndex::~DWARFIndex() = default; -bool DWARFIndex::ProcessFunctionDIE( +IterationAction DWARFIndex::ProcessFunctionDIE( const Module::LookupInfo &lookup_info, DWARFDIE die, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) { + llvm::function_ref<IterationAction(DWARFDIE die)> callback) { llvm::StringRef name = lookup_info.GetLookupName().GetStringRef(); FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); @@ -43,7 +44,7 @@ bool DWARFIndex::ProcessFunctionDIE( if (!lookup_info.NameMatchesLookupInfo(name_to_match_against, lookup_info.GetLanguageType())) - return true; + return IterationAction::Continue; } // Exit early if we're searching exclusively for methods or selectors and @@ -51,12 +52,12 @@ bool DWARFIndex::ProcessFunctionDIE( uint32_t looking_for_nonmethods = name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector); if (!looking_for_nonmethods && parent_decl_ctx.IsValid()) - return true; + return IterationAction::Continue; // Otherwise, we need to also check that the context matches. If it does not // match, we do nothing. if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) - return true; + return IterationAction::Continue; // In case of a full match, we just insert everything we find. if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name) @@ -79,7 +80,7 @@ bool DWARFIndex::ProcessFunctionDIE( return callback(die); } - return true; + return IterationAction::Continue; } DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h index 15d8503..3578824 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -16,6 +16,7 @@ #include "lldb/Core/Module.h" #include "lldb/Target/Statistics.h" +#include "lldb/lldb-private-enumerations.h" namespace lldb_private::plugin { namespace dwarf { @@ -82,10 +83,10 @@ public: virtual void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) = 0; + llvm::function_ref<IterationAction(DWARFDIE die)> callback) = 0; virtual void GetFunctions(const RegularExpression ®ex, - llvm::function_ref<bool(DWARFDIE die)> callback) = 0; + llvm::function_ref<IterationAction(DWARFDIE die)> callback) = 0; virtual void Dump(Stream &s) = 0; @@ -101,9 +102,10 @@ protected: /// the function given by "die" matches search criteria given by /// "parent_decl_ctx" and "name_type_mask", it calls the callback with the /// given die. - bool ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DWARFDIE die, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback); + IterationAction ProcessFunctionDIE( + const Module::LookupInfo &lookup_info, DWARFDIE die, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref<IterationAction(DWARFDIE die)> callback); class DIERefCallbackImpl { public: @@ -140,6 +142,25 @@ protected: bool ProcessNamespaceDieMatchParents( const CompilerDeclContext &parent_decl_ctx, DWARFDIE die, llvm::function_ref<bool(DWARFDIE die)> callback); + + /// Helper to convert callbacks that return an \c IterationAction + /// to a callback that returns a \c bool, where \c true indicates + /// we should continue iterating. This will be used to incrementally + /// migrate the callbacks to return an \c IterationAction. + /// + /// FIXME: remove once all callbacks in the DWARFIndex APIs return + /// IterationAction. + struct IterationActionAdaptor { + IterationActionAdaptor( + llvm::function_ref<IterationAction(DWARFDIE die)> callback) + : m_callback_ref(callback) {} + + bool operator()(DWARFDIE die) { + return m_callback_ref(std::move(die)) == IterationAction::Continue; + } + + llvm::function_ref<IterationAction(DWARFDIE die)> m_callback_ref; + }; }; } // namespace dwarf } // namespace lldb_private::plugin diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index ff1a76b..3ae9fcc 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/Module.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/ADT/Sequence.h" #include <optional> @@ -607,7 +608,7 @@ void DebugNamesDWARFIndex::GetNamespacesWithParents( void DebugNamesDWARFIndex::GetFunctions( const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) { + llvm::function_ref<IterationAction(DWARFDIE die)> callback) { ConstString name = lookup_info.GetLookupName(); std::set<DWARFDebugInfoEntry *> seen; for (const DebugNames::Entry &entry : @@ -617,12 +618,12 @@ void DebugNamesDWARFIndex::GetFunctions( continue; if (DWARFDIE die = GetDIE(entry)) { - if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, - [&](DWARFDIE die) { - if (!seen.insert(die.GetDIE()).second) - return true; - return callback(die); - })) + if (ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, + [&](DWARFDIE die) { + if (!seen.insert(die.GetDIE()).second) + return IterationAction::Continue; + return callback(die); + }) == IterationAction::Stop) return; } } @@ -632,7 +633,7 @@ void DebugNamesDWARFIndex::GetFunctions( void DebugNamesDWARFIndex::GetFunctions( const RegularExpression ®ex, - llvm::function_ref<bool(DWARFDIE die)> callback) { + llvm::function_ref<IterationAction(DWARFDIE die)> callback) { for (const DebugNames::NameIndex &ni: *m_debug_names_up) { for (DebugNames::NameTableEntry nte: ni) { if (!regex.Execute(nte.getString())) @@ -645,7 +646,7 @@ void DebugNamesDWARFIndex::GetFunctions( if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) continue; - if (!ProcessEntry(*entry_or, callback)) + if (!ProcessEntry(*entry_or, IterationActionAdaptor(callback))) return; } MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h index ab6cde1..2105919 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -58,12 +58,13 @@ public: void GetNamespacesWithParents( ConstString name, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(const Module::LookupInfo &lookup_info, - SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(const RegularExpression ®ex, - llvm::function_ref<bool(DWARFDIE die)> callback) override; + void GetFunctions( + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref<IterationAction(DWARFDIE die)> callback) override; + void GetFunctions( + const RegularExpression ®ex, + llvm::function_ref<IterationAction(DWARFDIE die)> callback) override; void Dump(Stream &s) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index c858ce2..f96ac7e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -21,6 +21,7 @@ #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ThreadPool.h" #include <atomic> @@ -471,60 +472,62 @@ void ManualDWARFIndex::GetNamespaces( void ManualDWARFIndex::GetFunctions( const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) { + llvm::function_ref<IterationAction(DWARFDIE die)> callback) { Index(); ConstString name = lookup_info.GetLookupName(); FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); if (name_type_mask & eFunctionNameTypeFull) { if (!m_set.function_fullnames.Find( - name, DIERefCallback( - [&](DWARFDIE die) { - if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, - die)) - return true; - return callback(die); - }, - name.GetStringRef()))) + name, DIERefCallback(IterationActionAdaptor([&](DWARFDIE die) { + if (!SymbolFileDWARF::DIEInDeclContext( + parent_decl_ctx, die)) + return IterationAction::Continue; + return callback(die); + }), + name.GetStringRef()))) return; } if (name_type_mask & eFunctionNameTypeBase) { if (!m_set.function_basenames.Find( - name, DIERefCallback( - [&](DWARFDIE die) { - if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, - die)) - return true; - return callback(die); - }, - name.GetStringRef()))) + name, DIERefCallback(IterationActionAdaptor([&](DWARFDIE die) { + if (!SymbolFileDWARF::DIEInDeclContext( + parent_decl_ctx, die)) + return IterationAction::Continue; + return callback(die); + }), + name.GetStringRef()))) return; } if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.IsValid()) { if (!m_set.function_methods.Find( - name, DIERefCallback(callback, name.GetStringRef()))) + name, DIERefCallback(IterationActionAdaptor(callback), + name.GetStringRef()))) return; } if (name_type_mask & eFunctionNameTypeSelector && !parent_decl_ctx.IsValid()) { if (!m_set.function_selectors.Find( - name, DIERefCallback(callback, name.GetStringRef()))) + name, DIERefCallback(IterationActionAdaptor(callback), + name.GetStringRef()))) return; } } void ManualDWARFIndex::GetFunctions( const RegularExpression ®ex, - llvm::function_ref<bool(DWARFDIE die)> callback) { + llvm::function_ref<IterationAction(DWARFDIE die)> callback) { Index(); - if (!m_set.function_basenames.Find(regex, - DIERefCallback(callback, regex.GetText()))) + if (!m_set.function_basenames.Find( + regex, + DIERefCallback(IterationActionAdaptor(callback), regex.GetText()))) return; - if (!m_set.function_fullnames.Find(regex, - DIERefCallback(callback, regex.GetText()))) + if (!m_set.function_fullnames.Find( + regex, + DIERefCallback(IterationActionAdaptor(callback), regex.GetText()))) return; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h index 04627b0..5685ba4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -50,12 +50,13 @@ public: llvm::function_ref<bool(DWARFDIE die)> callback) override; void GetNamespaces(ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(const Module::LookupInfo &lookup_info, - SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref<bool(DWARFDIE die)> callback) override; - void GetFunctions(const RegularExpression ®ex, - llvm::function_ref<bool(DWARFDIE die)> callback) override; + void GetFunctions( + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref<IterationAction(DWARFDIE die)> callback) override; + void GetFunctions( + const RegularExpression ®ex, + llvm::function_ref<IterationAction(DWARFDIE die)> callback) override; void Dump(Stream &s) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 41ab8d1..a3ba061 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -74,6 +74,7 @@ #include "ManualDWARFIndex.h" #include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" @@ -2475,6 +2476,55 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, return false; } +llvm::Expected<SymbolContext> +SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + + DWARFDIE die = GetDIE(label.symbol_id); + if (!die.IsValid()) + return llvm::createStringError( + llvm::formatv("invalid DIE ID in {0}", label)); + + // Label was created using a declaration DIE. Need to fetch the definition + // to resolve the function call. + if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) { + Module::LookupInfo info(ConstString(label.lookup_name), + lldb::eFunctionNameTypeFull, + lldb::eLanguageTypeUnknown); + + m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) { + if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) + return IterationAction::Continue; + + // We don't check whether the specification DIE for this function + // corresponds to the declaration DIE because the declaration might be in + // a type-unit but the definition in the compile-unit (and it's + // specifcation would point to the declaration in the compile-unit). We + // rely on the mangled name within the module to be enough to find us the + // unique definition. + die = entry; + return IterationAction::Stop; + }); + + if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) + return llvm::createStringError( + llvm::formatv("failed to find definition DIE for {0}", label)); + } + + SymbolContextList sc_list; + if (!ResolveFunction(die, /*include_inlines=*/false, sc_list)) + return llvm::createStringError( + llvm::formatv("failed to resolve function for {0}", label)); + + if (sc_list.IsEmpty()) + return llvm::createStringError( + llvm::formatv("failed to find function for {0}", label)); + + assert(sc_list.GetSize() == 1); + + return sc_list[0]; +} + bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx, const DWARFDIE &die, bool only_root_namespaces) { @@ -2539,7 +2589,7 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info, m_index->GetFunctions(lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); - return true; + return IterationAction::Continue; }); // With -gsimple-template-names, a templated type's DW_AT_name will not // contain the template parameters. Try again stripping '<' and anything @@ -2556,7 +2606,7 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info, [&](DWARFDIE die) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); - return true; + return IterationAction::Continue; }); } } @@ -2592,7 +2642,7 @@ void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, m_index->GetFunctions(regex, [&](DWARFDIE die) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); - return true; + return IterationAction::Continue; }); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 56d8ccb..3ec538d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -436,6 +436,9 @@ protected: DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die, DIEArray &&variable_dies); + llvm::Expected<SymbolContext> + ResolveFunctionCallLabel(const FunctionCallLabel &label) override; + // Given a die_offset, figure out the symbol context representing that die. bool ResolveFunction(const DWARFDIE &die, bool include_inlines, SymbolContextList &sc_list); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index dd94f0b..9d7452a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1602,3 +1602,14 @@ void SymbolFileDWARFDebugMap::GetCompileOptions( return IterationAction::Continue; }); } + +llvm::Expected<SymbolContext> SymbolFileDWARFDebugMap::ResolveFunctionCallLabel( + const FunctionCallLabel &label) { + const uint64_t oso_idx = GetOSOIndexFromUserID(label.symbol_id); + SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); + if (!oso_dwarf) + return llvm::createStringError(llvm::formatv( + "couldn't find symbol file for {0} in debug-map.", label)); + + return oso_dwarf->ResolveFunctionCallLabel(label); +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index f074b17..e1f1df23 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -144,6 +144,9 @@ public: void GetCompileOptions(std::unordered_map<lldb::CompUnitSP, Args> &args) override; + llvm::Expected<SymbolContext> + ResolveFunctionCallLabel(const FunctionCallLabel &label) override; + protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 702ec5e..8137622 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -88,7 +88,7 @@ struct CreateMethodDecl : public TypeVisitorCallbacks { MethodOptions::CompilerGenerated; function_decl = m_clang.AddMethodToCXXRecordType( parent_ty, proc_name, - /*mangled_name=*/nullptr, func_ct, /*access=*/access_type, + /*asm_label=*/{}, func_ct, /*access=*/access_type, /*is_virtual=*/is_virtual, /*is_static=*/is_static, /*is_inline=*/false, /*is_explicit=*/false, /*is_attr_used=*/false, /*is_artificial=*/is_artificial); @@ -903,7 +903,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, if (!function_decl) { function_decl = m_clang.AddMethodToCXXRecordType( parent_opaque_ty, func_name, - /*mangled_name=*/nullptr, func_ct, + /*asm_label=*/{}, func_ct, /*access=*/lldb::AccessType::eAccessPublic, /*is_virtual=*/false, /*is_static=*/false, /*is_inline=*/false, /*is_explicit=*/false, @@ -913,7 +913,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, } else { function_decl = m_clang.CreateFunctionDeclaration( parent, OptionalClangModuleID(), func_name, func_ct, func_storage, - is_inline); + is_inline, /*asm_label=*/{}); CreateFunctionParameters(func_id, *function_decl, param_count); } return function_decl; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 807ee5b..1c575e9 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -111,9 +111,8 @@ void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, bool is_artificial = (options & MethodOptions::CompilerGenerated) == MethodOptions::CompilerGenerated; m_ast_builder.clang().AddMethodToCXXRecordType( - derived_opaque_ty, name.data(), nullptr, method_ct, - access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false, - is_artificial); + derived_opaque_ty, name.data(), /*asm_label=*/{}, method_ct, access_type, + attrs.isVirtual(), attrs.isStatic(), false, false, false, is_artificial); m_cxx_record_map[derived_opaque_ty].insert({name, method_ct}); } diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 0090d8f..8b8eac6e 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -954,7 +954,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { auto decl = m_ast.CreateFunctionDeclaration( decl_context, OptionalClangModuleID(), name, - type->GetForwardCompilerType(), storage, func->hasInlineAttribute()); + type->GetForwardCompilerType(), storage, func->hasInlineAttribute(), + /*asm_label=*/{}); std::vector<clang::ParmVarDecl *> params; if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) { @@ -1446,7 +1447,7 @@ PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, // TODO: get mangled name for the method. return m_ast.AddMethodToCXXRecordType( record_type.GetOpaqueQualType(), name.c_str(), - /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(), + /*asm_label=*/{}, method_comp_type, access, method.isVirtual(), method.isStatic(), method.hasInlineAttribute(), /*is_explicit*/ false, // FIXME: Need this field in CodeView. /*is_attr_used*/ false, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 256952dc..9301f92 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -60,6 +60,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Expression/Expression.h" #include "lldb/Host/StreamFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" @@ -665,10 +666,9 @@ void TypeSystemClang::CreateASTContext() { m_file_manager_up = std::make_unique<clang::FileManager>( file_system_options, FileSystem::Instance().GetVirtualFileSystem()); - llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs()); m_diagnostic_options_up = std::make_unique<DiagnosticOptions>(); - m_diagnostics_engine_up = - std::make_unique<DiagnosticsEngine>(diag_id_sp, *m_diagnostic_options_up); + m_diagnostics_engine_up = std::make_unique<DiagnosticsEngine>( + DiagnosticIDs::create(), *m_diagnostic_options_up); m_source_manager_up = std::make_unique<clang::SourceManager>( *m_diagnostics_engine_up, *m_file_manager_up); @@ -796,6 +796,8 @@ TypeSystemClang::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding, return GetType(ast.LongDoubleTy); if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy)) return GetType(ast.HalfTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty)) + return GetType(ast.Float128Ty); break; case eEncodingVector: @@ -957,6 +959,13 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize( if (type_name == "long double" && QualTypeMatchesBitSize(bit_size, ast, ast.LongDoubleTy)) return GetType(ast.LongDoubleTy); + // As Rust currently uses `TypeSystemClang`, match `f128` here as well so it + // doesn't get misinterpreted as `long double` on targets where they are + // the same size but different formats. + if ((type_name == "__float128" || type_name == "_Float128" || + type_name == "f128") && + QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty)) + return GetType(ast.Float128Ty); // Fall back to not requiring a name match if (QualTypeMatchesBitSize(bit_size, ast, ast.FloatTy)) return GetType(ast.FloatTy); @@ -966,6 +975,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize( return GetType(ast.LongDoubleTy); if (QualTypeMatchesBitSize(bit_size, ast, ast.HalfTy)) return GetType(ast.HalfTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast.Float128Ty)) + return GetType(ast.Float128Ty); break; case DW_ATE_signed: @@ -2055,6 +2066,8 @@ TypeSystemClang::GetOpaqueCompilerType(clang::ASTContext *ast, return ast->DoubleTy.getAsOpaquePtr(); case eBasicTypeLongDouble: return ast->LongDoubleTy.getAsOpaquePtr(); + case eBasicTypeFloat128: + return ast->Float128Ty.getAsOpaquePtr(); case eBasicTypeFloatComplex: return ast->getComplexType(ast->FloatTy).getAsOpaquePtr(); case eBasicTypeDoubleComplex: @@ -2137,7 +2150,7 @@ std::string TypeSystemClang::GetTypeNameForDecl(const NamedDecl *named_decl, FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, llvm::StringRef name, const CompilerType &function_clang_type, - clang::StorageClass storage, bool is_inline) { + clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label) { FunctionDecl *func_decl = nullptr; ASTContext &ast = getASTContext(); if (!decl_ctx) @@ -2158,6 +2171,21 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( func_decl->setConstexprKind(isConstexprSpecified ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified); + + // Attach an asm(<mangled_name>) label to the FunctionDecl. + // This ensures that clang::CodeGen emits function calls + // using symbols that are mangled according to the DW_AT_linkage_name. + // If we didn't do this, the external symbols wouldn't exactly + // match the mangled name LLDB knows about and the IRExecutionUnit + // would have to fall back to searching object files for + // approximately matching function names. The motivating + // example is generating calls to ABI-tagged template functions. + // This is done separately for member functions in + // AddMethodToCXXRecordType. + if (!asm_label.empty()) + func_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(ast, asm_label, + /*literal=*/true)); + SetOwningModule(func_decl, owning_module); decl_ctx->addDecl(func_decl); @@ -4728,19 +4756,24 @@ CompilerType TypeSystemClang::CreateGenericFunctionPrototype() { // Exploring the type const llvm::fltSemantics & -TypeSystemClang::GetFloatTypeSemantics(size_t byte_size) { +TypeSystemClang::GetFloatTypeSemantics(size_t byte_size, lldb::Format format) { clang::ASTContext &ast = getASTContext(); const size_t bit_size = byte_size * 8; if (bit_size == ast.getTypeSize(ast.FloatTy)) return ast.getFloatTypeSemantics(ast.FloatTy); else if (bit_size == ast.getTypeSize(ast.DoubleTy)) return ast.getFloatTypeSemantics(ast.DoubleTy); + else if (format == eFormatFloat128 && + bit_size == ast.getTypeSize(ast.Float128Ty)) + return ast.getFloatTypeSemantics(ast.Float128Ty); else if (bit_size == ast.getTypeSize(ast.LongDoubleTy) || bit_size == llvm::APFloat::semanticsSizeInBits( ast.getFloatTypeSemantics(ast.LongDoubleTy))) return ast.getFloatTypeSemantics(ast.LongDoubleTy); else if (bit_size == ast.getTypeSize(ast.HalfTy)) return ast.getFloatTypeSemantics(ast.HalfTy); + else if (bit_size == ast.getTypeSize(ast.Float128Ty)) + return ast.getFloatTypeSemantics(ast.Float128Ty); return llvm::APFloatBase::Bogus(); } @@ -5218,6 +5251,8 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) { case clang::BuiltinType::Double: case clang::BuiltinType::LongDouble: return lldb::eFormatFloat; + case clang::BuiltinType::Float128: + return lldb::eFormatFloat128; default: return lldb::eFormatHex; } @@ -5515,6 +5550,8 @@ TypeSystemClang::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { return eBasicTypeDouble; case clang::BuiltinType::LongDouble: return eBasicTypeLongDouble; + case clang::BuiltinType::Float128: + return eBasicTypeFloat128; case clang::BuiltinType::NullPtr: return eBasicTypeNullPtr; @@ -6076,6 +6113,7 @@ uint32_t TypeSystemClang::GetNumPointeeChildren(clang::QualType type) { case clang::BuiltinType::Float: case clang::BuiltinType::Double: case clang::BuiltinType::LongDouble: + case clang::BuiltinType::Float128: case clang::BuiltinType::Dependent: case clang::BuiltinType::Overload: case clang::BuiltinType::ObjCId: @@ -7651,7 +7689,7 @@ TypeSystemClang::CreateParameterDeclarations( clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( lldb::opaque_compiler_type_t type, llvm::StringRef name, - const char *mangled_name, const CompilerType &method_clang_type, + llvm::StringRef asm_label, const CompilerType &method_clang_type, lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline, bool is_explicit, bool is_attr_used, bool is_artificial) { if (!type || !method_clang_type.IsValid() || name.empty()) @@ -7784,10 +7822,9 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( if (is_attr_used) cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext())); - if (mangled_name != nullptr) { + if (!asm_label.empty()) cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( - getASTContext(), mangled_name, /*literal=*/false)); - } + getASTContext(), asm_label, /*literal=*/true)); // Parameters on member function declarations in DWARF generally don't // have names, so we omit them when creating the ParmVarDecls. @@ -8720,6 +8757,7 @@ bool TypeSystemClang::DumpTypeValue( case eFormatHex: case eFormatHexUppercase: case eFormatFloat: + case eFormatFloat128: case eFormatOctal: case eFormatOSType: case eFormatUnsigned: @@ -9030,6 +9068,21 @@ ConstString TypeSystemClang::DeclGetName(void *opaque_decl) { return ConstString(); } +static ConstString +ExtractMangledNameFromFunctionCallLabel(llvm::StringRef label) { + auto label_or_err = FunctionCallLabel::fromString(label); + if (!label_or_err) { + llvm::consumeError(label_or_err.takeError()); + return {}; + } + + llvm::StringRef mangled = label_or_err->lookup_name; + if (Mangled::IsMangledName(mangled)) + return ConstString(mangled); + + return {}; +} + ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) { clang::NamedDecl *nd = llvm::dyn_cast_or_null<clang::NamedDecl>( static_cast<clang::Decl *>(opaque_decl)); @@ -9041,6 +9094,13 @@ ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) { if (!mc || !mc->shouldMangleCXXName(nd)) return {}; + // We have an LLDB FunctionCallLabel instead of an ordinary mangled name. + // Extract the mangled name out of this label. + if (const auto *label = nd->getAttr<AsmLabelAttr>()) + if (ConstString mangled = + ExtractMangledNameFromFunctionCallLabel(label->getLabel())) + return mangled; + llvm::SmallVector<char, 1024> buf; llvm::raw_svector_ostream llvm_ostrm(buf); if (llvm::isa<clang::CXXConstructorDecl>(nd)) { diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 63dee9d..5431d12 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -477,7 +477,7 @@ public: clang::FunctionDecl *CreateFunctionDeclaration( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, llvm::StringRef name, const CompilerType &function_Type, - clang::StorageClass storage, bool is_inline); + clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label); CompilerType CreateFunctionType(const CompilerType &result_type, @@ -823,7 +823,8 @@ public: // Exploring the type - const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) override; + const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size, + lldb::Format format) override; llvm::Expected<uint64_t> GetByteSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) { @@ -1001,7 +1002,7 @@ public: clang::CXXMethodDecl *AddMethodToCXXRecordType( lldb::opaque_compiler_type_t type, llvm::StringRef name, - const char *mangled_name, const CompilerType &method_type, + llvm::StringRef asm_label, const CompilerType &method_type, lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline, bool is_explicit, bool is_attr_used, bool is_artificial); |