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