blob: 1bad4c025fae7a83c29d2f9c14c4ee149c19ebc4 [file] [log] [blame]
Zachary Turnera93458b2018-12-06 17:49:15 +00001//===-- 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
26using namespace lldb;
27using namespace lldb_private;
28using namespace lldb_private::npdb;
29using namespace llvm::codeview;
30using namespace llvm::pdb;
31
32static 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
55static 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
85template <typename StreamWriter>
86static 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
110DWARFExpression 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 &register_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
139DWARFExpression 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}