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