1 //===-- PDBLocationToDWARFExpression.cpp ------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PDBLocationToDWARFExpression.h" 10 11 #include "lldb/Core/Section.h" 12 #include "lldb/Core/StreamBuffer.h" 13 #include "lldb/Core/dwarf.h" 14 #include "lldb/Expression/DWARFExpression.h" 15 #include "lldb/Symbol/Variable.h" 16 #include "lldb/Utility/DataBufferHeap.h" 17 18 #include "llvm/DebugInfo/CodeView/CodeView.h" 19 #include "llvm/DebugInfo/PDB/IPDBSession.h" 20 #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 21 22 #include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h" 23 #include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 using namespace lldb_private::npdb; 28 using namespace llvm::pdb; 29 30 static std::unique_ptr<IPDBFrameData> 31 GetCorrespondingFrameData(const IPDBSession &session, 32 const Variable::RangeList &ranges) { 33 auto enumFrameData = session.getFrameData(); 34 if (!enumFrameData) 35 return nullptr; 36 37 std::unique_ptr<IPDBFrameData> found; 38 while (auto fd = enumFrameData->getNext()) { 39 Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(), 40 fd->getLengthBlock()); 41 42 for (size_t i = 0; i < ranges.GetSize(); i++) { 43 auto range = ranges.GetEntryAtIndex(i); 44 if (!range) 45 continue; 46 47 if (!range->DoesIntersect(fdRange)) 48 continue; 49 50 found = std::move(fd); 51 52 break; 53 } 54 } 55 56 return found; 57 } 58 59 static bool EmitVFrameEvaluationDWARFExpression( 60 llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) { 61 // VFrame value always stored in $TO pseudo-register 62 return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type, 63 stream); 64 } 65 66 DWARFExpression ConvertPDBLocationToDWARFExpression( 67 ModuleSP module, const PDBSymbolData &symbol, 68 const Variable::RangeList &ranges, bool &is_constant) { 69 is_constant = true; 70 71 if (!module) 72 return DWARFExpression(nullptr); 73 74 const ArchSpec &architecture = module->GetArchitecture(); 75 llvm::Triple::ArchType arch_type = architecture.GetMachine(); 76 ByteOrder byte_order = architecture.GetByteOrder(); 77 uint32_t address_size = architecture.GetAddressByteSize(); 78 uint32_t byte_size = architecture.GetDataByteSize(); 79 if (byte_order == eByteOrderInvalid || address_size == 0) 80 return DWARFExpression(nullptr); 81 82 RegisterKind register_kind = eRegisterKindDWARF; 83 StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); 84 switch (symbol.getLocationType()) { 85 case PDB_LocType::Static: 86 case PDB_LocType::TLS: { 87 stream.PutHex8(DW_OP_addr); 88 89 SectionList *section_list = module->GetSectionList(); 90 if (!section_list) 91 return DWARFExpression(nullptr); 92 93 uint32_t section_idx = symbol.getAddressSection() - 1; 94 if (section_idx >= section_list->GetSize()) 95 return DWARFExpression(nullptr); 96 97 auto section = section_list->GetSectionAtIndex(section_idx); 98 if (!section) 99 return DWARFExpression(nullptr); 100 101 uint32_t offset = symbol.getAddressOffset(); 102 stream.PutMaxHex64(section->GetFileAddress() + offset, address_size, 103 byte_order); 104 105 is_constant = false; 106 107 break; 108 } 109 case PDB_LocType::RegRel: { 110 uint32_t reg_num; 111 auto reg_id = symbol.getRegisterId(); 112 if (reg_id == llvm::codeview::RegisterId::VFRAME) { 113 if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) { 114 if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type, 115 stream)) { 116 int32_t offset = symbol.getOffset(); 117 stream.PutHex8(DW_OP_consts); 118 stream.PutSLEB128(offset); 119 stream.PutHex8(DW_OP_plus); 120 121 register_kind = eRegisterKindLLDB; 122 123 is_constant = false; 124 break; 125 } 126 } 127 128 register_kind = eRegisterKindGeneric; 129 reg_num = LLDB_REGNUM_GENERIC_FP; 130 } else { 131 register_kind = eRegisterKindLLDB; 132 reg_num = GetLLDBRegisterNumber(arch_type, reg_id); 133 if (reg_num == LLDB_INVALID_REGNUM) 134 return DWARFExpression(nullptr); 135 } 136 137 if (reg_num > 31) { 138 stream.PutHex8(DW_OP_bregx); 139 stream.PutULEB128(reg_num); 140 } else 141 stream.PutHex8(DW_OP_breg0 + reg_num); 142 143 int32_t offset = symbol.getOffset(); 144 stream.PutSLEB128(offset); 145 146 is_constant = false; 147 148 break; 149 } 150 case PDB_LocType::Enregistered: { 151 register_kind = eRegisterKindLLDB; 152 uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId()); 153 if (reg_num == LLDB_INVALID_REGNUM) 154 return DWARFExpression(nullptr); 155 156 if (reg_num > 31) { 157 stream.PutHex8(DW_OP_regx); 158 stream.PutULEB128(reg_num); 159 } else 160 stream.PutHex8(DW_OP_reg0 + reg_num); 161 162 is_constant = false; 163 164 break; 165 } 166 case PDB_LocType::Constant: { 167 Variant value = symbol.getValue(); 168 stream.PutRawBytes(&value.Value, sizeof(value.Value), 169 endian::InlHostByteOrder()); 170 break; 171 } 172 default: 173 return DWARFExpression(nullptr); 174 } 175 176 DataBufferSP buffer = 177 std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); 178 DataExtractor extractor(buffer, byte_order, address_size, byte_size); 179 DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize()); 180 result.SetRegisterKind(register_kind); 181 182 return result; 183 } 184