1 //===-- DWARFLocationExpression.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 "DWARFLocationExpression.h" 10 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/Section.h" 13 #include "lldb/Core/StreamBuffer.h" 14 #include "lldb/Expression/DWARFExpression.h" 15 #include "lldb/Utility/ArchSpec.h" 16 #include "lldb/Utility/DataBufferHeap.h" 17 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 #include "CodeViewRegisterMapping.h" 26 #include "PdbFPOProgramToDWARFExpression.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 using namespace lldb_private::npdb; 31 using namespace llvm::codeview; 32 using namespace llvm::pdb; 33 34 uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) { 35 if (register_id == llvm::codeview::RegisterId::VFRAME) 36 return LLDB_REGNUM_GENERIC_FP; 37 38 return LLDB_INVALID_REGNUM; 39 } 40 41 static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type, 42 llvm::codeview::RegisterId register_id, 43 RegisterKind ®ister_kind) { 44 register_kind = eRegisterKindLLDB; 45 uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id); 46 if (reg_num != LLDB_INVALID_REGNUM) 47 return reg_num; 48 49 register_kind = eRegisterKindGeneric; 50 return GetGenericRegisterNumber(register_id); 51 } 52 53 static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) { 54 switch (kind) { 55 case SimpleTypeKind::Int128: 56 case SimpleTypeKind::Int64: 57 case SimpleTypeKind::Int64Quad: 58 case SimpleTypeKind::Int32: 59 case SimpleTypeKind::Int32Long: 60 case SimpleTypeKind::Int16: 61 case SimpleTypeKind::Int16Short: 62 case SimpleTypeKind::Float128: 63 case SimpleTypeKind::Float80: 64 case SimpleTypeKind::Float64: 65 case SimpleTypeKind::Float32: 66 case SimpleTypeKind::Float16: 67 case SimpleTypeKind::NarrowCharacter: 68 case SimpleTypeKind::SignedCharacter: 69 case SimpleTypeKind::SByte: 70 return true; 71 default: 72 return false; 73 } 74 } 75 76 static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti, 77 TpiStream &tpi) { 78 if (ti.isSimple()) { 79 SimpleTypeKind stk = ti.getSimpleKind(); 80 return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)}; 81 } 82 83 CVType cvt = tpi.getType(ti); 84 switch (cvt.kind()) { 85 case LF_MODIFIER: { 86 ModifierRecord mfr; 87 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr)); 88 return GetIntegralTypeInfo(mfr.ModifiedType, tpi); 89 } 90 case LF_POINTER: { 91 PointerRecord pr; 92 llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr)); 93 return GetIntegralTypeInfo(pr.ReferentType, tpi); 94 } 95 case LF_ENUM: { 96 EnumRecord er; 97 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 98 return GetIntegralTypeInfo(er.UnderlyingType, tpi); 99 } 100 default: 101 assert(false && "Type is not integral!"); 102 return {0, false}; 103 } 104 } 105 106 template <typename StreamWriter> 107 static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module, 108 StreamWriter &&writer) { 109 const ArchSpec &architecture = module->GetArchitecture(); 110 ByteOrder byte_order = architecture.GetByteOrder(); 111 uint32_t address_size = architecture.GetAddressByteSize(); 112 uint32_t byte_size = architecture.GetDataByteSize(); 113 if (byte_order == eByteOrderInvalid || address_size == 0) 114 return DWARFExpression(); 115 116 RegisterKind register_kind = eRegisterKindDWARF; 117 StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); 118 119 if (!writer(stream, register_kind)) 120 return DWARFExpression(); 121 122 DataBufferSP buffer = 123 std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); 124 DataExtractor extractor(buffer, byte_order, address_size, byte_size); 125 DWARFExpression result(module, extractor, nullptr); 126 result.SetRegisterKind(register_kind); 127 128 return result; 129 } 130 131 static DWARFExpression MakeRegisterBasedLocationExpressionInternal( 132 llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset, 133 lldb::ModuleSP module) { 134 return MakeLocationExpressionInternal( 135 module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { 136 uint32_t reg_num = GetRegisterNumber( 137 module->GetArchitecture().GetMachine(), reg, register_kind); 138 if (reg_num == LLDB_INVALID_REGNUM) 139 return false; 140 141 if (reg_num > 31) { 142 llvm::dwarf::LocationAtom base = relative_offset 143 ? llvm::dwarf::DW_OP_bregx 144 : llvm::dwarf::DW_OP_regx; 145 stream.PutHex8(base); 146 stream.PutULEB128(reg_num); 147 } else { 148 llvm::dwarf::LocationAtom base = relative_offset 149 ? llvm::dwarf::DW_OP_breg0 150 : llvm::dwarf::DW_OP_reg0; 151 stream.PutHex8(base + reg_num); 152 } 153 154 if (relative_offset) 155 stream.PutSLEB128(*relative_offset); 156 157 return true; 158 }); 159 } 160 161 DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression( 162 llvm::codeview::RegisterId reg, lldb::ModuleSP module) { 163 return MakeRegisterBasedLocationExpressionInternal(reg, llvm::None, module); 164 } 165 166 DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression( 167 llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) { 168 return MakeRegisterBasedLocationExpressionInternal(reg, offset, module); 169 } 170 171 static bool EmitVFrameEvaluationDWARFExpression( 172 llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) { 173 // VFrame value always stored in $TO pseudo-register 174 return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type, 175 stream); 176 } 177 178 DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression( 179 llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) { 180 return MakeLocationExpressionInternal( 181 module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { 182 const ArchSpec &architecture = module->GetArchitecture(); 183 184 if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(), 185 stream)) 186 return false; 187 188 stream.PutHex8(llvm::dwarf::DW_OP_consts); 189 stream.PutSLEB128(offset); 190 stream.PutHex8(llvm::dwarf::DW_OP_plus); 191 192 register_kind = eRegisterKindLLDB; 193 194 return true; 195 }); 196 } 197 198 DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression( 199 uint16_t section, uint32_t offset, ModuleSP module) { 200 assert(section > 0); 201 assert(module); 202 203 return MakeLocationExpressionInternal( 204 module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { 205 stream.PutHex8(llvm::dwarf::DW_OP_addr); 206 207 SectionList *section_list = module->GetSectionList(); 208 assert(section_list); 209 210 auto section_ptr = section_list->FindSectionByID(section); 211 if (!section_ptr) 212 return false; 213 214 stream.PutMaxHex64(section_ptr->GetFileAddress() + offset, 215 stream.GetAddressByteSize(), stream.GetByteOrder()); 216 217 return true; 218 }); 219 } 220 221 DWARFExpression lldb_private::npdb::MakeConstantLocationExpression( 222 TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant, 223 ModuleSP module) { 224 const ArchSpec &architecture = module->GetArchitecture(); 225 uint32_t address_size = architecture.GetAddressByteSize(); 226 227 size_t size = 0; 228 bool is_signed = false; 229 std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi); 230 231 union { 232 llvm::support::little64_t I; 233 llvm::support::ulittle64_t U; 234 } Value; 235 236 std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>(); 237 buffer->SetByteSize(size); 238 239 llvm::ArrayRef<uint8_t> bytes; 240 if (is_signed) { 241 Value.I = constant.getSExtValue(); 242 } else { 243 Value.U = constant.getZExtValue(); 244 } 245 246 bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8) 247 .take_front(size); 248 buffer->CopyData(bytes.data(), size); 249 DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size); 250 DWARFExpression result(nullptr, extractor, nullptr); 251 return result; 252 } 253