1 //===-- PDBLocationToDWARFExpression.cpp ----------------------------------===// 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(); 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(); 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(); 92 93 uint32_t section_id = symbol.getAddressSection(); 94 95 auto section = section_list->FindSectionByID(section_id); 96 if (!section) 97 return DWARFExpression(); 98 99 uint32_t offset = symbol.getAddressOffset(); 100 stream.PutMaxHex64(section->GetFileAddress() + offset, address_size, 101 byte_order); 102 103 is_constant = false; 104 105 break; 106 } 107 case PDB_LocType::RegRel: { 108 uint32_t reg_num; 109 auto reg_id = symbol.getRegisterId(); 110 if (reg_id == llvm::codeview::RegisterId::VFRAME) { 111 if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) { 112 if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type, 113 stream)) { 114 int32_t offset = symbol.getOffset(); 115 stream.PutHex8(DW_OP_consts); 116 stream.PutSLEB128(offset); 117 stream.PutHex8(DW_OP_plus); 118 119 register_kind = eRegisterKindLLDB; 120 121 is_constant = false; 122 break; 123 } 124 } 125 126 register_kind = eRegisterKindGeneric; 127 reg_num = LLDB_REGNUM_GENERIC_FP; 128 } else { 129 register_kind = eRegisterKindLLDB; 130 reg_num = GetLLDBRegisterNumber(arch_type, reg_id); 131 if (reg_num == LLDB_INVALID_REGNUM) 132 return DWARFExpression(); 133 } 134 135 if (reg_num > 31) { 136 stream.PutHex8(DW_OP_bregx); 137 stream.PutULEB128(reg_num); 138 } else 139 stream.PutHex8(DW_OP_breg0 + reg_num); 140 141 int32_t offset = symbol.getOffset(); 142 stream.PutSLEB128(offset); 143 144 is_constant = false; 145 146 break; 147 } 148 case PDB_LocType::Enregistered: { 149 register_kind = eRegisterKindLLDB; 150 uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId()); 151 if (reg_num == LLDB_INVALID_REGNUM) 152 return DWARFExpression(); 153 154 if (reg_num > 31) { 155 stream.PutHex8(DW_OP_regx); 156 stream.PutULEB128(reg_num); 157 } else 158 stream.PutHex8(DW_OP_reg0 + reg_num); 159 160 is_constant = false; 161 162 break; 163 } 164 case PDB_LocType::Constant: { 165 Variant value = symbol.getValue(); 166 stream.PutRawBytes(&value.Value, sizeof(value.Value), 167 endian::InlHostByteOrder()); 168 break; 169 } 170 default: 171 return DWARFExpression(); 172 } 173 174 DataBufferSP buffer = 175 std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); 176 DataExtractor extractor(buffer, byte_order, address_size, byte_size); 177 DWARFExpression result(module, extractor, nullptr); 178 result.SetRegisterKind(register_kind); 179 180 return result; 181 } 182