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