//===-- PdbFPOProgramToDWARFExpression.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 "PdbFPOProgramToDWARFExpression.h" #include "CodeViewRegisterMapping.h" #include "lldb/Core/StreamBuffer.h" #include "lldb/Symbol/PostfixExpression.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::postfix; static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::ArchType arch_type) { // lookup register name to get lldb register number llvm::codeview::CPUType cpu_type; switch (arch_type) { case llvm::Triple::ArchType::aarch64: cpu_type = llvm::codeview::CPUType::ARM64; break; default: cpu_type = llvm::codeview::CPUType::X64; break; } llvm::ArrayRef> register_names = llvm::codeview::getRegisterNames(cpu_type); auto it = llvm::find_if( register_names, [®_name](const llvm::EnumEntry ®ister_entry) { return reg_name.compare_lower(register_entry.Name) == 0; }); if (it == register_names.end()) return LLDB_INVALID_REGNUM; auto reg_id = static_cast(it->Value); return npdb::GetLLDBRegisterNumber(arch_type, reg_id); } static Node *ResolveFPOProgram(llvm::StringRef program, llvm::StringRef register_name, llvm::Triple::ArchType arch_type, llvm::BumpPtrAllocator &alloc) { std::vector> 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(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); if (reg_num == LLDB_INVALID_REGNUM) return nullptr; return MakeNode(alloc, reg_num); }); if (!success) return nullptr; if (it->first == register_name) { // found target assignment program - no need to parse further return it->second; } } return nullptr; } bool lldb_private::npdb::TranslateFPOProgramToDWARFExpression( llvm::StringRef program, llvm::StringRef register_name, llvm::Triple::ArchType arch_type, Stream &stream) { llvm::BumpPtrAllocator node_alloc; Node *target_program = ResolveFPOProgram(program, register_name, arch_type, node_alloc); if (target_program == nullptr) { return false; } ToDWARF(*target_program, stream); return true; }