180814287SRaphael Isemann //===-- PdbUtil.cpp -------------------------------------------------------===//
2307f5ae8SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6307f5ae8SZachary Turner //
7307f5ae8SZachary Turner //===----------------------------------------------------------------------===//
8307f5ae8SZachary Turner
9307f5ae8SZachary Turner #include "PdbUtil.h"
10594c85e9SZachary Turner
11594c85e9SZachary Turner #include "DWARFLocationExpression.h"
12594c85e9SZachary Turner #include "PdbIndex.h"
136284aee9SZachary Turner #include "PdbSymUid.h"
14307f5ae8SZachary Turner
155e9c9b32SZequan Wu #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
16307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
17b96181c2SZachary Turner #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18758657e5SAleksandr Urakov #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
196284aee9SZachary Turner #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
20307f5ae8SZachary Turner
2144f19514SZachary Turner #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
2271d778f3SZequan Wu #include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
23758657e5SAleksandr Urakov #include "lldb/Symbol/Block.h"
24307f5ae8SZachary Turner #include "lldb/Utility/LLDBAssert.h"
255e9c9b32SZequan Wu #include "lldb/Utility/LLDBLog.h"
26b96181c2SZachary Turner #include "lldb/lldb-enumerations.h"
27b96181c2SZachary Turner
28307f5ae8SZachary Turner using namespace lldb_private;
29307f5ae8SZachary Turner using namespace lldb_private::npdb;
30307f5ae8SZachary Turner using namespace llvm::codeview;
31307f5ae8SZachary Turner using namespace llvm::pdb;
32307f5ae8SZachary Turner
3371d778f3SZequan Wu // The returned range list is guaranteed to be sorted and no overlaps between
3471d778f3SZequan Wu // adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
35594c85e9SZachary Turner static Variable::RangeList
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)36594c85e9SZachary Turner MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
37594c85e9SZachary Turner llvm::ArrayRef<LocalVariableAddrGap> gaps) {
38594c85e9SZachary Turner lldb::addr_t start =
39594c85e9SZachary Turner index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
408a790e65SZequan Wu if (start == LLDB_INVALID_ADDRESS)
418a790e65SZequan Wu return {};
42594c85e9SZachary Turner lldb::addr_t end = start + range.Range;
43594c85e9SZachary Turner
44594c85e9SZachary Turner Variable::RangeList result;
45594c85e9SZachary Turner while (!gaps.empty()) {
46594c85e9SZachary Turner const LocalVariableAddrGap &gap = gaps.front();
47c45975cbSZequan Wu lldb::addr_t gap_start = start + gap.GapStartOffset;
48c45975cbSZequan Wu result.Append(start, gap_start - start);
49c45975cbSZequan Wu start = gap_start + gap.Range;
50594c85e9SZachary Turner gaps = gaps.drop_front();
51594c85e9SZachary Turner }
52594c85e9SZachary Turner
53758657e5SAleksandr Urakov result.Append(start, end - start);
54594c85e9SZachary Turner return result;
55594c85e9SZachary Turner }
56594c85e9SZachary Turner
575e9c9b32SZequan Wu namespace {
5871d778f3SZequan Wu struct MemberLocations {
5971d778f3SZequan Wu std::map<uint64_t, MemberValLocation> offset_to_location;
6071d778f3SZequan Wu DWARFExpression expr;
6171d778f3SZequan Wu bool is_dwarf = false;
6271d778f3SZequan Wu
6371d778f3SZequan Wu MemberLocations() = default;
MemberLocations__anonf2db53160111::MemberLocations6471d778f3SZequan Wu MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}
MemberLocations__anonf2db53160111::MemberLocations6571d778f3SZequan Wu MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {
6671d778f3SZequan Wu insert(offset, member_loc);
6771d778f3SZequan Wu }
6871d778f3SZequan Wu
insert__anonf2db53160111::MemberLocations6971d778f3SZequan Wu void insert(uint64_t offset, const MemberValLocation &member_loc) {
7071d778f3SZequan Wu offset_to_location[offset] = member_loc;
7171d778f3SZequan Wu }
7271d778f3SZequan Wu
7371d778f3SZequan Wu struct Comparator {
7471d778f3SZequan Wu public:
operator ()__anonf2db53160111::MemberLocations::Comparator7571d778f3SZequan Wu bool operator()(const MemberLocations &, const MemberLocations &) const {
7671d778f3SZequan Wu return false;
775e9c9b32SZequan Wu }
785e9c9b32SZequan Wu };
7971d778f3SZequan Wu };
8071d778f3SZequan Wu
8171d778f3SZequan Wu // A range map with address ranges to a map of pair of offset and locaitons.
8271d778f3SZequan Wu typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
8371d778f3SZequan Wu MemberLocations::Comparator>
8471d778f3SZequan Wu RangeMap;
8571d778f3SZequan Wu
AddMemberLocationRanges(RangeMap & location_map,uint64_t offset,MemberValLocation member_loc,const Variable::RangeList & ranges)8671d778f3SZequan Wu void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,
8771d778f3SZequan Wu MemberValLocation member_loc,
8871d778f3SZequan Wu const Variable::RangeList &ranges) {
8971d778f3SZequan Wu RangeMap new_location_map;
9071d778f3SZequan Wu auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,
9171d778f3SZequan Wu RangeMap::Entry *entry) {
9271d778f3SZequan Wu RangeMap::Entry overlap_region = {base, end - base, entry->data};
9371d778f3SZequan Wu overlap_region.data.insert(offset, member_loc);
9471d778f3SZequan Wu new_location_map.Append(overlap_region);
9571d778f3SZequan Wu };
9671d778f3SZequan Wu
9771d778f3SZequan Wu for (const auto &range : ranges) {
9871d778f3SZequan Wu lldb::addr_t base = range.GetRangeBase();
9971d778f3SZequan Wu lldb::addr_t end = range.GetRangeEnd();
10071d778f3SZequan Wu uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
10171d778f3SZequan Wu while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
10271d778f3SZequan Wu if (base >= end || entry->base >= end)
10371d778f3SZequan Wu break;
10471d778f3SZequan Wu if (entry->data.is_dwarf)
10571d778f3SZequan Wu base = entry->GetRangeEnd();
10671d778f3SZequan Wu else {
10771d778f3SZequan Wu lldb::addr_t entry_end = entry->GetRangeEnd();
10871d778f3SZequan Wu if (base > entry->base) {
10971d778f3SZequan Wu if (end < entry_end)
11071d778f3SZequan Wu new_location_map.Append({end, entry_end - end, entry->data});
11171d778f3SZequan Wu add_overlap_region(base, end < entry_end ? end : entry_end, entry);
11271d778f3SZequan Wu entry->SetRangeEnd(base);
11371d778f3SZequan Wu } else if (base < entry->base) {
11471d778f3SZequan Wu new_location_map.Append(
11571d778f3SZequan Wu {base, entry->base - base, {offset, member_loc}});
11671d778f3SZequan Wu if (entry_end == end)
11771d778f3SZequan Wu entry->data.insert(offset, member_loc);
11871d778f3SZequan Wu else {
11971d778f3SZequan Wu add_overlap_region(entry->base, end, entry);
12071d778f3SZequan Wu entry->ShrinkFront(end - entry->base);
12171d778f3SZequan Wu }
12271d778f3SZequan Wu } else {
12371d778f3SZequan Wu if (end < entry_end) {
12471d778f3SZequan Wu new_location_map.Append({end, entry_end, entry->data});
12571d778f3SZequan Wu entry->SetRangeEnd(end);
12671d778f3SZequan Wu }
12771d778f3SZequan Wu entry->data.insert(offset, member_loc);
12871d778f3SZequan Wu }
12971d778f3SZequan Wu base = entry_end;
13071d778f3SZequan Wu }
13171d778f3SZequan Wu ++base_idx;
13271d778f3SZequan Wu }
13371d778f3SZequan Wu if (base >= end)
13471d778f3SZequan Wu continue;
13571d778f3SZequan Wu new_location_map.Append({base, end - base, {offset, member_loc}});
13671d778f3SZequan Wu }
13771d778f3SZequan Wu for (const auto &entry : new_location_map)
13871d778f3SZequan Wu location_map.Append(entry);
13971d778f3SZequan Wu if (!new_location_map.IsEmpty())
14071d778f3SZequan Wu location_map.Sort();
14171d778f3SZequan Wu }
14271d778f3SZequan Wu
AddDwarfRange(RangeMap & location_map,const DWARFExpression & expr,const Variable::RangeList & ranges)14371d778f3SZequan Wu void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,
14471d778f3SZequan Wu const Variable::RangeList &ranges) {
14571d778f3SZequan Wu if (!expr.IsValid())
14671d778f3SZequan Wu return;
14771d778f3SZequan Wu RangeMap new_location_map;
14871d778f3SZequan Wu for (const auto &range : ranges) {
14971d778f3SZequan Wu lldb::addr_t base = range.GetRangeBase();
15071d778f3SZequan Wu lldb::addr_t end = range.GetRangeEnd();
15171d778f3SZequan Wu uint32_t base_idx = location_map.FindEntryIndexThatContains(base);
15271d778f3SZequan Wu uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);
15371d778f3SZequan Wu // range is within an entry.
15471d778f3SZequan Wu if (base_idx == end_idx && base_idx != UINT32_MAX) {
15571d778f3SZequan Wu auto *entry = location_map.GetMutableEntryAtIndex(base_idx);
15671d778f3SZequan Wu if (base > entry->base) {
15771d778f3SZequan Wu new_location_map.Append({entry->base, base - entry->base, entry->data});
15871d778f3SZequan Wu entry->ShrinkFront(base - entry->base);
15971d778f3SZequan Wu }
16071d778f3SZequan Wu if (end == entry->GetRangeEnd())
16171d778f3SZequan Wu entry->data = expr;
16271d778f3SZequan Wu else {
16371d778f3SZequan Wu entry->ShrinkFront(end - base);
16471d778f3SZequan Wu new_location_map.Append({base, end - base, expr});
16571d778f3SZequan Wu }
16671d778f3SZequan Wu continue;
16771d778f3SZequan Wu }
16871d778f3SZequan Wu base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
16971d778f3SZequan Wu if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
17071d778f3SZequan Wu if (entry->Contains(base) && entry->base != base) {
17171d778f3SZequan Wu entry->SetRangeEnd(base);
17271d778f3SZequan Wu ++base_idx;
17371d778f3SZequan Wu }
17471d778f3SZequan Wu }
17571d778f3SZequan Wu end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);
17671d778f3SZequan Wu if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {
17771d778f3SZequan Wu if (entry->Contains(end - 1)) {
17871d778f3SZequan Wu if (entry->GetRangeEnd() == end)
17971d778f3SZequan Wu ++end_idx;
18071d778f3SZequan Wu else
18171d778f3SZequan Wu entry->ShrinkFront(end - entry->base);
18271d778f3SZequan Wu }
18371d778f3SZequan Wu }
18471d778f3SZequan Wu
18571d778f3SZequan Wu if (end_idx == UINT32_MAX)
18671d778f3SZequan Wu end_idx = location_map.GetSize();
18771d778f3SZequan Wu // Erase existing ranges covered by new range.
18871d778f3SZequan Wu location_map.Erase(base_idx, end_idx);
18971d778f3SZequan Wu new_location_map.Append({base, end - base, expr});
19071d778f3SZequan Wu }
19171d778f3SZequan Wu
19271d778f3SZequan Wu for (const auto &entry : new_location_map)
19371d778f3SZequan Wu location_map.Append(entry);
19471d778f3SZequan Wu location_map.Sort();
19571d778f3SZequan Wu }
1965e9c9b32SZequan Wu } // namespace
1975e9c9b32SZequan Wu
create(CVType type)198056e4ab4SZachary Turner CVTagRecord CVTagRecord::create(CVType type) {
199056e4ab4SZachary Turner assert(IsTagRecord(type) && "type is not a tag record!");
200056e4ab4SZachary Turner switch (type.kind()) {
201056e4ab4SZachary Turner case LF_CLASS:
202056e4ab4SZachary Turner case LF_STRUCTURE:
203056e4ab4SZachary Turner case LF_INTERFACE: {
204056e4ab4SZachary Turner ClassRecord cr;
205056e4ab4SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
206056e4ab4SZachary Turner return CVTagRecord(std::move(cr));
207056e4ab4SZachary Turner }
208056e4ab4SZachary Turner case LF_UNION: {
209056e4ab4SZachary Turner UnionRecord ur;
210056e4ab4SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
211056e4ab4SZachary Turner return CVTagRecord(std::move(ur));
212056e4ab4SZachary Turner }
213056e4ab4SZachary Turner case LF_ENUM: {
214056e4ab4SZachary Turner EnumRecord er;
215056e4ab4SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
216056e4ab4SZachary Turner return CVTagRecord(std::move(er));
217056e4ab4SZachary Turner }
218056e4ab4SZachary Turner default:
219056e4ab4SZachary Turner llvm_unreachable("Unreachable!");
220056e4ab4SZachary Turner }
221056e4ab4SZachary Turner }
222056e4ab4SZachary Turner
CVTagRecord(ClassRecord && c)223056e4ab4SZachary Turner CVTagRecord::CVTagRecord(ClassRecord &&c)
224056e4ab4SZachary Turner : cvclass(std::move(c)),
225056e4ab4SZachary Turner m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)226056e4ab4SZachary Turner CVTagRecord::CVTagRecord(UnionRecord &&u)
227056e4ab4SZachary Turner : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)228056e4ab4SZachary Turner CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
229056e4ab4SZachary Turner
CVSymToPDBSym(SymbolKind kind)230b96181c2SZachary Turner PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
231307f5ae8SZachary Turner switch (kind) {
232307f5ae8SZachary Turner case S_COMPILE3:
233307f5ae8SZachary Turner case S_OBJNAME:
234307f5ae8SZachary Turner return PDB_SymType::CompilandDetails;
235307f5ae8SZachary Turner case S_ENVBLOCK:
236307f5ae8SZachary Turner return PDB_SymType::CompilandEnv;
237307f5ae8SZachary Turner case S_THUNK32:
238307f5ae8SZachary Turner case S_TRAMPOLINE:
239307f5ae8SZachary Turner return PDB_SymType::Thunk;
240307f5ae8SZachary Turner case S_COFFGROUP:
241307f5ae8SZachary Turner return PDB_SymType::CoffGroup;
242307f5ae8SZachary Turner case S_EXPORT:
243307f5ae8SZachary Turner return PDB_SymType::Export;
244307f5ae8SZachary Turner case S_LPROC32:
245307f5ae8SZachary Turner case S_GPROC32:
246307f5ae8SZachary Turner case S_LPROC32_DPC:
247307f5ae8SZachary Turner return PDB_SymType::Function;
248307f5ae8SZachary Turner case S_PUB32:
249307f5ae8SZachary Turner return PDB_SymType::PublicSymbol;
250307f5ae8SZachary Turner case S_INLINESITE:
251307f5ae8SZachary Turner return PDB_SymType::InlineSite;
252307f5ae8SZachary Turner case S_LOCAL:
253307f5ae8SZachary Turner case S_BPREL32:
254307f5ae8SZachary Turner case S_REGREL32:
255307f5ae8SZachary Turner case S_MANCONSTANT:
256307f5ae8SZachary Turner case S_CONSTANT:
257307f5ae8SZachary Turner case S_LDATA32:
258307f5ae8SZachary Turner case S_GDATA32:
259307f5ae8SZachary Turner case S_LMANDATA:
260307f5ae8SZachary Turner case S_GMANDATA:
261307f5ae8SZachary Turner case S_LTHREAD32:
262307f5ae8SZachary Turner case S_GTHREAD32:
263307f5ae8SZachary Turner return PDB_SymType::Data;
264307f5ae8SZachary Turner case S_BLOCK32:
265307f5ae8SZachary Turner return PDB_SymType::Block;
266307f5ae8SZachary Turner case S_LABEL32:
267307f5ae8SZachary Turner return PDB_SymType::Label;
268307f5ae8SZachary Turner case S_CALLSITEINFO:
269307f5ae8SZachary Turner return PDB_SymType::CallSite;
270307f5ae8SZachary Turner case S_HEAPALLOCSITE:
271307f5ae8SZachary Turner return PDB_SymType::HeapAllocationSite;
272307f5ae8SZachary Turner case S_CALLEES:
273307f5ae8SZachary Turner return PDB_SymType::Callee;
274307f5ae8SZachary Turner case S_CALLERS:
275307f5ae8SZachary Turner return PDB_SymType::Caller;
276307f5ae8SZachary Turner default:
277307f5ae8SZachary Turner lldbassert(false && "Invalid symbol record kind!");
278307f5ae8SZachary Turner }
279307f5ae8SZachary Turner return PDB_SymType::None;
280307f5ae8SZachary Turner }
281307f5ae8SZachary Turner
CVTypeToPDBType(TypeLeafKind kind)282b96181c2SZachary Turner PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
283b96181c2SZachary Turner switch (kind) {
284b96181c2SZachary Turner case LF_ARRAY:
285b96181c2SZachary Turner return PDB_SymType::ArrayType;
286b96181c2SZachary Turner case LF_ARGLIST:
287b96181c2SZachary Turner return PDB_SymType::FunctionSig;
288b96181c2SZachary Turner case LF_BCLASS:
289b96181c2SZachary Turner return PDB_SymType::BaseClass;
290b96181c2SZachary Turner case LF_BINTERFACE:
291b96181c2SZachary Turner return PDB_SymType::BaseInterface;
292b96181c2SZachary Turner case LF_CLASS:
293b96181c2SZachary Turner case LF_STRUCTURE:
294b96181c2SZachary Turner case LF_INTERFACE:
295b96181c2SZachary Turner case LF_UNION:
296b96181c2SZachary Turner return PDB_SymType::UDT;
297b96181c2SZachary Turner case LF_POINTER:
298b96181c2SZachary Turner return PDB_SymType::PointerType;
299b96181c2SZachary Turner case LF_ENUM:
300b96181c2SZachary Turner return PDB_SymType::Enum;
301544a66d8SZachary Turner case LF_PROCEDURE:
302544a66d8SZachary Turner return PDB_SymType::FunctionSig;
303056e4ab4SZachary Turner case LF_BITFIELD:
304056e4ab4SZachary Turner return PDB_SymType::BuiltinType;
305b96181c2SZachary Turner default:
306b96181c2SZachary Turner lldbassert(false && "Invalid type record kind!");
307b96181c2SZachary Turner }
308b96181c2SZachary Turner return PDB_SymType::None;
309b96181c2SZachary Turner }
310b96181c2SZachary Turner
SymbolHasAddress(const CVSymbol & sym)311b96181c2SZachary Turner bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
312307f5ae8SZachary Turner switch (sym.kind()) {
313307f5ae8SZachary Turner case S_GPROC32:
314307f5ae8SZachary Turner case S_LPROC32:
315307f5ae8SZachary Turner case S_GPROC32_ID:
316307f5ae8SZachary Turner case S_LPROC32_ID:
317307f5ae8SZachary Turner case S_LPROC32_DPC:
318307f5ae8SZachary Turner case S_LPROC32_DPC_ID:
319307f5ae8SZachary Turner case S_THUNK32:
320307f5ae8SZachary Turner case S_TRAMPOLINE:
321307f5ae8SZachary Turner case S_COFFGROUP:
322307f5ae8SZachary Turner case S_BLOCK32:
323307f5ae8SZachary Turner case S_LABEL32:
324307f5ae8SZachary Turner case S_CALLSITEINFO:
325307f5ae8SZachary Turner case S_HEAPALLOCSITE:
326307f5ae8SZachary Turner case S_LDATA32:
327307f5ae8SZachary Turner case S_GDATA32:
328307f5ae8SZachary Turner case S_LMANDATA:
329307f5ae8SZachary Turner case S_GMANDATA:
330307f5ae8SZachary Turner case S_LTHREAD32:
331307f5ae8SZachary Turner case S_GTHREAD32:
332307f5ae8SZachary Turner return true;
333307f5ae8SZachary Turner default:
334307f5ae8SZachary Turner return false;
335307f5ae8SZachary Turner }
336307f5ae8SZachary Turner }
337307f5ae8SZachary Turner
SymbolIsCode(const CVSymbol & sym)338b96181c2SZachary Turner bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
339307f5ae8SZachary Turner switch (sym.kind()) {
340307f5ae8SZachary Turner case S_GPROC32:
341307f5ae8SZachary Turner case S_LPROC32:
342307f5ae8SZachary Turner case S_GPROC32_ID:
343307f5ae8SZachary Turner case S_LPROC32_ID:
344307f5ae8SZachary Turner case S_LPROC32_DPC:
345307f5ae8SZachary Turner case S_LPROC32_DPC_ID:
346307f5ae8SZachary Turner case S_THUNK32:
347307f5ae8SZachary Turner case S_TRAMPOLINE:
348307f5ae8SZachary Turner case S_COFFGROUP:
349307f5ae8SZachary Turner case S_BLOCK32:
350307f5ae8SZachary Turner return true;
351307f5ae8SZachary Turner default:
352307f5ae8SZachary Turner return false;
353307f5ae8SZachary Turner }
354307f5ae8SZachary Turner }
355307f5ae8SZachary Turner
createRecord(const CVSymbol & sym)356307f5ae8SZachary Turner template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
357307f5ae8SZachary Turner RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
358307f5ae8SZachary Turner cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
359307f5ae8SZachary Turner return record;
360307f5ae8SZachary Turner }
361307f5ae8SZachary Turner
362307f5ae8SZachary Turner template <typename RecordT>
GetSegmentAndOffset(const CVSymbol & sym)363307f5ae8SZachary Turner static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
364307f5ae8SZachary Turner RecordT record = createRecord<RecordT>(sym);
365307f5ae8SZachary Turner return {record.Segment, record.CodeOffset};
366307f5ae8SZachary Turner }
367307f5ae8SZachary Turner
368307f5ae8SZachary Turner template <>
GetSegmentAndOffset(const CVSymbol & sym)369307f5ae8SZachary Turner SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
370307f5ae8SZachary Turner TrampolineSym record = createRecord<TrampolineSym>(sym);
371307f5ae8SZachary Turner return {record.ThunkSection, record.ThunkOffset};
372307f5ae8SZachary Turner }
373307f5ae8SZachary Turner
GetSegmentAndOffset(const CVSymbol & sym)374307f5ae8SZachary Turner template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
375307f5ae8SZachary Turner Thunk32Sym record = createRecord<Thunk32Sym>(sym);
376307f5ae8SZachary Turner return {record.Segment, record.Offset};
377307f5ae8SZachary Turner }
378307f5ae8SZachary Turner
379307f5ae8SZachary Turner template <>
GetSegmentAndOffset(const CVSymbol & sym)380307f5ae8SZachary Turner SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
381307f5ae8SZachary Turner CoffGroupSym record = createRecord<CoffGroupSym>(sym);
382307f5ae8SZachary Turner return {record.Segment, record.Offset};
383307f5ae8SZachary Turner }
384307f5ae8SZachary Turner
GetSegmentAndOffset(const CVSymbol & sym)385307f5ae8SZachary Turner template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
386307f5ae8SZachary Turner DataSym record = createRecord<DataSym>(sym);
387307f5ae8SZachary Turner return {record.Segment, record.DataOffset};
388307f5ae8SZachary Turner }
389307f5ae8SZachary Turner
390307f5ae8SZachary Turner template <>
GetSegmentAndOffset(const CVSymbol & sym)391307f5ae8SZachary Turner SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
392307f5ae8SZachary Turner ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
393307f5ae8SZachary Turner return {record.Segment, record.DataOffset};
394307f5ae8SZachary Turner }
395307f5ae8SZachary Turner
GetSegmentAndOffset(const CVSymbol & sym)396b96181c2SZachary Turner SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
397307f5ae8SZachary Turner switch (sym.kind()) {
398307f5ae8SZachary Turner case S_GPROC32:
399307f5ae8SZachary Turner case S_LPROC32:
400307f5ae8SZachary Turner case S_GPROC32_ID:
401307f5ae8SZachary Turner case S_LPROC32_ID:
402307f5ae8SZachary Turner case S_LPROC32_DPC:
403307f5ae8SZachary Turner case S_LPROC32_DPC_ID:
404307f5ae8SZachary Turner return ::GetSegmentAndOffset<ProcSym>(sym);
405307f5ae8SZachary Turner case S_THUNK32:
406307f5ae8SZachary Turner return ::GetSegmentAndOffset<Thunk32Sym>(sym);
407307f5ae8SZachary Turner break;
408307f5ae8SZachary Turner case S_TRAMPOLINE:
409307f5ae8SZachary Turner return ::GetSegmentAndOffset<TrampolineSym>(sym);
410307f5ae8SZachary Turner break;
411307f5ae8SZachary Turner case S_COFFGROUP:
412307f5ae8SZachary Turner return ::GetSegmentAndOffset<CoffGroupSym>(sym);
413307f5ae8SZachary Turner break;
414307f5ae8SZachary Turner case S_BLOCK32:
415307f5ae8SZachary Turner return ::GetSegmentAndOffset<BlockSym>(sym);
416307f5ae8SZachary Turner break;
417307f5ae8SZachary Turner case S_LABEL32:
418307f5ae8SZachary Turner return ::GetSegmentAndOffset<LabelSym>(sym);
419307f5ae8SZachary Turner break;
420307f5ae8SZachary Turner case S_CALLSITEINFO:
421307f5ae8SZachary Turner return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
422307f5ae8SZachary Turner break;
423307f5ae8SZachary Turner case S_HEAPALLOCSITE:
424307f5ae8SZachary Turner return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
425307f5ae8SZachary Turner break;
426307f5ae8SZachary Turner case S_LDATA32:
427307f5ae8SZachary Turner case S_GDATA32:
428307f5ae8SZachary Turner case S_LMANDATA:
429307f5ae8SZachary Turner case S_GMANDATA:
430307f5ae8SZachary Turner return ::GetSegmentAndOffset<DataSym>(sym);
431307f5ae8SZachary Turner break;
432307f5ae8SZachary Turner case S_LTHREAD32:
433307f5ae8SZachary Turner case S_GTHREAD32:
434307f5ae8SZachary Turner return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
435307f5ae8SZachary Turner break;
436307f5ae8SZachary Turner default:
437307f5ae8SZachary Turner lldbassert(false && "Record does not have a segment/offset!");
438307f5ae8SZachary Turner }
439307f5ae8SZachary Turner return {0, 0};
440307f5ae8SZachary Turner }
441307f5ae8SZachary Turner
442307f5ae8SZachary Turner template <typename RecordT>
GetSegmentOffsetAndLength(const CVSymbol & sym)443307f5ae8SZachary Turner SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
444307f5ae8SZachary Turner RecordT record = createRecord<RecordT>(sym);
445307f5ae8SZachary Turner return {record.Segment, record.CodeOffset, record.CodeSize};
446307f5ae8SZachary Turner }
447307f5ae8SZachary Turner
448307f5ae8SZachary Turner template <>
449307f5ae8SZachary Turner SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)450307f5ae8SZachary Turner GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
451307f5ae8SZachary Turner TrampolineSym record = createRecord<TrampolineSym>(sym);
452307f5ae8SZachary Turner return {record.ThunkSection, record.ThunkOffset, record.Size};
453307f5ae8SZachary Turner }
454307f5ae8SZachary Turner
455307f5ae8SZachary Turner template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)456307f5ae8SZachary Turner SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
457307f5ae8SZachary Turner Thunk32Sym record = createRecord<Thunk32Sym>(sym);
458307f5ae8SZachary Turner return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
459307f5ae8SZachary Turner }
460307f5ae8SZachary Turner
461307f5ae8SZachary Turner template <>
462307f5ae8SZachary Turner SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)463307f5ae8SZachary Turner GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
464307f5ae8SZachary Turner CoffGroupSym record = createRecord<CoffGroupSym>(sym);
465307f5ae8SZachary Turner return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
466307f5ae8SZachary Turner }
467307f5ae8SZachary Turner
468b96181c2SZachary Turner SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)469b96181c2SZachary Turner lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
470307f5ae8SZachary Turner switch (sym.kind()) {
471307f5ae8SZachary Turner case S_GPROC32:
472307f5ae8SZachary Turner case S_LPROC32:
473307f5ae8SZachary Turner case S_GPROC32_ID:
474307f5ae8SZachary Turner case S_LPROC32_ID:
475307f5ae8SZachary Turner case S_LPROC32_DPC:
476307f5ae8SZachary Turner case S_LPROC32_DPC_ID:
477307f5ae8SZachary Turner return ::GetSegmentOffsetAndLength<ProcSym>(sym);
478307f5ae8SZachary Turner case S_THUNK32:
479307f5ae8SZachary Turner return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
480307f5ae8SZachary Turner break;
481307f5ae8SZachary Turner case S_TRAMPOLINE:
482307f5ae8SZachary Turner return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
483307f5ae8SZachary Turner break;
484307f5ae8SZachary Turner case S_COFFGROUP:
485307f5ae8SZachary Turner return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
486307f5ae8SZachary Turner break;
487307f5ae8SZachary Turner case S_BLOCK32:
488307f5ae8SZachary Turner return ::GetSegmentOffsetAndLength<BlockSym>(sym);
489307f5ae8SZachary Turner break;
490307f5ae8SZachary Turner default:
491307f5ae8SZachary Turner lldbassert(false && "Record does not have a segment/offset/length triple!");
492307f5ae8SZachary Turner }
493307f5ae8SZachary Turner return {0, 0, 0};
494307f5ae8SZachary Turner }
495b96181c2SZachary Turner
IsForwardRefUdt(CVType cvt)496b96181c2SZachary Turner bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
497b96181c2SZachary Turner ClassRecord cr;
498b96181c2SZachary Turner UnionRecord ur;
499b96181c2SZachary Turner EnumRecord er;
500b96181c2SZachary Turner switch (cvt.kind()) {
501b96181c2SZachary Turner case LF_CLASS:
502b96181c2SZachary Turner case LF_STRUCTURE:
503b96181c2SZachary Turner case LF_INTERFACE:
504b96181c2SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
505b96181c2SZachary Turner return cr.isForwardRef();
506b96181c2SZachary Turner case LF_UNION:
507b96181c2SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
508b96181c2SZachary Turner return ur.isForwardRef();
509b96181c2SZachary Turner case LF_ENUM:
510b96181c2SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
511b96181c2SZachary Turner return er.isForwardRef();
512b96181c2SZachary Turner default:
513b96181c2SZachary Turner return false;
514b96181c2SZachary Turner }
515b96181c2SZachary Turner }
516b96181c2SZachary Turner
IsTagRecord(llvm::codeview::CVType cvt)517056e4ab4SZachary Turner bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
518056e4ab4SZachary Turner switch (cvt.kind()) {
519056e4ab4SZachary Turner case LF_CLASS:
520056e4ab4SZachary Turner case LF_STRUCTURE:
521056e4ab4SZachary Turner case LF_UNION:
522056e4ab4SZachary Turner case LF_ENUM:
523056e4ab4SZachary Turner return true;
524056e4ab4SZachary Turner default:
525056e4ab4SZachary Turner return false;
526056e4ab4SZachary Turner }
527056e4ab4SZachary Turner }
528056e4ab4SZachary Turner
IsClassStructUnion(llvm::codeview::CVType cvt)529594c85e9SZachary Turner bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
530594c85e9SZachary Turner switch (cvt.kind()) {
531594c85e9SZachary Turner case LF_CLASS:
532594c85e9SZachary Turner case LF_STRUCTURE:
533594c85e9SZachary Turner case LF_UNION:
534594c85e9SZachary Turner return true;
535594c85e9SZachary Turner default:
536594c85e9SZachary Turner return false;
537594c85e9SZachary Turner }
538594c85e9SZachary Turner }
539594c85e9SZachary Turner
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)5406284aee9SZachary Turner bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
5416284aee9SZachary Turner TpiStream &tpi) {
5426284aee9SZachary Turner if (id.is_ipi || id.index.isSimple())
5436284aee9SZachary Turner return false;
5446284aee9SZachary Turner return IsForwardRefUdt(tpi.getType(id.index));
5456284aee9SZachary Turner }
5466284aee9SZachary Turner
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)5476284aee9SZachary Turner bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
5486284aee9SZachary Turner if (id.is_ipi || id.index.isSimple())
5496284aee9SZachary Turner return false;
5506284aee9SZachary Turner return IsTagRecord(tpi.getType(id.index));
5516284aee9SZachary Turner }
5526284aee9SZachary Turner
553b96181c2SZachary Turner lldb::AccessType
TranslateMemberAccess(MemberAccess access)554b96181c2SZachary Turner lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
555b96181c2SZachary Turner switch (access) {
556b96181c2SZachary Turner case MemberAccess::Private:
557b96181c2SZachary Turner return lldb::eAccessPrivate;
558b96181c2SZachary Turner case MemberAccess::Protected:
559b96181c2SZachary Turner return lldb::eAccessProtected;
560b96181c2SZachary Turner case MemberAccess::Public:
561b96181c2SZachary Turner return lldb::eAccessPublic;
562b96181c2SZachary Turner case MemberAccess::None:
563b96181c2SZachary Turner return lldb::eAccessNone;
564b96181c2SZachary Turner }
565b96181c2SZachary Turner llvm_unreachable("unreachable");
566b96181c2SZachary Turner }
567b96181c2SZachary Turner
GetFieldListIndex(CVType cvt)568b96181c2SZachary Turner TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
569b96181c2SZachary Turner switch (cvt.kind()) {
570b96181c2SZachary Turner case LF_CLASS:
571b96181c2SZachary Turner case LF_STRUCTURE:
572b96181c2SZachary Turner case LF_INTERFACE: {
573b96181c2SZachary Turner ClassRecord cr;
574b96181c2SZachary Turner cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
575b96181c2SZachary Turner return cr.FieldList;
576b96181c2SZachary Turner }
577b96181c2SZachary Turner case LF_UNION: {
578b96181c2SZachary Turner UnionRecord ur;
579b96181c2SZachary Turner cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
580b96181c2SZachary Turner return ur.FieldList;
581b96181c2SZachary Turner }
582b96181c2SZachary Turner case LF_ENUM: {
583b96181c2SZachary Turner EnumRecord er;
584b96181c2SZachary Turner cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
585b96181c2SZachary Turner return er.FieldList;
586b96181c2SZachary Turner }
587b96181c2SZachary Turner default:
588b96181c2SZachary Turner llvm_unreachable("Unreachable!");
589b96181c2SZachary Turner }
590b96181c2SZachary Turner }
591b96181c2SZachary Turner
LookThroughModifierRecord(CVType modifier)592511bff21SZachary Turner TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
593511bff21SZachary Turner lldbassert(modifier.kind() == LF_MODIFIER);
594511bff21SZachary Turner ModifierRecord mr;
595511bff21SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
596511bff21SZachary Turner return mr.ModifiedType;
597511bff21SZachary Turner }
598511bff21SZachary Turner
DropNameScope(llvm::StringRef name)599b96181c2SZachary Turner llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
60044f19514SZachary Turner return MSVCUndecoratedNameParser::DropScope(name);
601b96181c2SZachary Turner }
602a93458b0SZachary Turner
GetVariableNameInfo(CVSymbol sym)603594c85e9SZachary Turner VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
6044871dfc6SSlava Gurevich VariableInfo result = {};
605594c85e9SZachary Turner
606594c85e9SZachary Turner if (sym.kind() == S_REGREL32) {
607594c85e9SZachary Turner RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
608594c85e9SZachary Turner cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
609594c85e9SZachary Turner result.type = reg.Type;
610594c85e9SZachary Turner result.name = reg.Name;
611594c85e9SZachary Turner return result;
612594c85e9SZachary Turner }
613594c85e9SZachary Turner
614594c85e9SZachary Turner if (sym.kind() == S_REGISTER) {
615594c85e9SZachary Turner RegisterSym reg(SymbolRecordKind::RegisterSym);
616594c85e9SZachary Turner cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
617594c85e9SZachary Turner result.type = reg.Index;
618594c85e9SZachary Turner result.name = reg.Name;
619594c85e9SZachary Turner return result;
620594c85e9SZachary Turner }
621594c85e9SZachary Turner
622594c85e9SZachary Turner if (sym.kind() == S_LOCAL) {
623594c85e9SZachary Turner LocalSym local(SymbolRecordKind::LocalSym);
624594c85e9SZachary Turner cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
625594c85e9SZachary Turner result.type = local.Type;
626594c85e9SZachary Turner result.name = local.Name;
6275e9c9b32SZequan Wu result.is_param =
6285e9c9b32SZequan Wu ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
629594c85e9SZachary Turner return result;
630594c85e9SZachary Turner }
631594c85e9SZachary Turner
6323790029dSZachary Turner if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
6333790029dSZachary Turner DataSym data(SymbolRecordKind::DataSym);
6343790029dSZachary Turner cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
6353790029dSZachary Turner result.type = data.Type;
6363790029dSZachary Turner result.name = data.Name;
6373790029dSZachary Turner return result;
6383790029dSZachary Turner }
6393790029dSZachary Turner
6403790029dSZachary Turner if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
6413790029dSZachary Turner ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
6423790029dSZachary Turner cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
6433790029dSZachary Turner result.type = data.Type;
6443790029dSZachary Turner result.name = data.Name;
6453790029dSZachary Turner return result;
6463790029dSZachary Turner }
6473790029dSZachary Turner
6483790029dSZachary Turner if (sym.kind() == S_CONSTANT) {
6493790029dSZachary Turner ConstantSym constant(SymbolRecordKind::ConstantSym);
6503790029dSZachary Turner cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
6513790029dSZachary Turner result.type = constant.Type;
6523790029dSZachary Turner result.name = constant.Name;
6533790029dSZachary Turner return result;
6543790029dSZachary Turner }
6553790029dSZachary Turner
656594c85e9SZachary Turner lldbassert(false && "Invalid variable record kind!");
657594c85e9SZachary Turner return {};
658594c85e9SZachary Turner }
659594c85e9SZachary Turner
6602c15fc56SAleksandr Urakov static llvm::FixedStreamArray<FrameData>::Iterator
GetCorrespondingFrameData(lldb::addr_t load_addr,const DebugFrameDataSubsectionRef & fpo_data,const Variable::RangeList & ranges)661758657e5SAleksandr Urakov GetCorrespondingFrameData(lldb::addr_t load_addr,
662758657e5SAleksandr Urakov const DebugFrameDataSubsectionRef &fpo_data,
663758657e5SAleksandr Urakov const Variable::RangeList &ranges) {
664758657e5SAleksandr Urakov lldbassert(!ranges.IsEmpty());
665758657e5SAleksandr Urakov
666758657e5SAleksandr Urakov // assume that all variable ranges correspond to one frame data
667758657e5SAleksandr Urakov using RangeListEntry = Variable::RangeList::Entry;
668758657e5SAleksandr Urakov const RangeListEntry &range = ranges.GetEntryRef(0);
669758657e5SAleksandr Urakov
670758657e5SAleksandr Urakov auto it = fpo_data.begin();
671758657e5SAleksandr Urakov
672758657e5SAleksandr Urakov // start by searching first frame data range containing variable range
673758657e5SAleksandr Urakov for (; it != fpo_data.end(); ++it) {
674758657e5SAleksandr Urakov RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
675758657e5SAleksandr Urakov
676758657e5SAleksandr Urakov if (fd_range.Contains(range)) {
677758657e5SAleksandr Urakov break;
678758657e5SAleksandr Urakov }
679758657e5SAleksandr Urakov }
680758657e5SAleksandr Urakov
681758657e5SAleksandr Urakov // then first most nested entry that still contains variable range
682758657e5SAleksandr Urakov auto found = it;
683758657e5SAleksandr Urakov for (; it != fpo_data.end(); ++it) {
684758657e5SAleksandr Urakov RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
685758657e5SAleksandr Urakov
686758657e5SAleksandr Urakov if (!fd_range.Contains(range)) {
687758657e5SAleksandr Urakov break;
688758657e5SAleksandr Urakov }
689758657e5SAleksandr Urakov found = it;
690758657e5SAleksandr Urakov }
691758657e5SAleksandr Urakov
692758657e5SAleksandr Urakov return found;
693758657e5SAleksandr Urakov }
694758657e5SAleksandr Urakov
GetFrameDataProgram(PdbIndex & index,const Variable::RangeList & ranges,llvm::StringRef & out_program)695758657e5SAleksandr Urakov static bool GetFrameDataProgram(PdbIndex &index,
696758657e5SAleksandr Urakov const Variable::RangeList &ranges,
697758657e5SAleksandr Urakov llvm::StringRef &out_program) {
698758657e5SAleksandr Urakov const DebugFrameDataSubsectionRef &new_fpo_data =
699758657e5SAleksandr Urakov index.dbi().getNewFpoRecords();
700758657e5SAleksandr Urakov
701758657e5SAleksandr Urakov auto frame_data_it =
702758657e5SAleksandr Urakov GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
703758657e5SAleksandr Urakov if (frame_data_it == new_fpo_data.end())
704758657e5SAleksandr Urakov return false;
705758657e5SAleksandr Urakov
706*960126e0SZequan Wu auto strings = index.pdb().getStringTable();
707*960126e0SZequan Wu if (!strings) {
708*960126e0SZequan Wu consumeError(strings.takeError());
709*960126e0SZequan Wu return false;
710*960126e0SZequan Wu }
711*960126e0SZequan Wu out_program = cantFail(strings->getStringForID(frame_data_it->FrameFunc));
712758657e5SAleksandr Urakov return true;
713758657e5SAleksandr Urakov }
714758657e5SAleksandr Urakov
GetBaseFrameRegister(PdbIndex & index,PdbCompilandSymId frame_proc_id,bool is_parameter)715758657e5SAleksandr Urakov static RegisterId GetBaseFrameRegister(PdbIndex &index,
716758657e5SAleksandr Urakov PdbCompilandSymId frame_proc_id,
717758657e5SAleksandr Urakov bool is_parameter) {
718758657e5SAleksandr Urakov CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
719d6710023SZequan Wu if (frame_proc_cvs.kind() != S_FRAMEPROC)
720d6710023SZequan Wu return RegisterId::NONE;
721758657e5SAleksandr Urakov
722758657e5SAleksandr Urakov FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
723758657e5SAleksandr Urakov cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
724758657e5SAleksandr Urakov frame_proc));
725758657e5SAleksandr Urakov
726758657e5SAleksandr Urakov CPUType cpu_type = index.compilands()
727758657e5SAleksandr Urakov .GetCompiland(frame_proc_id.modi)
728758657e5SAleksandr Urakov ->m_compile_opts->Machine;
729758657e5SAleksandr Urakov
730758657e5SAleksandr Urakov return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
731758657e5SAleksandr Urakov : frame_proc.getLocalFramePtrReg(cpu_type);
732758657e5SAleksandr Urakov }
733758657e5SAleksandr Urakov
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,Block & func_block,lldb::ModuleSP module)734594c85e9SZachary Turner VariableInfo lldb_private::npdb::GetVariableLocationInfo(
735b74a01a8SZequan Wu PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
736758657e5SAleksandr Urakov lldb::ModuleSP module) {
737594c85e9SZachary Turner
738594c85e9SZachary Turner CVSymbol sym = index.ReadSymbolRecord(var_id);
739594c85e9SZachary Turner
740594c85e9SZachary Turner VariableInfo result = GetVariableNameInfo(sym);
741594c85e9SZachary Turner
742594c85e9SZachary Turner if (sym.kind() == S_REGREL32) {
743594c85e9SZachary Turner RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
744594c85e9SZachary Turner cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
74571d778f3SZequan Wu result.location = DWARFExpressionList(
74671d778f3SZequan Wu module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
74771d778f3SZequan Wu nullptr);
748594c85e9SZachary Turner return result;
749594c85e9SZachary Turner }
750594c85e9SZachary Turner
751594c85e9SZachary Turner if (sym.kind() == S_REGISTER) {
752594c85e9SZachary Turner RegisterSym reg(SymbolRecordKind::RegisterSym);
753594c85e9SZachary Turner cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
75471d778f3SZequan Wu result.location = DWARFExpressionList(
75571d778f3SZequan Wu module, MakeEnregisteredLocationExpression(reg.Register, module),
75671d778f3SZequan Wu nullptr);
757594c85e9SZachary Turner return result;
758594c85e9SZachary Turner }
759594c85e9SZachary Turner
760594c85e9SZachary Turner if (sym.kind() == S_LOCAL) {
761594c85e9SZachary Turner LocalSym local(SymbolRecordKind::LocalSym);
76271d778f3SZequan Wu if (llvm::Error error =
76371d778f3SZequan Wu SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {
76471d778f3SZequan Wu llvm::consumeError(std::move(error));
76571d778f3SZequan Wu return result;
76671d778f3SZequan Wu }
767594c85e9SZachary Turner
768594c85e9SZachary Turner PdbCompilandSymId loc_specifier_id(var_id.modi,
769594c85e9SZachary Turner var_id.offset + sym.RecordData.size());
77071d778f3SZequan Wu CVSymbol loc_specifier_cvs;
77171d778f3SZequan Wu // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
77271d778f3SZequan Wu RegisterId base_reg = RegisterId::NONE;
77371d778f3SZequan Wu size_t type_size = GetSizeOfType(result.type, index.tpi());
77471d778f3SZequan Wu // A map from offset of a field in parent to size of the field.
77571d778f3SZequan Wu std::map<uint64_t, size_t> offset_to_size;
77671d778f3SZequan Wu
77771d778f3SZequan Wu // When overlaps happens, always prefer the one that doesn't split the value
77871d778f3SZequan Wu // into multiple locations and the location parsed first is perfered.
77971d778f3SZequan Wu RangeMap location_map;
78071d778f3SZequan Wu
78171d778f3SZequan Wu // Iterate through all location records after S_LOCAL. They describe the
78271d778f3SZequan Wu // value of this variable at different locations.
78371d778f3SZequan Wu bool finished = false;
78471d778f3SZequan Wu while (!finished) {
78571d778f3SZequan Wu loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
7865e9c9b32SZequan Wu switch (loc_specifier_cvs.kind()) {
7875e9c9b32SZequan Wu case S_DEFRANGE_FRAMEPOINTER_REL: {
788594c85e9SZachary Turner DefRangeFramePointerRelSym loc(
789594c85e9SZachary Turner SymbolRecordKind::DefRangeFramePointerRelSym);
79071d778f3SZequan Wu if (llvm::Error error =
79171d778f3SZequan Wu SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
79271d778f3SZequan Wu loc_specifier_cvs, loc)) {
79371d778f3SZequan Wu llvm::consumeError(std::move(error));
79471d778f3SZequan Wu return result;
79571d778f3SZequan Wu }
79671d778f3SZequan Wu Variable::RangeList raw_ranges =
79771d778f3SZequan Wu MakeRangeList(index, loc.Range, loc.Gaps);
79871d778f3SZequan Wu if (base_reg == RegisterId::NONE) {
799758657e5SAleksandr Urakov PdbCompilandSymId func_scope_id =
800b74a01a8SZequan Wu PdbSymUid(func_block.GetID()).asCompilandSym();
801758657e5SAleksandr Urakov CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
802758657e5SAleksandr Urakov lldbassert(func_block_cvs.kind() == S_GPROC32 ||
803758657e5SAleksandr Urakov func_block_cvs.kind() == S_LPROC32);
80471d778f3SZequan Wu PdbCompilandSymId frame_proc_id(func_scope_id.modi,
80571d778f3SZequan Wu func_scope_id.offset +
80671d778f3SZequan Wu func_block_cvs.length());
80771d778f3SZequan Wu base_reg =
8085e9c9b32SZequan Wu GetBaseFrameRegister(index, frame_proc_id, result.is_param);
809d6710023SZequan Wu if (base_reg == RegisterId::NONE)
810d6710023SZequan Wu break;
81171d778f3SZequan Wu }
81271d778f3SZequan Wu DWARFExpression expr;
813758657e5SAleksandr Urakov if (base_reg == RegisterId::VFRAME) {
814758657e5SAleksandr Urakov llvm::StringRef program;
81571d778f3SZequan Wu if (GetFrameDataProgram(index, raw_ranges, program))
81671d778f3SZequan Wu expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
81771d778f3SZequan Wu module);
81871d778f3SZequan Wu else {
819758657e5SAleksandr Urakov // invalid variable
820758657e5SAleksandr Urakov }
82171d778f3SZequan Wu } else
82271d778f3SZequan Wu expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
82371d778f3SZequan Wu AddDwarfRange(location_map, expr, raw_ranges);
8245e9c9b32SZequan Wu break;
8255e9c9b32SZequan Wu }
8265e9c9b32SZequan Wu case S_DEFRANGE_REGISTER: {
8275e9c9b32SZequan Wu DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
82871d778f3SZequan Wu if (llvm::Error error =
82971d778f3SZequan Wu SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
83071d778f3SZequan Wu loc_specifier_cvs, loc)) {
83171d778f3SZequan Wu llvm::consumeError(std::move(error));
83271d778f3SZequan Wu return result;
83371d778f3SZequan Wu }
83471d778f3SZequan Wu RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
83571d778f3SZequan Wu Variable::RangeList raw_ranges =
83671d778f3SZequan Wu MakeRangeList(index, loc.Range, loc.Gaps);
83771d778f3SZequan Wu DWARFExpression expr =
83871d778f3SZequan Wu MakeEnregisteredLocationExpression(reg_id, module);
83971d778f3SZequan Wu AddDwarfRange(location_map, expr, raw_ranges);
84071d778f3SZequan Wu break;
84171d778f3SZequan Wu }
84271d778f3SZequan Wu case S_DEFRANGE_REGISTER_REL: {
84371d778f3SZequan Wu DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
84471d778f3SZequan Wu if (llvm::Error error =
84571d778f3SZequan Wu SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
84671d778f3SZequan Wu loc_specifier_cvs, loc)) {
84771d778f3SZequan Wu llvm::consumeError(std::move(error));
84871d778f3SZequan Wu return result;
84971d778f3SZequan Wu }
85071d778f3SZequan Wu Variable::RangeList raw_ranges =
85171d778f3SZequan Wu MakeRangeList(index, loc.Range, loc.Gaps);
85271d778f3SZequan Wu RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
85371d778f3SZequan Wu DWARFExpression expr;
85471d778f3SZequan Wu if (reg_id == RegisterId::VFRAME) {
85571d778f3SZequan Wu llvm::StringRef program;
85671d778f3SZequan Wu if (GetFrameDataProgram(index, raw_ranges, program))
85771d778f3SZequan Wu expr = MakeVFrameRelLocationExpression(
85871d778f3SZequan Wu program, loc.Hdr.BasePointerOffset, module);
85971d778f3SZequan Wu else {
86071d778f3SZequan Wu // invalid variable
86171d778f3SZequan Wu }
86271d778f3SZequan Wu } else {
86371d778f3SZequan Wu expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,
86471d778f3SZequan Wu module);
86571d778f3SZequan Wu }
86671d778f3SZequan Wu // FIXME: If it's UDT, we need to know the size of the value in byte.
86771d778f3SZequan Wu if (!loc.hasSpilledUDTMember())
86871d778f3SZequan Wu AddDwarfRange(location_map, expr, raw_ranges);
8695e9c9b32SZequan Wu break;
8705e9c9b32SZequan Wu }
8715e9c9b32SZequan Wu case S_DEFRANGE_SUBFIELD_REGISTER: {
8725e9c9b32SZequan Wu DefRangeSubfieldRegisterSym loc(
8735e9c9b32SZequan Wu SymbolRecordKind::DefRangeSubfieldRegisterSym);
87471d778f3SZequan Wu if (llvm::Error error =
87571d778f3SZequan Wu SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
87671d778f3SZequan Wu loc_specifier_cvs, loc)) {
87771d778f3SZequan Wu llvm::consumeError(std::move(error));
8782fa27346SZequan Wu return result;
8792fa27346SZequan Wu }
88071d778f3SZequan Wu
88171d778f3SZequan Wu Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
88271d778f3SZequan Wu uint32_t reg_size =
88371d778f3SZequan Wu GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);
88471d778f3SZequan Wu if (reg_size == 0)
88571d778f3SZequan Wu break;
88671d778f3SZequan Wu offset_to_size[loc.Hdr.OffsetInParent] = reg_size;
88771d778f3SZequan Wu AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,
88871d778f3SZequan Wu {loc.Hdr.Register, 0, true}, ranges);
88971d778f3SZequan Wu break;
8905e9c9b32SZequan Wu }
89171d778f3SZequan Wu // FIXME: Handle other kinds. LLVM only generates the 4 types of records
89271d778f3SZequan Wu // above. MSVC generates other location types.
89371d778f3SZequan Wu case S_DEFRANGE:
89471d778f3SZequan Wu case S_DEFRANGE_SUBFIELD:
89571d778f3SZequan Wu case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
89671d778f3SZequan Wu break;
89771d778f3SZequan Wu default:
89871d778f3SZequan Wu finished = true;
89971d778f3SZequan Wu break;
9003dbf524aSZequan Wu }
9015e9c9b32SZequan Wu loc_specifier_id = PdbCompilandSymId(
9025e9c9b32SZequan Wu loc_specifier_id.modi,
9035e9c9b32SZequan Wu loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
9045e9c9b32SZequan Wu }
90571d778f3SZequan Wu for (const auto &entry : location_map) {
90671d778f3SZequan Wu DWARFExpression dwarf_expr =
90771d778f3SZequan Wu entry.data.is_dwarf ? entry.data.expr
90871d778f3SZequan Wu : MakeEnregisteredLocationExpressionForComposite(
90971d778f3SZequan Wu entry.data.offset_to_location,
91071d778f3SZequan Wu offset_to_size, type_size, module);
91171d778f3SZequan Wu
912aedad602SZequan Wu result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
91371d778f3SZequan Wu dwarf_expr);
9145e9c9b32SZequan Wu }
915594c85e9SZachary Turner return result;
916594c85e9SZachary Turner }
917594c85e9SZachary Turner llvm_unreachable("Symbol is not a local variable!");
918594c85e9SZachary Turner return result;
919594c85e9SZachary Turner }
920594c85e9SZachary Turner
921a93458b0SZachary Turner lldb::BasicType
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)922a93458b0SZachary Turner lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
923a93458b0SZachary Turner switch (kind) {
924a93458b0SZachary Turner case SimpleTypeKind::Boolean128:
925a93458b0SZachary Turner case SimpleTypeKind::Boolean16:
926a93458b0SZachary Turner case SimpleTypeKind::Boolean32:
927a93458b0SZachary Turner case SimpleTypeKind::Boolean64:
928a93458b0SZachary Turner case SimpleTypeKind::Boolean8:
929a93458b0SZachary Turner return lldb::eBasicTypeBool;
930a93458b0SZachary Turner case SimpleTypeKind::Byte:
931a93458b0SZachary Turner case SimpleTypeKind::UnsignedCharacter:
932a93458b0SZachary Turner return lldb::eBasicTypeUnsignedChar;
933a93458b0SZachary Turner case SimpleTypeKind::NarrowCharacter:
934a93458b0SZachary Turner return lldb::eBasicTypeChar;
935a93458b0SZachary Turner case SimpleTypeKind::SignedCharacter:
936a93458b0SZachary Turner case SimpleTypeKind::SByte:
937a93458b0SZachary Turner return lldb::eBasicTypeSignedChar;
938a93458b0SZachary Turner case SimpleTypeKind::Character16:
939a93458b0SZachary Turner return lldb::eBasicTypeChar16;
940a93458b0SZachary Turner case SimpleTypeKind::Character32:
941a93458b0SZachary Turner return lldb::eBasicTypeChar32;
9425c9e20d7SZequan Wu case SimpleTypeKind::Character8:
9435c9e20d7SZequan Wu return lldb::eBasicTypeChar8;
944a93458b0SZachary Turner case SimpleTypeKind::Complex80:
945a93458b0SZachary Turner return lldb::eBasicTypeLongDoubleComplex;
946a93458b0SZachary Turner case SimpleTypeKind::Complex64:
947a93458b0SZachary Turner return lldb::eBasicTypeDoubleComplex;
948a93458b0SZachary Turner case SimpleTypeKind::Complex32:
949a93458b0SZachary Turner return lldb::eBasicTypeFloatComplex;
950a93458b0SZachary Turner case SimpleTypeKind::Float128:
951a93458b0SZachary Turner case SimpleTypeKind::Float80:
952a93458b0SZachary Turner return lldb::eBasicTypeLongDouble;
953a93458b0SZachary Turner case SimpleTypeKind::Float64:
954a93458b0SZachary Turner return lldb::eBasicTypeDouble;
955a93458b0SZachary Turner case SimpleTypeKind::Float32:
956a93458b0SZachary Turner return lldb::eBasicTypeFloat;
957a93458b0SZachary Turner case SimpleTypeKind::Float16:
958a93458b0SZachary Turner return lldb::eBasicTypeHalf;
959a93458b0SZachary Turner case SimpleTypeKind::Int128:
960a93458b0SZachary Turner return lldb::eBasicTypeInt128;
961a93458b0SZachary Turner case SimpleTypeKind::Int64:
962a93458b0SZachary Turner case SimpleTypeKind::Int64Quad:
963a93458b0SZachary Turner return lldb::eBasicTypeLongLong;
964a93458b0SZachary Turner case SimpleTypeKind::Int32:
965a93458b0SZachary Turner return lldb::eBasicTypeInt;
966a93458b0SZachary Turner case SimpleTypeKind::Int16:
967a93458b0SZachary Turner case SimpleTypeKind::Int16Short:
968a93458b0SZachary Turner return lldb::eBasicTypeShort;
969a93458b0SZachary Turner case SimpleTypeKind::UInt128:
970a93458b0SZachary Turner return lldb::eBasicTypeUnsignedInt128;
971a93458b0SZachary Turner case SimpleTypeKind::UInt64:
972a93458b0SZachary Turner case SimpleTypeKind::UInt64Quad:
973a93458b0SZachary Turner return lldb::eBasicTypeUnsignedLongLong;
974a93458b0SZachary Turner case SimpleTypeKind::HResult:
975a93458b0SZachary Turner case SimpleTypeKind::UInt32:
976a93458b0SZachary Turner return lldb::eBasicTypeUnsignedInt;
977a93458b0SZachary Turner case SimpleTypeKind::UInt16:
978a93458b0SZachary Turner case SimpleTypeKind::UInt16Short:
979a93458b0SZachary Turner return lldb::eBasicTypeUnsignedShort;
980a93458b0SZachary Turner case SimpleTypeKind::Int32Long:
981a93458b0SZachary Turner return lldb::eBasicTypeLong;
982a93458b0SZachary Turner case SimpleTypeKind::UInt32Long:
983a93458b0SZachary Turner return lldb::eBasicTypeUnsignedLong;
984a93458b0SZachary Turner case SimpleTypeKind::Void:
985a93458b0SZachary Turner return lldb::eBasicTypeVoid;
986a93458b0SZachary Turner case SimpleTypeKind::WideCharacter:
987a93458b0SZachary Turner return lldb::eBasicTypeWChar;
988a93458b0SZachary Turner default:
989a93458b0SZachary Turner return lldb::eBasicTypeInvalid;
990a93458b0SZachary Turner }
991a93458b0SZachary Turner }
992a93458b0SZachary Turner
GetTypeSizeForSimpleKind(SimpleTypeKind kind)993a93458b0SZachary Turner size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
994a93458b0SZachary Turner switch (kind) {
995a93458b0SZachary Turner case SimpleTypeKind::Boolean128:
996a93458b0SZachary Turner case SimpleTypeKind::Int128:
997a93458b0SZachary Turner case SimpleTypeKind::UInt128:
998a93458b0SZachary Turner case SimpleTypeKind::Float128:
999a93458b0SZachary Turner return 16;
1000a93458b0SZachary Turner case SimpleTypeKind::Complex80:
1001a93458b0SZachary Turner case SimpleTypeKind::Float80:
1002a93458b0SZachary Turner return 10;
1003a93458b0SZachary Turner case SimpleTypeKind::Boolean64:
1004a93458b0SZachary Turner case SimpleTypeKind::Complex64:
1005a93458b0SZachary Turner case SimpleTypeKind::UInt64:
1006a93458b0SZachary Turner case SimpleTypeKind::UInt64Quad:
1007a93458b0SZachary Turner case SimpleTypeKind::Float64:
1008a93458b0SZachary Turner case SimpleTypeKind::Int64:
1009a93458b0SZachary Turner case SimpleTypeKind::Int64Quad:
1010a93458b0SZachary Turner return 8;
1011a93458b0SZachary Turner case SimpleTypeKind::Boolean32:
1012a93458b0SZachary Turner case SimpleTypeKind::Character32:
1013a93458b0SZachary Turner case SimpleTypeKind::Complex32:
1014a93458b0SZachary Turner case SimpleTypeKind::Float32:
1015a93458b0SZachary Turner case SimpleTypeKind::Int32:
1016a93458b0SZachary Turner case SimpleTypeKind::Int32Long:
1017a93458b0SZachary Turner case SimpleTypeKind::UInt32Long:
1018a93458b0SZachary Turner case SimpleTypeKind::HResult:
1019a93458b0SZachary Turner case SimpleTypeKind::UInt32:
1020a93458b0SZachary Turner return 4;
1021a93458b0SZachary Turner case SimpleTypeKind::Boolean16:
1022a93458b0SZachary Turner case SimpleTypeKind::Character16:
1023a93458b0SZachary Turner case SimpleTypeKind::Float16:
1024a93458b0SZachary Turner case SimpleTypeKind::Int16:
1025a93458b0SZachary Turner case SimpleTypeKind::Int16Short:
1026a93458b0SZachary Turner case SimpleTypeKind::UInt16:
1027a93458b0SZachary Turner case SimpleTypeKind::UInt16Short:
1028a93458b0SZachary Turner case SimpleTypeKind::WideCharacter:
1029a93458b0SZachary Turner return 2;
1030a93458b0SZachary Turner case SimpleTypeKind::Boolean8:
1031a93458b0SZachary Turner case SimpleTypeKind::Byte:
1032a93458b0SZachary Turner case SimpleTypeKind::UnsignedCharacter:
1033a93458b0SZachary Turner case SimpleTypeKind::NarrowCharacter:
1034a93458b0SZachary Turner case SimpleTypeKind::SignedCharacter:
1035a93458b0SZachary Turner case SimpleTypeKind::SByte:
10365c9e20d7SZequan Wu case SimpleTypeKind::Character8:
1037a93458b0SZachary Turner return 1;
1038a93458b0SZachary Turner case SimpleTypeKind::Void:
1039a93458b0SZachary Turner default:
1040a93458b0SZachary Turner return 0;
1041a93458b0SZachary Turner }
1042a93458b0SZachary Turner }
1043594c85e9SZachary Turner
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)1044594c85e9SZachary Turner PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
1045594c85e9SZachary Turner TpiStream &tpi) {
1046594c85e9SZachary Turner if (id.index.isSimple())
1047594c85e9SZachary Turner return id;
1048594c85e9SZachary Turner
1049594c85e9SZachary Turner CVType cvt = tpi.getType(id.index);
1050594c85e9SZachary Turner
1051594c85e9SZachary Turner // Only tag records have a best and a worst record.
1052594c85e9SZachary Turner if (!IsTagRecord(cvt))
1053594c85e9SZachary Turner return id;
1054594c85e9SZachary Turner
1055594c85e9SZachary Turner // Tag records that are not forward decls are full decls, hence they are the
1056594c85e9SZachary Turner // best.
1057594c85e9SZachary Turner if (!IsForwardRefUdt(cvt))
1058594c85e9SZachary Turner return id;
1059594c85e9SZachary Turner
1060594c85e9SZachary Turner return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
1061594c85e9SZachary Turner }
1062594c85e9SZachary Turner
GetSizeOfTypeInternal(CVType cvt)1063594c85e9SZachary Turner template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
1064594c85e9SZachary Turner RecordType record;
1065594c85e9SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
1066594c85e9SZachary Turner return record.getSize();
1067594c85e9SZachary Turner }
1068594c85e9SZachary Turner
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)1069594c85e9SZachary Turner size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
1070594c85e9SZachary Turner llvm::pdb::TpiStream &tpi) {
1071594c85e9SZachary Turner if (id.index.isSimple()) {
1072594c85e9SZachary Turner switch (id.index.getSimpleMode()) {
1073594c85e9SZachary Turner case SimpleTypeMode::Direct:
1074594c85e9SZachary Turner return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
1075594c85e9SZachary Turner case SimpleTypeMode::NearPointer32:
1076594c85e9SZachary Turner case SimpleTypeMode::FarPointer32:
1077594c85e9SZachary Turner return 4;
1078594c85e9SZachary Turner case SimpleTypeMode::NearPointer64:
1079594c85e9SZachary Turner return 8;
1080594c85e9SZachary Turner case SimpleTypeMode::NearPointer128:
1081594c85e9SZachary Turner return 16;
1082594c85e9SZachary Turner default:
1083594c85e9SZachary Turner break;
1084594c85e9SZachary Turner }
1085594c85e9SZachary Turner return 0;
1086594c85e9SZachary Turner }
1087594c85e9SZachary Turner
108822566330SZachary Turner TypeIndex index = id.index;
108922566330SZachary Turner if (IsForwardRefUdt(index, tpi))
109022566330SZachary Turner index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
109122566330SZachary Turner
109222566330SZachary Turner CVType cvt = tpi.getType(index);
1093594c85e9SZachary Turner switch (cvt.kind()) {
1094594c85e9SZachary Turner case LF_MODIFIER:
1095594c85e9SZachary Turner return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
1096594c85e9SZachary Turner case LF_ENUM: {
1097594c85e9SZachary Turner EnumRecord record;
1098594c85e9SZachary Turner llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
1099594c85e9SZachary Turner return GetSizeOfType({record.UnderlyingType}, tpi);
1100594c85e9SZachary Turner }
1101594c85e9SZachary Turner case LF_POINTER:
1102594c85e9SZachary Turner return GetSizeOfTypeInternal<PointerRecord>(cvt);
1103594c85e9SZachary Turner case LF_ARRAY:
1104594c85e9SZachary Turner return GetSizeOfTypeInternal<ArrayRecord>(cvt);
1105594c85e9SZachary Turner case LF_CLASS:
1106594c85e9SZachary Turner case LF_STRUCTURE:
1107594c85e9SZachary Turner case LF_INTERFACE:
1108594c85e9SZachary Turner return GetSizeOfTypeInternal<ClassRecord>(cvt);
1109594c85e9SZachary Turner case LF_UNION:
1110594c85e9SZachary Turner return GetSizeOfTypeInternal<UnionRecord>(cvt);
1111d3492ed0SZequan Wu case LF_BITFIELD: {
1112d3492ed0SZequan Wu BitFieldRecord record;
1113d3492ed0SZequan Wu llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));
1114d3492ed0SZequan Wu return GetSizeOfType({record.Type}, tpi);
1115d3492ed0SZequan Wu }
1116594c85e9SZachary Turner default:
1117594c85e9SZachary Turner break;
1118594c85e9SZachary Turner }
1119594c85e9SZachary Turner return 0;
1120594c85e9SZachary Turner }
1121