1 //===-- DWARFLocationExpression.cpp -----------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "DWARFLocationExpression.h" 11 12 #include "lldb/Core/Module.h" 13 #include "lldb/Core/Section.h" 14 #include "lldb/Core/StreamBuffer.h" 15 #include "lldb/Expression/DWARFExpression.h" 16 #include "lldb/Utility/ArchSpec.h" 17 #include "lldb/Utility/DataBufferHeap.h" 18 #include "llvm/BinaryFormat/Dwarf.h" 19 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 20 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 21 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 22 #include "llvm/Support/Endian.h" 23 24 #include "PdbUtil.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 using namespace lldb_private::npdb; 29 using namespace llvm::codeview; 30 using namespace llvm::pdb; 31 32 static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) { 33 switch (kind) { 34 case SimpleTypeKind::Int128: 35 case SimpleTypeKind::Int64: 36 case SimpleTypeKind::Int64Quad: 37 case SimpleTypeKind::Int32: 38 case SimpleTypeKind::Int32Long: 39 case SimpleTypeKind::Int16: 40 case SimpleTypeKind::Int16Short: 41 case SimpleTypeKind::Float128: 42 case SimpleTypeKind::Float80: 43 case SimpleTypeKind::Float64: 44 case SimpleTypeKind::Float32: 45 case SimpleTypeKind::Float16: 46 case SimpleTypeKind::NarrowCharacter: 47 case SimpleTypeKind::SignedCharacter: 48 case SimpleTypeKind::SByte: 49 return true; 50 default: 51 return false; 52 } 53 } 54 55 static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti, 56 TpiStream &tpi) { 57 if (ti.isSimple()) { 58 SimpleTypeKind stk = ti.getSimpleKind(); 59 return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)}; 60 } 61 62 CVType cvt = tpi.getType(ti); 63 switch (cvt.kind()) { 64 case LF_MODIFIER: { 65 ModifierRecord mfr; 66 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr)); 67 return GetIntegralTypeInfo(mfr.ModifiedType, tpi); 68 } 69 case LF_POINTER: { 70 PointerRecord pr; 71 llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr)); 72 return GetIntegralTypeInfo(pr.ReferentType, tpi); 73 } 74 case LF_ENUM: { 75 EnumRecord er; 76 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 77 return GetIntegralTypeInfo(er.UnderlyingType, tpi); 78 } 79 default: 80 assert(false && "Type is not integral!"); 81 return {0, false}; 82 } 83 } 84 85 template <typename StreamWriter> 86 static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, 87 StreamWriter &&writer) { 88 const ArchSpec &architecture = module->GetArchitecture(); 89 ByteOrder byte_order = architecture.GetByteOrder(); 90 uint32_t address_size = architecture.GetAddressByteSize(); 91 uint32_t byte_size = architecture.GetDataByteSize(); 92 if (byte_order == eByteOrderInvalid || address_size == 0) 93 return DWARFExpression(nullptr); 94 95 RegisterKind register_kind = eRegisterKindDWARF; 96 StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); 97 98 if (!writer(stream, register_kind)) 99 return DWARFExpression(nullptr); 100 101 DataBufferSP buffer = 102 std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); 103 DataExtractor extractor(buffer, byte_order, address_size, byte_size); 104 DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize()); 105 result.SetRegisterKind(register_kind); 106 107 return result; 108 } 109 110 DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression( 111 uint16_t section, uint32_t offset, ModuleSP module) { 112 assert(section > 0); 113 assert(module); 114 115 return MakeLocationExpressionInternal( 116 module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { 117 stream.PutHex8(llvm::dwarf::DW_OP_addr); 118 119 SectionList *section_list = module->GetSectionList(); 120 assert(section_list); 121 122 // Section indices in PDB are 1-based, but in DWARF they are 0-based, so 123 // we need to subtract 1. 124 uint32_t section_idx = section - 1; 125 if (section_idx >= section_list->GetSize()) 126 return false; 127 128 auto section_ptr = section_list->GetSectionAtIndex(section_idx); 129 if (!section_ptr) 130 return false; 131 132 stream.PutMaxHex64(section_ptr->GetFileAddress() + offset, 133 stream.GetAddressByteSize(), stream.GetByteOrder()); 134 135 return true; 136 }); 137 } 138 139 DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( 140 TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant, 141 ModuleSP module) { 142 const ArchSpec &architecture = module->GetArchitecture(); 143 uint32_t address_size = architecture.GetAddressByteSize(); 144 145 size_t size = 0; 146 bool is_signed = false; 147 std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi); 148 149 union { 150 llvm::support::little64_t I; 151 llvm::support::ulittle64_t U; 152 } Value; 153 154 std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>(); 155 buffer->SetByteSize(size); 156 157 llvm::ArrayRef<uint8_t> bytes; 158 if (is_signed) { 159 Value.I = constant.getSExtValue(); 160 } else { 161 Value.U = constant.getZExtValue(); 162 } 163 164 bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8) 165 .take_front(size); 166 buffer->CopyData(bytes.data(), size); 167 DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size); 168 DWARFExpression result(nullptr, extractor, nullptr, 0, size); 169 return result; 170 } 171