15ffd83dbSDimitry Andric //===-- PdbUtil.cpp -------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "PdbUtil.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "DWARFLocationExpression.h"
120b57cec5SDimitry Andric #include "PdbIndex.h"
130b57cec5SDimitry Andric #include "PdbSymUid.h"
140b57cec5SDimitry Andric
1581ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
170b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
22bdd1243dSDimitry Andric #include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
230b57cec5SDimitry Andric #include "lldb/Symbol/Block.h"
240b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
2581ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
260b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric using namespace lldb_private;
290b57cec5SDimitry Andric using namespace lldb_private::npdb;
300b57cec5SDimitry Andric using namespace llvm::codeview;
310b57cec5SDimitry Andric using namespace llvm::pdb;
320b57cec5SDimitry Andric
33bdd1243dSDimitry Andric // The returned range list is guaranteed to be sorted and no overlaps between
34bdd1243dSDimitry Andric // adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
350b57cec5SDimitry Andric static Variable::RangeList
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)360b57cec5SDimitry Andric MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
370b57cec5SDimitry Andric llvm::ArrayRef<LocalVariableAddrGap> gaps) {
380b57cec5SDimitry Andric lldb::addr_t start =
390b57cec5SDimitry Andric index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
4081ad6265SDimitry Andric if (start == LLDB_INVALID_ADDRESS)
4181ad6265SDimitry Andric return {};
420b57cec5SDimitry Andric lldb::addr_t end = start + range.Range;
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric Variable::RangeList result;
450b57cec5SDimitry Andric while (!gaps.empty()) {
460b57cec5SDimitry Andric const LocalVariableAddrGap &gap = gaps.front();
4781ad6265SDimitry Andric lldb::addr_t gap_start = start + gap.GapStartOffset;
4881ad6265SDimitry Andric result.Append(start, gap_start - start);
4981ad6265SDimitry Andric start = gap_start + gap.Range;
500b57cec5SDimitry Andric gaps = gaps.drop_front();
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric result.Append(start, end - start);
540b57cec5SDimitry Andric return result;
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric
5781ad6265SDimitry Andric namespace {
58bdd1243dSDimitry Andric struct MemberLocations {
59bdd1243dSDimitry Andric std::map<uint64_t, MemberValLocation> offset_to_location;
60bdd1243dSDimitry Andric DWARFExpression expr;
61bdd1243dSDimitry Andric bool is_dwarf = false;
62bdd1243dSDimitry Andric
63bdd1243dSDimitry Andric MemberLocations() = default;
MemberLocations__anon86ad4bd50111::MemberLocations64bdd1243dSDimitry Andric MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}
MemberLocations__anon86ad4bd50111::MemberLocations65bdd1243dSDimitry Andric MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {
66bdd1243dSDimitry Andric insert(offset, member_loc);
67bdd1243dSDimitry Andric }
68bdd1243dSDimitry Andric
insert__anon86ad4bd50111::MemberLocations69bdd1243dSDimitry Andric void insert(uint64_t offset, const MemberValLocation &member_loc) {
70bdd1243dSDimitry Andric offset_to_location[offset] = member_loc;
71bdd1243dSDimitry Andric }
72bdd1243dSDimitry Andric
73bdd1243dSDimitry Andric struct Comparator {
74bdd1243dSDimitry Andric public:
operator ()__anon86ad4bd50111::MemberLocations::Comparator75bdd1243dSDimitry Andric bool operator()(const MemberLocations &, const MemberLocations &) const {
76bdd1243dSDimitry Andric return false;
7781ad6265SDimitry Andric }
7881ad6265SDimitry Andric };
79bdd1243dSDimitry Andric };
80bdd1243dSDimitry Andric
81bdd1243dSDimitry Andric // A range map with address ranges to a map of pair of offset and locaitons.
82bdd1243dSDimitry Andric typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
83bdd1243dSDimitry Andric MemberLocations::Comparator>
84bdd1243dSDimitry Andric RangeMap;
85bdd1243dSDimitry Andric
AddMemberLocationRanges(RangeMap & location_map,uint64_t offset,MemberValLocation member_loc,const Variable::RangeList & ranges)86bdd1243dSDimitry Andric void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,
87bdd1243dSDimitry Andric MemberValLocation member_loc,
88bdd1243dSDimitry Andric const Variable::RangeList &ranges) {
89bdd1243dSDimitry Andric RangeMap new_location_map;
90bdd1243dSDimitry Andric auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,
91bdd1243dSDimitry Andric RangeMap::Entry *entry) {
92bdd1243dSDimitry Andric RangeMap::Entry overlap_region = {base, end - base, entry->data};
93bdd1243dSDimitry Andric overlap_region.data.insert(offset, member_loc);
94bdd1243dSDimitry Andric new_location_map.Append(overlap_region);
95bdd1243dSDimitry Andric };
96bdd1243dSDimitry Andric
97bdd1243dSDimitry Andric for (const auto &range : ranges) {
98bdd1243dSDimitry Andric lldb::addr_t base = range.GetRangeBase();
99bdd1243dSDimitry Andric lldb::addr_t end = range.GetRangeEnd();
100bdd1243dSDimitry Andric uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
101bdd1243dSDimitry Andric while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
102bdd1243dSDimitry Andric if (base >= end || entry->base >= end)
103bdd1243dSDimitry Andric break;
104bdd1243dSDimitry Andric if (entry->data.is_dwarf)
105bdd1243dSDimitry Andric base = entry->GetRangeEnd();
106bdd1243dSDimitry Andric else {
107bdd1243dSDimitry Andric lldb::addr_t entry_end = entry->GetRangeEnd();
108bdd1243dSDimitry Andric if (base > entry->base) {
109bdd1243dSDimitry Andric if (end < entry_end)
110bdd1243dSDimitry Andric new_location_map.Append({end, entry_end - end, entry->data});
111bdd1243dSDimitry Andric add_overlap_region(base, end < entry_end ? end : entry_end, entry);
112bdd1243dSDimitry Andric entry->SetRangeEnd(base);
113bdd1243dSDimitry Andric } else if (base < entry->base) {
114bdd1243dSDimitry Andric new_location_map.Append(
115bdd1243dSDimitry Andric {base, entry->base - base, {offset, member_loc}});
116bdd1243dSDimitry Andric if (entry_end == end)
117bdd1243dSDimitry Andric entry->data.insert(offset, member_loc);
118bdd1243dSDimitry Andric else {
119bdd1243dSDimitry Andric add_overlap_region(entry->base, end, entry);
120bdd1243dSDimitry Andric entry->ShrinkFront(end - entry->base);
121bdd1243dSDimitry Andric }
122bdd1243dSDimitry Andric } else {
123bdd1243dSDimitry Andric if (end < entry_end) {
124bdd1243dSDimitry Andric new_location_map.Append({end, entry_end, entry->data});
125bdd1243dSDimitry Andric entry->SetRangeEnd(end);
126bdd1243dSDimitry Andric }
127bdd1243dSDimitry Andric entry->data.insert(offset, member_loc);
128bdd1243dSDimitry Andric }
129bdd1243dSDimitry Andric base = entry_end;
130bdd1243dSDimitry Andric }
131bdd1243dSDimitry Andric ++base_idx;
132bdd1243dSDimitry Andric }
133bdd1243dSDimitry Andric if (base >= end)
134bdd1243dSDimitry Andric continue;
135bdd1243dSDimitry Andric new_location_map.Append({base, end - base, {offset, member_loc}});
136bdd1243dSDimitry Andric }
137bdd1243dSDimitry Andric for (const auto &entry : new_location_map)
138bdd1243dSDimitry Andric location_map.Append(entry);
139bdd1243dSDimitry Andric if (!new_location_map.IsEmpty())
140bdd1243dSDimitry Andric location_map.Sort();
141bdd1243dSDimitry Andric }
142bdd1243dSDimitry Andric
AddDwarfRange(RangeMap & location_map,const DWARFExpression & expr,const Variable::RangeList & ranges)143bdd1243dSDimitry Andric void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,
144bdd1243dSDimitry Andric const Variable::RangeList &ranges) {
145bdd1243dSDimitry Andric if (!expr.IsValid())
146bdd1243dSDimitry Andric return;
147bdd1243dSDimitry Andric RangeMap new_location_map;
148bdd1243dSDimitry Andric for (const auto &range : ranges) {
149bdd1243dSDimitry Andric lldb::addr_t base = range.GetRangeBase();
150bdd1243dSDimitry Andric lldb::addr_t end = range.GetRangeEnd();
151bdd1243dSDimitry Andric uint32_t base_idx = location_map.FindEntryIndexThatContains(base);
152bdd1243dSDimitry Andric uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);
153bdd1243dSDimitry Andric // range is within an entry.
154bdd1243dSDimitry Andric if (base_idx == end_idx && base_idx != UINT32_MAX) {
155bdd1243dSDimitry Andric auto *entry = location_map.GetMutableEntryAtIndex(base_idx);
156bdd1243dSDimitry Andric if (base > entry->base) {
157bdd1243dSDimitry Andric new_location_map.Append({entry->base, base - entry->base, entry->data});
158bdd1243dSDimitry Andric entry->ShrinkFront(base - entry->base);
159bdd1243dSDimitry Andric }
160bdd1243dSDimitry Andric if (end == entry->GetRangeEnd())
161bdd1243dSDimitry Andric entry->data = expr;
162bdd1243dSDimitry Andric else {
163bdd1243dSDimitry Andric entry->ShrinkFront(end - base);
164bdd1243dSDimitry Andric new_location_map.Append({base, end - base, expr});
165bdd1243dSDimitry Andric }
166bdd1243dSDimitry Andric continue;
167bdd1243dSDimitry Andric }
168bdd1243dSDimitry Andric base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
169bdd1243dSDimitry Andric if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
170bdd1243dSDimitry Andric if (entry->Contains(base) && entry->base != base) {
171bdd1243dSDimitry Andric entry->SetRangeEnd(base);
172bdd1243dSDimitry Andric ++base_idx;
173bdd1243dSDimitry Andric }
174bdd1243dSDimitry Andric }
175bdd1243dSDimitry Andric end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);
176bdd1243dSDimitry Andric if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {
177bdd1243dSDimitry Andric if (entry->Contains(end - 1)) {
178bdd1243dSDimitry Andric if (entry->GetRangeEnd() == end)
179bdd1243dSDimitry Andric ++end_idx;
180bdd1243dSDimitry Andric else
181bdd1243dSDimitry Andric entry->ShrinkFront(end - entry->base);
182bdd1243dSDimitry Andric }
183bdd1243dSDimitry Andric }
184bdd1243dSDimitry Andric
185bdd1243dSDimitry Andric if (end_idx == UINT32_MAX)
186bdd1243dSDimitry Andric end_idx = location_map.GetSize();
187bdd1243dSDimitry Andric // Erase existing ranges covered by new range.
188bdd1243dSDimitry Andric location_map.Erase(base_idx, end_idx);
189bdd1243dSDimitry Andric new_location_map.Append({base, end - base, expr});
190bdd1243dSDimitry Andric }
191bdd1243dSDimitry Andric
192bdd1243dSDimitry Andric for (const auto &entry : new_location_map)
193bdd1243dSDimitry Andric location_map.Append(entry);
194bdd1243dSDimitry Andric location_map.Sort();
195bdd1243dSDimitry Andric }
19681ad6265SDimitry Andric } // namespace
19781ad6265SDimitry Andric
create(CVType type)1980b57cec5SDimitry Andric CVTagRecord CVTagRecord::create(CVType type) {
1990b57cec5SDimitry Andric assert(IsTagRecord(type) && "type is not a tag record!");
2000b57cec5SDimitry Andric switch (type.kind()) {
2010b57cec5SDimitry Andric case LF_CLASS:
2020b57cec5SDimitry Andric case LF_STRUCTURE:
2030b57cec5SDimitry Andric case LF_INTERFACE: {
2040b57cec5SDimitry Andric ClassRecord cr;
2050b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
2060b57cec5SDimitry Andric return CVTagRecord(std::move(cr));
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric case LF_UNION: {
2090b57cec5SDimitry Andric UnionRecord ur;
2100b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
2110b57cec5SDimitry Andric return CVTagRecord(std::move(ur));
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric case LF_ENUM: {
2140b57cec5SDimitry Andric EnumRecord er;
2150b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
2160b57cec5SDimitry Andric return CVTagRecord(std::move(er));
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric default:
2190b57cec5SDimitry Andric llvm_unreachable("Unreachable!");
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric
CVTagRecord(ClassRecord && c)2230b57cec5SDimitry Andric CVTagRecord::CVTagRecord(ClassRecord &&c)
2240b57cec5SDimitry Andric : cvclass(std::move(c)),
2250b57cec5SDimitry Andric m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)2260b57cec5SDimitry Andric CVTagRecord::CVTagRecord(UnionRecord &&u)
2270b57cec5SDimitry Andric : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)2280b57cec5SDimitry Andric CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
2290b57cec5SDimitry Andric
CVSymToPDBSym(SymbolKind kind)2300b57cec5SDimitry Andric PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
2310b57cec5SDimitry Andric switch (kind) {
2320b57cec5SDimitry Andric case S_COMPILE3:
2330b57cec5SDimitry Andric case S_OBJNAME:
2340b57cec5SDimitry Andric return PDB_SymType::CompilandDetails;
2350b57cec5SDimitry Andric case S_ENVBLOCK:
2360b57cec5SDimitry Andric return PDB_SymType::CompilandEnv;
2370b57cec5SDimitry Andric case S_THUNK32:
2380b57cec5SDimitry Andric case S_TRAMPOLINE:
2390b57cec5SDimitry Andric return PDB_SymType::Thunk;
2400b57cec5SDimitry Andric case S_COFFGROUP:
2410b57cec5SDimitry Andric return PDB_SymType::CoffGroup;
2420b57cec5SDimitry Andric case S_EXPORT:
2430b57cec5SDimitry Andric return PDB_SymType::Export;
2440b57cec5SDimitry Andric case S_LPROC32:
2450b57cec5SDimitry Andric case S_GPROC32:
2460b57cec5SDimitry Andric case S_LPROC32_DPC:
2470b57cec5SDimitry Andric return PDB_SymType::Function;
2480b57cec5SDimitry Andric case S_PUB32:
2490b57cec5SDimitry Andric return PDB_SymType::PublicSymbol;
2500b57cec5SDimitry Andric case S_INLINESITE:
2510b57cec5SDimitry Andric return PDB_SymType::InlineSite;
2520b57cec5SDimitry Andric case S_LOCAL:
2530b57cec5SDimitry Andric case S_BPREL32:
2540b57cec5SDimitry Andric case S_REGREL32:
2550b57cec5SDimitry Andric case S_MANCONSTANT:
2560b57cec5SDimitry Andric case S_CONSTANT:
2570b57cec5SDimitry Andric case S_LDATA32:
2580b57cec5SDimitry Andric case S_GDATA32:
2590b57cec5SDimitry Andric case S_LMANDATA:
2600b57cec5SDimitry Andric case S_GMANDATA:
2610b57cec5SDimitry Andric case S_LTHREAD32:
2620b57cec5SDimitry Andric case S_GTHREAD32:
2630b57cec5SDimitry Andric return PDB_SymType::Data;
2640b57cec5SDimitry Andric case S_BLOCK32:
2650b57cec5SDimitry Andric return PDB_SymType::Block;
2660b57cec5SDimitry Andric case S_LABEL32:
2670b57cec5SDimitry Andric return PDB_SymType::Label;
2680b57cec5SDimitry Andric case S_CALLSITEINFO:
2690b57cec5SDimitry Andric return PDB_SymType::CallSite;
2700b57cec5SDimitry Andric case S_HEAPALLOCSITE:
2710b57cec5SDimitry Andric return PDB_SymType::HeapAllocationSite;
2720b57cec5SDimitry Andric case S_CALLEES:
2730b57cec5SDimitry Andric return PDB_SymType::Callee;
2740b57cec5SDimitry Andric case S_CALLERS:
2750b57cec5SDimitry Andric return PDB_SymType::Caller;
2760b57cec5SDimitry Andric default:
2770b57cec5SDimitry Andric lldbassert(false && "Invalid symbol record kind!");
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric return PDB_SymType::None;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric
CVTypeToPDBType(TypeLeafKind kind)2820b57cec5SDimitry Andric PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
2830b57cec5SDimitry Andric switch (kind) {
2840b57cec5SDimitry Andric case LF_ARRAY:
2850b57cec5SDimitry Andric return PDB_SymType::ArrayType;
2860b57cec5SDimitry Andric case LF_ARGLIST:
2870b57cec5SDimitry Andric return PDB_SymType::FunctionSig;
2880b57cec5SDimitry Andric case LF_BCLASS:
2890b57cec5SDimitry Andric return PDB_SymType::BaseClass;
2900b57cec5SDimitry Andric case LF_BINTERFACE:
2910b57cec5SDimitry Andric return PDB_SymType::BaseInterface;
2920b57cec5SDimitry Andric case LF_CLASS:
2930b57cec5SDimitry Andric case LF_STRUCTURE:
2940b57cec5SDimitry Andric case LF_INTERFACE:
2950b57cec5SDimitry Andric case LF_UNION:
2960b57cec5SDimitry Andric return PDB_SymType::UDT;
2970b57cec5SDimitry Andric case LF_POINTER:
2980b57cec5SDimitry Andric return PDB_SymType::PointerType;
2990b57cec5SDimitry Andric case LF_ENUM:
3000b57cec5SDimitry Andric return PDB_SymType::Enum;
3010b57cec5SDimitry Andric case LF_PROCEDURE:
3020b57cec5SDimitry Andric return PDB_SymType::FunctionSig;
3030b57cec5SDimitry Andric case LF_BITFIELD:
3040b57cec5SDimitry Andric return PDB_SymType::BuiltinType;
3050b57cec5SDimitry Andric default:
3060b57cec5SDimitry Andric lldbassert(false && "Invalid type record kind!");
3070b57cec5SDimitry Andric }
3080b57cec5SDimitry Andric return PDB_SymType::None;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric
SymbolHasAddress(const CVSymbol & sym)3110b57cec5SDimitry Andric bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
3120b57cec5SDimitry Andric switch (sym.kind()) {
3130b57cec5SDimitry Andric case S_GPROC32:
3140b57cec5SDimitry Andric case S_LPROC32:
3150b57cec5SDimitry Andric case S_GPROC32_ID:
3160b57cec5SDimitry Andric case S_LPROC32_ID:
3170b57cec5SDimitry Andric case S_LPROC32_DPC:
3180b57cec5SDimitry Andric case S_LPROC32_DPC_ID:
3190b57cec5SDimitry Andric case S_THUNK32:
3200b57cec5SDimitry Andric case S_TRAMPOLINE:
3210b57cec5SDimitry Andric case S_COFFGROUP:
3220b57cec5SDimitry Andric case S_BLOCK32:
3230b57cec5SDimitry Andric case S_LABEL32:
3240b57cec5SDimitry Andric case S_CALLSITEINFO:
3250b57cec5SDimitry Andric case S_HEAPALLOCSITE:
3260b57cec5SDimitry Andric case S_LDATA32:
3270b57cec5SDimitry Andric case S_GDATA32:
3280b57cec5SDimitry Andric case S_LMANDATA:
3290b57cec5SDimitry Andric case S_GMANDATA:
3300b57cec5SDimitry Andric case S_LTHREAD32:
3310b57cec5SDimitry Andric case S_GTHREAD32:
3320b57cec5SDimitry Andric return true;
3330b57cec5SDimitry Andric default:
3340b57cec5SDimitry Andric return false;
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric
SymbolIsCode(const CVSymbol & sym)3380b57cec5SDimitry Andric bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
3390b57cec5SDimitry Andric switch (sym.kind()) {
3400b57cec5SDimitry Andric case S_GPROC32:
3410b57cec5SDimitry Andric case S_LPROC32:
3420b57cec5SDimitry Andric case S_GPROC32_ID:
3430b57cec5SDimitry Andric case S_LPROC32_ID:
3440b57cec5SDimitry Andric case S_LPROC32_DPC:
3450b57cec5SDimitry Andric case S_LPROC32_DPC_ID:
3460b57cec5SDimitry Andric case S_THUNK32:
3470b57cec5SDimitry Andric case S_TRAMPOLINE:
3480b57cec5SDimitry Andric case S_COFFGROUP:
3490b57cec5SDimitry Andric case S_BLOCK32:
3500b57cec5SDimitry Andric return true;
3510b57cec5SDimitry Andric default:
3520b57cec5SDimitry Andric return false;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
createRecord(const CVSymbol & sym)3560b57cec5SDimitry Andric template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
3570b57cec5SDimitry Andric RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
3580b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
3590b57cec5SDimitry Andric return record;
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric template <typename RecordT>
GetSegmentAndOffset(const CVSymbol & sym)3630b57cec5SDimitry Andric static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
3640b57cec5SDimitry Andric RecordT record = createRecord<RecordT>(sym);
3650b57cec5SDimitry Andric return {record.Segment, record.CodeOffset};
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric template <>
GetSegmentAndOffset(const CVSymbol & sym)3690b57cec5SDimitry Andric SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
3700b57cec5SDimitry Andric TrampolineSym record = createRecord<TrampolineSym>(sym);
3710b57cec5SDimitry Andric return {record.ThunkSection, record.ThunkOffset};
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric
GetSegmentAndOffset(const CVSymbol & sym)3740b57cec5SDimitry Andric template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
3750b57cec5SDimitry Andric Thunk32Sym record = createRecord<Thunk32Sym>(sym);
3760b57cec5SDimitry Andric return {record.Segment, record.Offset};
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andric template <>
GetSegmentAndOffset(const CVSymbol & sym)3800b57cec5SDimitry Andric SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
3810b57cec5SDimitry Andric CoffGroupSym record = createRecord<CoffGroupSym>(sym);
3820b57cec5SDimitry Andric return {record.Segment, record.Offset};
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric
GetSegmentAndOffset(const CVSymbol & sym)3850b57cec5SDimitry Andric template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
3860b57cec5SDimitry Andric DataSym record = createRecord<DataSym>(sym);
3870b57cec5SDimitry Andric return {record.Segment, record.DataOffset};
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric template <>
GetSegmentAndOffset(const CVSymbol & sym)3910b57cec5SDimitry Andric SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
3920b57cec5SDimitry Andric ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
3930b57cec5SDimitry Andric return {record.Segment, record.DataOffset};
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric
GetSegmentAndOffset(const CVSymbol & sym)3960b57cec5SDimitry Andric SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
3970b57cec5SDimitry Andric switch (sym.kind()) {
3980b57cec5SDimitry Andric case S_GPROC32:
3990b57cec5SDimitry Andric case S_LPROC32:
4000b57cec5SDimitry Andric case S_GPROC32_ID:
4010b57cec5SDimitry Andric case S_LPROC32_ID:
4020b57cec5SDimitry Andric case S_LPROC32_DPC:
4030b57cec5SDimitry Andric case S_LPROC32_DPC_ID:
4040b57cec5SDimitry Andric return ::GetSegmentAndOffset<ProcSym>(sym);
4050b57cec5SDimitry Andric case S_THUNK32:
4060b57cec5SDimitry Andric return ::GetSegmentAndOffset<Thunk32Sym>(sym);
4070b57cec5SDimitry Andric break;
4080b57cec5SDimitry Andric case S_TRAMPOLINE:
4090b57cec5SDimitry Andric return ::GetSegmentAndOffset<TrampolineSym>(sym);
4100b57cec5SDimitry Andric break;
4110b57cec5SDimitry Andric case S_COFFGROUP:
4120b57cec5SDimitry Andric return ::GetSegmentAndOffset<CoffGroupSym>(sym);
4130b57cec5SDimitry Andric break;
4140b57cec5SDimitry Andric case S_BLOCK32:
4150b57cec5SDimitry Andric return ::GetSegmentAndOffset<BlockSym>(sym);
4160b57cec5SDimitry Andric break;
4170b57cec5SDimitry Andric case S_LABEL32:
4180b57cec5SDimitry Andric return ::GetSegmentAndOffset<LabelSym>(sym);
4190b57cec5SDimitry Andric break;
4200b57cec5SDimitry Andric case S_CALLSITEINFO:
4210b57cec5SDimitry Andric return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
4220b57cec5SDimitry Andric break;
4230b57cec5SDimitry Andric case S_HEAPALLOCSITE:
4240b57cec5SDimitry Andric return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
4250b57cec5SDimitry Andric break;
4260b57cec5SDimitry Andric case S_LDATA32:
4270b57cec5SDimitry Andric case S_GDATA32:
4280b57cec5SDimitry Andric case S_LMANDATA:
4290b57cec5SDimitry Andric case S_GMANDATA:
4300b57cec5SDimitry Andric return ::GetSegmentAndOffset<DataSym>(sym);
4310b57cec5SDimitry Andric break;
4320b57cec5SDimitry Andric case S_LTHREAD32:
4330b57cec5SDimitry Andric case S_GTHREAD32:
4340b57cec5SDimitry Andric return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
4350b57cec5SDimitry Andric break;
4360b57cec5SDimitry Andric default:
4370b57cec5SDimitry Andric lldbassert(false && "Record does not have a segment/offset!");
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric return {0, 0};
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric
4420b57cec5SDimitry Andric template <typename RecordT>
GetSegmentOffsetAndLength(const CVSymbol & sym)4430b57cec5SDimitry Andric SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
4440b57cec5SDimitry Andric RecordT record = createRecord<RecordT>(sym);
4450b57cec5SDimitry Andric return {record.Segment, record.CodeOffset, record.CodeSize};
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andric template <>
4490b57cec5SDimitry Andric SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)4500b57cec5SDimitry Andric GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
4510b57cec5SDimitry Andric TrampolineSym record = createRecord<TrampolineSym>(sym);
4520b57cec5SDimitry Andric return {record.ThunkSection, record.ThunkOffset, record.Size};
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric
4550b57cec5SDimitry Andric template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)4560b57cec5SDimitry Andric SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
4570b57cec5SDimitry Andric Thunk32Sym record = createRecord<Thunk32Sym>(sym);
4580b57cec5SDimitry Andric return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric
4610b57cec5SDimitry Andric template <>
4620b57cec5SDimitry Andric SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)4630b57cec5SDimitry Andric GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
4640b57cec5SDimitry Andric CoffGroupSym record = createRecord<CoffGroupSym>(sym);
4650b57cec5SDimitry Andric return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric SegmentOffsetLength
GetSegmentOffsetAndLength(const CVSymbol & sym)4690b57cec5SDimitry Andric lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
4700b57cec5SDimitry Andric switch (sym.kind()) {
4710b57cec5SDimitry Andric case S_GPROC32:
4720b57cec5SDimitry Andric case S_LPROC32:
4730b57cec5SDimitry Andric case S_GPROC32_ID:
4740b57cec5SDimitry Andric case S_LPROC32_ID:
4750b57cec5SDimitry Andric case S_LPROC32_DPC:
4760b57cec5SDimitry Andric case S_LPROC32_DPC_ID:
4770b57cec5SDimitry Andric return ::GetSegmentOffsetAndLength<ProcSym>(sym);
4780b57cec5SDimitry Andric case S_THUNK32:
4790b57cec5SDimitry Andric return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
4800b57cec5SDimitry Andric break;
4810b57cec5SDimitry Andric case S_TRAMPOLINE:
4820b57cec5SDimitry Andric return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
4830b57cec5SDimitry Andric break;
4840b57cec5SDimitry Andric case S_COFFGROUP:
4850b57cec5SDimitry Andric return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
4860b57cec5SDimitry Andric break;
4870b57cec5SDimitry Andric case S_BLOCK32:
4880b57cec5SDimitry Andric return ::GetSegmentOffsetAndLength<BlockSym>(sym);
4890b57cec5SDimitry Andric break;
4900b57cec5SDimitry Andric default:
4910b57cec5SDimitry Andric lldbassert(false && "Record does not have a segment/offset/length triple!");
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric return {0, 0, 0};
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric
IsForwardRefUdt(CVType cvt)4960b57cec5SDimitry Andric bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
4970b57cec5SDimitry Andric ClassRecord cr;
4980b57cec5SDimitry Andric UnionRecord ur;
4990b57cec5SDimitry Andric EnumRecord er;
5000b57cec5SDimitry Andric switch (cvt.kind()) {
5010b57cec5SDimitry Andric case LF_CLASS:
5020b57cec5SDimitry Andric case LF_STRUCTURE:
5030b57cec5SDimitry Andric case LF_INTERFACE:
5040b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
5050b57cec5SDimitry Andric return cr.isForwardRef();
5060b57cec5SDimitry Andric case LF_UNION:
5070b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
5080b57cec5SDimitry Andric return ur.isForwardRef();
5090b57cec5SDimitry Andric case LF_ENUM:
5100b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
5110b57cec5SDimitry Andric return er.isForwardRef();
5120b57cec5SDimitry Andric default:
5130b57cec5SDimitry Andric return false;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric
IsTagRecord(llvm::codeview::CVType cvt)5170b57cec5SDimitry Andric bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
5180b57cec5SDimitry Andric switch (cvt.kind()) {
5190b57cec5SDimitry Andric case LF_CLASS:
5200b57cec5SDimitry Andric case LF_STRUCTURE:
5210b57cec5SDimitry Andric case LF_UNION:
5220b57cec5SDimitry Andric case LF_ENUM:
5230b57cec5SDimitry Andric return true;
5240b57cec5SDimitry Andric default:
5250b57cec5SDimitry Andric return false;
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric
IsClassStructUnion(llvm::codeview::CVType cvt)5290b57cec5SDimitry Andric bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
5300b57cec5SDimitry Andric switch (cvt.kind()) {
5310b57cec5SDimitry Andric case LF_CLASS:
5320b57cec5SDimitry Andric case LF_STRUCTURE:
5330b57cec5SDimitry Andric case LF_UNION:
5340b57cec5SDimitry Andric return true;
5350b57cec5SDimitry Andric default:
5360b57cec5SDimitry Andric return false;
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)5400b57cec5SDimitry Andric bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
5410b57cec5SDimitry Andric TpiStream &tpi) {
5420b57cec5SDimitry Andric if (id.is_ipi || id.index.isSimple())
5430b57cec5SDimitry Andric return false;
5440b57cec5SDimitry Andric return IsForwardRefUdt(tpi.getType(id.index));
5450b57cec5SDimitry Andric }
5460b57cec5SDimitry Andric
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)5470b57cec5SDimitry Andric bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
5480b57cec5SDimitry Andric if (id.is_ipi || id.index.isSimple())
5490b57cec5SDimitry Andric return false;
5500b57cec5SDimitry Andric return IsTagRecord(tpi.getType(id.index));
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andric lldb::AccessType
TranslateMemberAccess(MemberAccess access)5540b57cec5SDimitry Andric lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
5550b57cec5SDimitry Andric switch (access) {
5560b57cec5SDimitry Andric case MemberAccess::Private:
5570b57cec5SDimitry Andric return lldb::eAccessPrivate;
5580b57cec5SDimitry Andric case MemberAccess::Protected:
5590b57cec5SDimitry Andric return lldb::eAccessProtected;
5600b57cec5SDimitry Andric case MemberAccess::Public:
5610b57cec5SDimitry Andric return lldb::eAccessPublic;
5620b57cec5SDimitry Andric case MemberAccess::None:
5630b57cec5SDimitry Andric return lldb::eAccessNone;
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric llvm_unreachable("unreachable");
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric
GetFieldListIndex(CVType cvt)5680b57cec5SDimitry Andric TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
5690b57cec5SDimitry Andric switch (cvt.kind()) {
5700b57cec5SDimitry Andric case LF_CLASS:
5710b57cec5SDimitry Andric case LF_STRUCTURE:
5720b57cec5SDimitry Andric case LF_INTERFACE: {
5730b57cec5SDimitry Andric ClassRecord cr;
5740b57cec5SDimitry Andric cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
5750b57cec5SDimitry Andric return cr.FieldList;
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric case LF_UNION: {
5780b57cec5SDimitry Andric UnionRecord ur;
5790b57cec5SDimitry Andric cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
5800b57cec5SDimitry Andric return ur.FieldList;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric case LF_ENUM: {
5830b57cec5SDimitry Andric EnumRecord er;
5840b57cec5SDimitry Andric cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
5850b57cec5SDimitry Andric return er.FieldList;
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric default:
5880b57cec5SDimitry Andric llvm_unreachable("Unreachable!");
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric
LookThroughModifierRecord(CVType modifier)5920b57cec5SDimitry Andric TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
5930b57cec5SDimitry Andric lldbassert(modifier.kind() == LF_MODIFIER);
5940b57cec5SDimitry Andric ModifierRecord mr;
5950b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
5960b57cec5SDimitry Andric return mr.ModifiedType;
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric
DropNameScope(llvm::StringRef name)5990b57cec5SDimitry Andric llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
6000b57cec5SDimitry Andric return MSVCUndecoratedNameParser::DropScope(name);
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric
GetVariableNameInfo(CVSymbol sym)6030b57cec5SDimitry Andric VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
604972a253aSDimitry Andric VariableInfo result = {};
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric if (sym.kind() == S_REGREL32) {
6070b57cec5SDimitry Andric RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
6080b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
6090b57cec5SDimitry Andric result.type = reg.Type;
6100b57cec5SDimitry Andric result.name = reg.Name;
6110b57cec5SDimitry Andric return result;
6120b57cec5SDimitry Andric }
6130b57cec5SDimitry Andric
6140b57cec5SDimitry Andric if (sym.kind() == S_REGISTER) {
6150b57cec5SDimitry Andric RegisterSym reg(SymbolRecordKind::RegisterSym);
6160b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
6170b57cec5SDimitry Andric result.type = reg.Index;
6180b57cec5SDimitry Andric result.name = reg.Name;
6190b57cec5SDimitry Andric return result;
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric
6220b57cec5SDimitry Andric if (sym.kind() == S_LOCAL) {
6230b57cec5SDimitry Andric LocalSym local(SymbolRecordKind::LocalSym);
6240b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
6250b57cec5SDimitry Andric result.type = local.Type;
6260b57cec5SDimitry Andric result.name = local.Name;
62781ad6265SDimitry Andric result.is_param =
62881ad6265SDimitry Andric ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
6290b57cec5SDimitry Andric return result;
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric
6320b57cec5SDimitry Andric if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
6330b57cec5SDimitry Andric DataSym data(SymbolRecordKind::DataSym);
6340b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
6350b57cec5SDimitry Andric result.type = data.Type;
6360b57cec5SDimitry Andric result.name = data.Name;
6370b57cec5SDimitry Andric return result;
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric
6400b57cec5SDimitry Andric if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
6410b57cec5SDimitry Andric ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
6420b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
6430b57cec5SDimitry Andric result.type = data.Type;
6440b57cec5SDimitry Andric result.name = data.Name;
6450b57cec5SDimitry Andric return result;
6460b57cec5SDimitry Andric }
6470b57cec5SDimitry Andric
6480b57cec5SDimitry Andric if (sym.kind() == S_CONSTANT) {
6490b57cec5SDimitry Andric ConstantSym constant(SymbolRecordKind::ConstantSym);
6500b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
6510b57cec5SDimitry Andric result.type = constant.Type;
6520b57cec5SDimitry Andric result.name = constant.Name;
6530b57cec5SDimitry Andric return result;
6540b57cec5SDimitry Andric }
6550b57cec5SDimitry Andric
6560b57cec5SDimitry Andric lldbassert(false && "Invalid variable record kind!");
6570b57cec5SDimitry Andric return {};
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric
6600b57cec5SDimitry Andric static llvm::FixedStreamArray<FrameData>::Iterator
GetCorrespondingFrameData(lldb::addr_t load_addr,const DebugFrameDataSubsectionRef & fpo_data,const Variable::RangeList & ranges)6610b57cec5SDimitry Andric GetCorrespondingFrameData(lldb::addr_t load_addr,
6620b57cec5SDimitry Andric const DebugFrameDataSubsectionRef &fpo_data,
6630b57cec5SDimitry Andric const Variable::RangeList &ranges) {
6640b57cec5SDimitry Andric lldbassert(!ranges.IsEmpty());
6650b57cec5SDimitry Andric
6660b57cec5SDimitry Andric // assume that all variable ranges correspond to one frame data
6670b57cec5SDimitry Andric using RangeListEntry = Variable::RangeList::Entry;
6680b57cec5SDimitry Andric const RangeListEntry &range = ranges.GetEntryRef(0);
6690b57cec5SDimitry Andric
6700b57cec5SDimitry Andric auto it = fpo_data.begin();
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric // start by searching first frame data range containing variable range
6730b57cec5SDimitry Andric for (; it != fpo_data.end(); ++it) {
6740b57cec5SDimitry Andric RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
6750b57cec5SDimitry Andric
6760b57cec5SDimitry Andric if (fd_range.Contains(range)) {
6770b57cec5SDimitry Andric break;
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric
6810b57cec5SDimitry Andric // then first most nested entry that still contains variable range
6820b57cec5SDimitry Andric auto found = it;
6830b57cec5SDimitry Andric for (; it != fpo_data.end(); ++it) {
6840b57cec5SDimitry Andric RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
6850b57cec5SDimitry Andric
6860b57cec5SDimitry Andric if (!fd_range.Contains(range)) {
6870b57cec5SDimitry Andric break;
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric found = it;
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric
6920b57cec5SDimitry Andric return found;
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric
GetFrameDataProgram(PdbIndex & index,const Variable::RangeList & ranges,llvm::StringRef & out_program)6950b57cec5SDimitry Andric static bool GetFrameDataProgram(PdbIndex &index,
6960b57cec5SDimitry Andric const Variable::RangeList &ranges,
6970b57cec5SDimitry Andric llvm::StringRef &out_program) {
6980b57cec5SDimitry Andric const DebugFrameDataSubsectionRef &new_fpo_data =
6990b57cec5SDimitry Andric index.dbi().getNewFpoRecords();
7000b57cec5SDimitry Andric
7010b57cec5SDimitry Andric auto frame_data_it =
7020b57cec5SDimitry Andric GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
7030b57cec5SDimitry Andric if (frame_data_it == new_fpo_data.end())
7040b57cec5SDimitry Andric return false;
7050b57cec5SDimitry Andric
706*06c3fb27SDimitry Andric auto strings = index.pdb().getStringTable();
707*06c3fb27SDimitry Andric if (!strings) {
708*06c3fb27SDimitry Andric consumeError(strings.takeError());
709*06c3fb27SDimitry Andric return false;
710*06c3fb27SDimitry Andric }
711*06c3fb27SDimitry Andric out_program = cantFail(strings->getStringForID(frame_data_it->FrameFunc));
7120b57cec5SDimitry Andric return true;
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric
GetBaseFrameRegister(PdbIndex & index,PdbCompilandSymId frame_proc_id,bool is_parameter)7150b57cec5SDimitry Andric static RegisterId GetBaseFrameRegister(PdbIndex &index,
7160b57cec5SDimitry Andric PdbCompilandSymId frame_proc_id,
7170b57cec5SDimitry Andric bool is_parameter) {
7180b57cec5SDimitry Andric CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
71981ad6265SDimitry Andric if (frame_proc_cvs.kind() != S_FRAMEPROC)
72081ad6265SDimitry Andric return RegisterId::NONE;
7210b57cec5SDimitry Andric
7220b57cec5SDimitry Andric FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
7230b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
7240b57cec5SDimitry Andric frame_proc));
7250b57cec5SDimitry Andric
7260b57cec5SDimitry Andric CPUType cpu_type = index.compilands()
7270b57cec5SDimitry Andric .GetCompiland(frame_proc_id.modi)
7280b57cec5SDimitry Andric ->m_compile_opts->Machine;
7290b57cec5SDimitry Andric
7300b57cec5SDimitry Andric return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
7310b57cec5SDimitry Andric : frame_proc.getLocalFramePtrReg(cpu_type);
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,Block & func_block,lldb::ModuleSP module)7340b57cec5SDimitry Andric VariableInfo lldb_private::npdb::GetVariableLocationInfo(
735753f127fSDimitry Andric PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
7360b57cec5SDimitry Andric lldb::ModuleSP module) {
7370b57cec5SDimitry Andric
7380b57cec5SDimitry Andric CVSymbol sym = index.ReadSymbolRecord(var_id);
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andric VariableInfo result = GetVariableNameInfo(sym);
7410b57cec5SDimitry Andric
7420b57cec5SDimitry Andric if (sym.kind() == S_REGREL32) {
7430b57cec5SDimitry Andric RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
7440b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
745bdd1243dSDimitry Andric result.location = DWARFExpressionList(
746bdd1243dSDimitry Andric module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
747bdd1243dSDimitry Andric nullptr);
7480b57cec5SDimitry Andric return result;
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric
7510b57cec5SDimitry Andric if (sym.kind() == S_REGISTER) {
7520b57cec5SDimitry Andric RegisterSym reg(SymbolRecordKind::RegisterSym);
7530b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
754bdd1243dSDimitry Andric result.location = DWARFExpressionList(
755bdd1243dSDimitry Andric module, MakeEnregisteredLocationExpression(reg.Register, module),
756bdd1243dSDimitry Andric nullptr);
7570b57cec5SDimitry Andric return result;
7580b57cec5SDimitry Andric }
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andric if (sym.kind() == S_LOCAL) {
7610b57cec5SDimitry Andric LocalSym local(SymbolRecordKind::LocalSym);
762bdd1243dSDimitry Andric if (llvm::Error error =
763bdd1243dSDimitry Andric SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {
764bdd1243dSDimitry Andric llvm::consumeError(std::move(error));
765bdd1243dSDimitry Andric return result;
766bdd1243dSDimitry Andric }
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric PdbCompilandSymId loc_specifier_id(var_id.modi,
7690b57cec5SDimitry Andric var_id.offset + sym.RecordData.size());
770bdd1243dSDimitry Andric CVSymbol loc_specifier_cvs;
771bdd1243dSDimitry Andric // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
772bdd1243dSDimitry Andric RegisterId base_reg = RegisterId::NONE;
773bdd1243dSDimitry Andric size_t type_size = GetSizeOfType(result.type, index.tpi());
774bdd1243dSDimitry Andric // A map from offset of a field in parent to size of the field.
775bdd1243dSDimitry Andric std::map<uint64_t, size_t> offset_to_size;
776bdd1243dSDimitry Andric
777bdd1243dSDimitry Andric // When overlaps happens, always prefer the one that doesn't split the value
778bdd1243dSDimitry Andric // into multiple locations and the location parsed first is perfered.
779bdd1243dSDimitry Andric RangeMap location_map;
780bdd1243dSDimitry Andric
781bdd1243dSDimitry Andric // Iterate through all location records after S_LOCAL. They describe the
782bdd1243dSDimitry Andric // value of this variable at different locations.
783bdd1243dSDimitry Andric bool finished = false;
784bdd1243dSDimitry Andric while (!finished) {
785bdd1243dSDimitry Andric loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
78681ad6265SDimitry Andric switch (loc_specifier_cvs.kind()) {
78781ad6265SDimitry Andric case S_DEFRANGE_FRAMEPOINTER_REL: {
7880b57cec5SDimitry Andric DefRangeFramePointerRelSym loc(
7890b57cec5SDimitry Andric SymbolRecordKind::DefRangeFramePointerRelSym);
790bdd1243dSDimitry Andric if (llvm::Error error =
791bdd1243dSDimitry Andric SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
792bdd1243dSDimitry Andric loc_specifier_cvs, loc)) {
793bdd1243dSDimitry Andric llvm::consumeError(std::move(error));
794bdd1243dSDimitry Andric return result;
795bdd1243dSDimitry Andric }
796bdd1243dSDimitry Andric Variable::RangeList raw_ranges =
797bdd1243dSDimitry Andric MakeRangeList(index, loc.Range, loc.Gaps);
798bdd1243dSDimitry Andric if (base_reg == RegisterId::NONE) {
7990b57cec5SDimitry Andric PdbCompilandSymId func_scope_id =
800753f127fSDimitry Andric PdbSymUid(func_block.GetID()).asCompilandSym();
8010b57cec5SDimitry Andric CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
8020b57cec5SDimitry Andric lldbassert(func_block_cvs.kind() == S_GPROC32 ||
8030b57cec5SDimitry Andric func_block_cvs.kind() == S_LPROC32);
804bdd1243dSDimitry Andric PdbCompilandSymId frame_proc_id(func_scope_id.modi,
805bdd1243dSDimitry Andric func_scope_id.offset +
806bdd1243dSDimitry Andric func_block_cvs.length());
807bdd1243dSDimitry Andric base_reg =
80881ad6265SDimitry Andric GetBaseFrameRegister(index, frame_proc_id, result.is_param);
80981ad6265SDimitry Andric if (base_reg == RegisterId::NONE)
81081ad6265SDimitry Andric break;
811bdd1243dSDimitry Andric }
812bdd1243dSDimitry Andric DWARFExpression expr;
8130b57cec5SDimitry Andric if (base_reg == RegisterId::VFRAME) {
8140b57cec5SDimitry Andric llvm::StringRef program;
815bdd1243dSDimitry Andric if (GetFrameDataProgram(index, raw_ranges, program))
816bdd1243dSDimitry Andric expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
817bdd1243dSDimitry Andric module);
818bdd1243dSDimitry Andric else {
8190b57cec5SDimitry Andric // invalid variable
8200b57cec5SDimitry Andric }
821bdd1243dSDimitry Andric } else
822bdd1243dSDimitry Andric expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
823bdd1243dSDimitry Andric AddDwarfRange(location_map, expr, raw_ranges);
82481ad6265SDimitry Andric break;
82581ad6265SDimitry Andric }
82681ad6265SDimitry Andric case S_DEFRANGE_REGISTER: {
82781ad6265SDimitry Andric DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
828bdd1243dSDimitry Andric if (llvm::Error error =
829bdd1243dSDimitry Andric SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
830bdd1243dSDimitry Andric loc_specifier_cvs, loc)) {
831bdd1243dSDimitry Andric llvm::consumeError(std::move(error));
832bdd1243dSDimitry Andric return result;
833bdd1243dSDimitry Andric }
834bdd1243dSDimitry Andric RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
835bdd1243dSDimitry Andric Variable::RangeList raw_ranges =
836bdd1243dSDimitry Andric MakeRangeList(index, loc.Range, loc.Gaps);
837bdd1243dSDimitry Andric DWARFExpression expr =
838bdd1243dSDimitry Andric MakeEnregisteredLocationExpression(reg_id, module);
839bdd1243dSDimitry Andric AddDwarfRange(location_map, expr, raw_ranges);
840bdd1243dSDimitry Andric break;
841bdd1243dSDimitry Andric }
842bdd1243dSDimitry Andric case S_DEFRANGE_REGISTER_REL: {
843bdd1243dSDimitry Andric DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
844bdd1243dSDimitry Andric if (llvm::Error error =
845bdd1243dSDimitry Andric SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
846bdd1243dSDimitry Andric loc_specifier_cvs, loc)) {
847bdd1243dSDimitry Andric llvm::consumeError(std::move(error));
848bdd1243dSDimitry Andric return result;
849bdd1243dSDimitry Andric }
850bdd1243dSDimitry Andric Variable::RangeList raw_ranges =
851bdd1243dSDimitry Andric MakeRangeList(index, loc.Range, loc.Gaps);
852bdd1243dSDimitry Andric RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
853bdd1243dSDimitry Andric DWARFExpression expr;
854bdd1243dSDimitry Andric if (reg_id == RegisterId::VFRAME) {
855bdd1243dSDimitry Andric llvm::StringRef program;
856bdd1243dSDimitry Andric if (GetFrameDataProgram(index, raw_ranges, program))
857bdd1243dSDimitry Andric expr = MakeVFrameRelLocationExpression(
858bdd1243dSDimitry Andric program, loc.Hdr.BasePointerOffset, module);
859bdd1243dSDimitry Andric else {
860bdd1243dSDimitry Andric // invalid variable
861bdd1243dSDimitry Andric }
862bdd1243dSDimitry Andric } else {
863bdd1243dSDimitry Andric expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,
864bdd1243dSDimitry Andric module);
865bdd1243dSDimitry Andric }
866bdd1243dSDimitry Andric // FIXME: If it's UDT, we need to know the size of the value in byte.
867bdd1243dSDimitry Andric if (!loc.hasSpilledUDTMember())
868bdd1243dSDimitry Andric AddDwarfRange(location_map, expr, raw_ranges);
86981ad6265SDimitry Andric break;
87081ad6265SDimitry Andric }
87181ad6265SDimitry Andric case S_DEFRANGE_SUBFIELD_REGISTER: {
87281ad6265SDimitry Andric DefRangeSubfieldRegisterSym loc(
87381ad6265SDimitry Andric SymbolRecordKind::DefRangeSubfieldRegisterSym);
874bdd1243dSDimitry Andric if (llvm::Error error =
875bdd1243dSDimitry Andric SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
876bdd1243dSDimitry Andric loc_specifier_cvs, loc)) {
877bdd1243dSDimitry Andric llvm::consumeError(std::move(error));
87881ad6265SDimitry Andric return result;
87981ad6265SDimitry Andric }
880bdd1243dSDimitry Andric
881bdd1243dSDimitry Andric Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
882bdd1243dSDimitry Andric uint32_t reg_size =
883bdd1243dSDimitry Andric GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);
884bdd1243dSDimitry Andric if (reg_size == 0)
885bdd1243dSDimitry Andric break;
886bdd1243dSDimitry Andric offset_to_size[loc.Hdr.OffsetInParent] = reg_size;
887bdd1243dSDimitry Andric AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,
888bdd1243dSDimitry Andric {loc.Hdr.Register, 0, true}, ranges);
889bdd1243dSDimitry Andric break;
89081ad6265SDimitry Andric }
891bdd1243dSDimitry Andric // FIXME: Handle other kinds. LLVM only generates the 4 types of records
892bdd1243dSDimitry Andric // above. MSVC generates other location types.
893bdd1243dSDimitry Andric case S_DEFRANGE:
894bdd1243dSDimitry Andric case S_DEFRANGE_SUBFIELD:
895bdd1243dSDimitry Andric case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
896bdd1243dSDimitry Andric break;
897bdd1243dSDimitry Andric default:
898bdd1243dSDimitry Andric finished = true;
899bdd1243dSDimitry Andric break;
90081ad6265SDimitry Andric }
90181ad6265SDimitry Andric loc_specifier_id = PdbCompilandSymId(
90281ad6265SDimitry Andric loc_specifier_id.modi,
90381ad6265SDimitry Andric loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
90481ad6265SDimitry Andric }
905bdd1243dSDimitry Andric for (const auto &entry : location_map) {
906bdd1243dSDimitry Andric DWARFExpression dwarf_expr =
907bdd1243dSDimitry Andric entry.data.is_dwarf ? entry.data.expr
908bdd1243dSDimitry Andric : MakeEnregisteredLocationExpressionForComposite(
909bdd1243dSDimitry Andric entry.data.offset_to_location,
910bdd1243dSDimitry Andric offset_to_size, type_size, module);
911bdd1243dSDimitry Andric
912bdd1243dSDimitry Andric result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
913bdd1243dSDimitry Andric dwarf_expr);
91481ad6265SDimitry Andric }
9150b57cec5SDimitry Andric return result;
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric llvm_unreachable("Symbol is not a local variable!");
9180b57cec5SDimitry Andric return result;
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric
9210b57cec5SDimitry Andric lldb::BasicType
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)9220b57cec5SDimitry Andric lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
9230b57cec5SDimitry Andric switch (kind) {
9240b57cec5SDimitry Andric case SimpleTypeKind::Boolean128:
9250b57cec5SDimitry Andric case SimpleTypeKind::Boolean16:
9260b57cec5SDimitry Andric case SimpleTypeKind::Boolean32:
9270b57cec5SDimitry Andric case SimpleTypeKind::Boolean64:
9280b57cec5SDimitry Andric case SimpleTypeKind::Boolean8:
9290b57cec5SDimitry Andric return lldb::eBasicTypeBool;
9300b57cec5SDimitry Andric case SimpleTypeKind::Byte:
9310b57cec5SDimitry Andric case SimpleTypeKind::UnsignedCharacter:
9320b57cec5SDimitry Andric return lldb::eBasicTypeUnsignedChar;
9330b57cec5SDimitry Andric case SimpleTypeKind::NarrowCharacter:
9340b57cec5SDimitry Andric return lldb::eBasicTypeChar;
9350b57cec5SDimitry Andric case SimpleTypeKind::SignedCharacter:
9360b57cec5SDimitry Andric case SimpleTypeKind::SByte:
9370b57cec5SDimitry Andric return lldb::eBasicTypeSignedChar;
9380b57cec5SDimitry Andric case SimpleTypeKind::Character16:
9390b57cec5SDimitry Andric return lldb::eBasicTypeChar16;
9400b57cec5SDimitry Andric case SimpleTypeKind::Character32:
9410b57cec5SDimitry Andric return lldb::eBasicTypeChar32;
94281ad6265SDimitry Andric case SimpleTypeKind::Character8:
94381ad6265SDimitry Andric return lldb::eBasicTypeChar8;
9440b57cec5SDimitry Andric case SimpleTypeKind::Complex80:
9450b57cec5SDimitry Andric return lldb::eBasicTypeLongDoubleComplex;
9460b57cec5SDimitry Andric case SimpleTypeKind::Complex64:
9470b57cec5SDimitry Andric return lldb::eBasicTypeDoubleComplex;
9480b57cec5SDimitry Andric case SimpleTypeKind::Complex32:
9490b57cec5SDimitry Andric return lldb::eBasicTypeFloatComplex;
9500b57cec5SDimitry Andric case SimpleTypeKind::Float128:
9510b57cec5SDimitry Andric case SimpleTypeKind::Float80:
9520b57cec5SDimitry Andric return lldb::eBasicTypeLongDouble;
9530b57cec5SDimitry Andric case SimpleTypeKind::Float64:
9540b57cec5SDimitry Andric return lldb::eBasicTypeDouble;
9550b57cec5SDimitry Andric case SimpleTypeKind::Float32:
9560b57cec5SDimitry Andric return lldb::eBasicTypeFloat;
9570b57cec5SDimitry Andric case SimpleTypeKind::Float16:
9580b57cec5SDimitry Andric return lldb::eBasicTypeHalf;
9590b57cec5SDimitry Andric case SimpleTypeKind::Int128:
9600b57cec5SDimitry Andric return lldb::eBasicTypeInt128;
9610b57cec5SDimitry Andric case SimpleTypeKind::Int64:
9620b57cec5SDimitry Andric case SimpleTypeKind::Int64Quad:
9630b57cec5SDimitry Andric return lldb::eBasicTypeLongLong;
9640b57cec5SDimitry Andric case SimpleTypeKind::Int32:
9650b57cec5SDimitry Andric return lldb::eBasicTypeInt;
9660b57cec5SDimitry Andric case SimpleTypeKind::Int16:
9670b57cec5SDimitry Andric case SimpleTypeKind::Int16Short:
9680b57cec5SDimitry Andric return lldb::eBasicTypeShort;
9690b57cec5SDimitry Andric case SimpleTypeKind::UInt128:
9700b57cec5SDimitry Andric return lldb::eBasicTypeUnsignedInt128;
9710b57cec5SDimitry Andric case SimpleTypeKind::UInt64:
9720b57cec5SDimitry Andric case SimpleTypeKind::UInt64Quad:
9730b57cec5SDimitry Andric return lldb::eBasicTypeUnsignedLongLong;
9740b57cec5SDimitry Andric case SimpleTypeKind::HResult:
9750b57cec5SDimitry Andric case SimpleTypeKind::UInt32:
9760b57cec5SDimitry Andric return lldb::eBasicTypeUnsignedInt;
9770b57cec5SDimitry Andric case SimpleTypeKind::UInt16:
9780b57cec5SDimitry Andric case SimpleTypeKind::UInt16Short:
9790b57cec5SDimitry Andric return lldb::eBasicTypeUnsignedShort;
9800b57cec5SDimitry Andric case SimpleTypeKind::Int32Long:
9810b57cec5SDimitry Andric return lldb::eBasicTypeLong;
9820b57cec5SDimitry Andric case SimpleTypeKind::UInt32Long:
9830b57cec5SDimitry Andric return lldb::eBasicTypeUnsignedLong;
9840b57cec5SDimitry Andric case SimpleTypeKind::Void:
9850b57cec5SDimitry Andric return lldb::eBasicTypeVoid;
9860b57cec5SDimitry Andric case SimpleTypeKind::WideCharacter:
9870b57cec5SDimitry Andric return lldb::eBasicTypeWChar;
9880b57cec5SDimitry Andric default:
9890b57cec5SDimitry Andric return lldb::eBasicTypeInvalid;
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric
GetTypeSizeForSimpleKind(SimpleTypeKind kind)9930b57cec5SDimitry Andric size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
9940b57cec5SDimitry Andric switch (kind) {
9950b57cec5SDimitry Andric case SimpleTypeKind::Boolean128:
9960b57cec5SDimitry Andric case SimpleTypeKind::Int128:
9970b57cec5SDimitry Andric case SimpleTypeKind::UInt128:
9980b57cec5SDimitry Andric case SimpleTypeKind::Float128:
9990b57cec5SDimitry Andric return 16;
10000b57cec5SDimitry Andric case SimpleTypeKind::Complex80:
10010b57cec5SDimitry Andric case SimpleTypeKind::Float80:
10020b57cec5SDimitry Andric return 10;
10030b57cec5SDimitry Andric case SimpleTypeKind::Boolean64:
10040b57cec5SDimitry Andric case SimpleTypeKind::Complex64:
10050b57cec5SDimitry Andric case SimpleTypeKind::UInt64:
10060b57cec5SDimitry Andric case SimpleTypeKind::UInt64Quad:
10070b57cec5SDimitry Andric case SimpleTypeKind::Float64:
10080b57cec5SDimitry Andric case SimpleTypeKind::Int64:
10090b57cec5SDimitry Andric case SimpleTypeKind::Int64Quad:
10100b57cec5SDimitry Andric return 8;
10110b57cec5SDimitry Andric case SimpleTypeKind::Boolean32:
10120b57cec5SDimitry Andric case SimpleTypeKind::Character32:
10130b57cec5SDimitry Andric case SimpleTypeKind::Complex32:
10140b57cec5SDimitry Andric case SimpleTypeKind::Float32:
10150b57cec5SDimitry Andric case SimpleTypeKind::Int32:
10160b57cec5SDimitry Andric case SimpleTypeKind::Int32Long:
10170b57cec5SDimitry Andric case SimpleTypeKind::UInt32Long:
10180b57cec5SDimitry Andric case SimpleTypeKind::HResult:
10190b57cec5SDimitry Andric case SimpleTypeKind::UInt32:
10200b57cec5SDimitry Andric return 4;
10210b57cec5SDimitry Andric case SimpleTypeKind::Boolean16:
10220b57cec5SDimitry Andric case SimpleTypeKind::Character16:
10230b57cec5SDimitry Andric case SimpleTypeKind::Float16:
10240b57cec5SDimitry Andric case SimpleTypeKind::Int16:
10250b57cec5SDimitry Andric case SimpleTypeKind::Int16Short:
10260b57cec5SDimitry Andric case SimpleTypeKind::UInt16:
10270b57cec5SDimitry Andric case SimpleTypeKind::UInt16Short:
10280b57cec5SDimitry Andric case SimpleTypeKind::WideCharacter:
10290b57cec5SDimitry Andric return 2;
10300b57cec5SDimitry Andric case SimpleTypeKind::Boolean8:
10310b57cec5SDimitry Andric case SimpleTypeKind::Byte:
10320b57cec5SDimitry Andric case SimpleTypeKind::UnsignedCharacter:
10330b57cec5SDimitry Andric case SimpleTypeKind::NarrowCharacter:
10340b57cec5SDimitry Andric case SimpleTypeKind::SignedCharacter:
10350b57cec5SDimitry Andric case SimpleTypeKind::SByte:
103681ad6265SDimitry Andric case SimpleTypeKind::Character8:
10370b57cec5SDimitry Andric return 1;
10380b57cec5SDimitry Andric case SimpleTypeKind::Void:
10390b57cec5SDimitry Andric default:
10400b57cec5SDimitry Andric return 0;
10410b57cec5SDimitry Andric }
10420b57cec5SDimitry Andric }
10430b57cec5SDimitry Andric
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)10440b57cec5SDimitry Andric PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
10450b57cec5SDimitry Andric TpiStream &tpi) {
10460b57cec5SDimitry Andric if (id.index.isSimple())
10470b57cec5SDimitry Andric return id;
10480b57cec5SDimitry Andric
10490b57cec5SDimitry Andric CVType cvt = tpi.getType(id.index);
10500b57cec5SDimitry Andric
10510b57cec5SDimitry Andric // Only tag records have a best and a worst record.
10520b57cec5SDimitry Andric if (!IsTagRecord(cvt))
10530b57cec5SDimitry Andric return id;
10540b57cec5SDimitry Andric
10550b57cec5SDimitry Andric // Tag records that are not forward decls are full decls, hence they are the
10560b57cec5SDimitry Andric // best.
10570b57cec5SDimitry Andric if (!IsForwardRefUdt(cvt))
10580b57cec5SDimitry Andric return id;
10590b57cec5SDimitry Andric
10600b57cec5SDimitry Andric return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
10610b57cec5SDimitry Andric }
10620b57cec5SDimitry Andric
GetSizeOfTypeInternal(CVType cvt)10630b57cec5SDimitry Andric template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
10640b57cec5SDimitry Andric RecordType record;
10650b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
10660b57cec5SDimitry Andric return record.getSize();
10670b57cec5SDimitry Andric }
10680b57cec5SDimitry Andric
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)10690b57cec5SDimitry Andric size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
10700b57cec5SDimitry Andric llvm::pdb::TpiStream &tpi) {
10710b57cec5SDimitry Andric if (id.index.isSimple()) {
10720b57cec5SDimitry Andric switch (id.index.getSimpleMode()) {
10730b57cec5SDimitry Andric case SimpleTypeMode::Direct:
10740b57cec5SDimitry Andric return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
10750b57cec5SDimitry Andric case SimpleTypeMode::NearPointer32:
10760b57cec5SDimitry Andric case SimpleTypeMode::FarPointer32:
10770b57cec5SDimitry Andric return 4;
10780b57cec5SDimitry Andric case SimpleTypeMode::NearPointer64:
10790b57cec5SDimitry Andric return 8;
10800b57cec5SDimitry Andric case SimpleTypeMode::NearPointer128:
10810b57cec5SDimitry Andric return 16;
10820b57cec5SDimitry Andric default:
10830b57cec5SDimitry Andric break;
10840b57cec5SDimitry Andric }
10850b57cec5SDimitry Andric return 0;
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric
10880b57cec5SDimitry Andric TypeIndex index = id.index;
10890b57cec5SDimitry Andric if (IsForwardRefUdt(index, tpi))
10900b57cec5SDimitry Andric index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
10910b57cec5SDimitry Andric
10920b57cec5SDimitry Andric CVType cvt = tpi.getType(index);
10930b57cec5SDimitry Andric switch (cvt.kind()) {
10940b57cec5SDimitry Andric case LF_MODIFIER:
10950b57cec5SDimitry Andric return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
10960b57cec5SDimitry Andric case LF_ENUM: {
10970b57cec5SDimitry Andric EnumRecord record;
10980b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
10990b57cec5SDimitry Andric return GetSizeOfType({record.UnderlyingType}, tpi);
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric case LF_POINTER:
11020b57cec5SDimitry Andric return GetSizeOfTypeInternal<PointerRecord>(cvt);
11030b57cec5SDimitry Andric case LF_ARRAY:
11040b57cec5SDimitry Andric return GetSizeOfTypeInternal<ArrayRecord>(cvt);
11050b57cec5SDimitry Andric case LF_CLASS:
11060b57cec5SDimitry Andric case LF_STRUCTURE:
11070b57cec5SDimitry Andric case LF_INTERFACE:
11080b57cec5SDimitry Andric return GetSizeOfTypeInternal<ClassRecord>(cvt);
11090b57cec5SDimitry Andric case LF_UNION:
11100b57cec5SDimitry Andric return GetSizeOfTypeInternal<UnionRecord>(cvt);
1111bdd1243dSDimitry Andric case LF_BITFIELD: {
1112bdd1243dSDimitry Andric BitFieldRecord record;
1113bdd1243dSDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));
1114bdd1243dSDimitry Andric return GetSizeOfType({record.Type}, tpi);
1115bdd1243dSDimitry Andric }
11160b57cec5SDimitry Andric default:
11170b57cec5SDimitry Andric break;
11180b57cec5SDimitry Andric }
11190b57cec5SDimitry Andric return 0;
11200b57cec5SDimitry Andric }
1121