45#define DEBUG_TYPE "CodeViewUtilities"
48namespace logicalview {
79#define CV_TYPE(enum, val) {#enum, enum},
80#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
91 auto GetName = [&](
auto Record) {
100 if (RK == TypeRecordKind::Class || RK == TypeRecordKind::Struct)
102 else if (RK == TypeRecordKind::Union)
104 else if (RK == TypeRecordKind::Enum)
114#define DEBUG_TYPE "CodeViewDataVisitor"
117namespace logicalview {
128 using RecordEntry = std::pair<TypeLeafKind, LVElement *>;
129 using RecordTable = std::map<TypeIndex, RecordEntry>;
130 RecordTable RecordFromTypes;
131 RecordTable RecordFromIds;
133 using NameTable = std::map<StringRef, TypeIndex>;
134 NameTable NameFromTypes;
135 NameTable NameFromIds;
138 LVTypeRecords(
LVShared *Shared) : Shared(Shared) {}
147class LVForwardReferences {
149 using ForwardEntry = std::pair<TypeIndex, TypeIndex>;
150 using ForwardTypeNames = std::map<StringRef, ForwardEntry>;
151 ForwardTypeNames ForwardTypesNames;
154 using ForwardType = std::map<TypeIndex, TypeIndex>;
155 ForwardType ForwardTypes;
159 ForwardTypes.emplace(TIForward, TIReference);
163 if (ForwardTypesNames.find(
Name) == ForwardTypesNames.end()) {
164 ForwardTypesNames.emplace(
165 std::piecewise_construct, std::forward_as_tuple(
Name),
169 ForwardTypesNames[
Name].first = TIForward;
170 add(TIForward, ForwardTypesNames[
Name].second);
176 if (ForwardTypesNames.find(
Name) != ForwardTypesNames.end()) {
178 ForwardTypesNames[
Name].second = TIReference;
179 add(ForwardTypesNames[
Name].first, TIReference);
182 ForwardTypesNames.emplace(
183 std::piecewise_construct, std::forward_as_tuple(
Name),
189 LVForwardReferences() =
default;
195 (IsForwardRef) ? add(
Name, TI) : update(
Name, TI);
199 return (ForwardTypes.find(TIForward) != ForwardTypes.end())
200 ? ForwardTypes[TIForward]
205 return (ForwardTypesNames.find(
Name) != ForwardTypesNames.end())
206 ? ForwardTypesNames[
Name].second
219class LVNamespaceDeduction {
222 using Names = std::map<StringRef, LVScope *>;
223 Names NamespaceNames;
225 using LookupSet = std::set<StringRef>;
226 LookupSet DeducedScopes;
227 LookupSet UnresolvedScopes;
228 LookupSet IdentifiedNamespaces;
231 if (NamespaceNames.find(
Name) == NamespaceNames.end())
232 NamespaceNames.emplace(
Name, Namespace);
236 LVNamespaceDeduction(
LVShared *Shared) : Shared(Shared) {}
245 LVScope *Namespace = (NamespaceNames.find(
Name) != NamespaceNames.end())
246 ? NamespaceNames[
Name]
255 if (Components.empty())
258 LVStringRefs::size_type FirstNamespace = 0;
259 LVStringRefs::size_type FirstNonNamespace;
260 for (LVStringRefs::size_type
Index = 0;
Index < Components.size();
262 FirstNonNamespace =
Index;
263 LookupSet::iterator Iter = IdentifiedNamespaces.find(Components[
Index]);
264 if (Iter == IdentifiedNamespaces.end())
268 return std::make_tuple(FirstNamespace, FirstNonNamespace);
273class LVStringRecords {
274 using StringEntry = std::tuple<uint32_t, std::string, LVScopeCompileUnit *>;
275 using StringIds = std::map<TypeIndex, StringEntry>;
279 LVStringRecords() =
default;
283 if (Strings.find(TI) == Strings.end())
285 std::piecewise_construct, std::forward_as_tuple(TI),
286 std::forward_as_tuple(++
Index, std::string(
String),
nullptr));
290 StringIds::iterator Iter = Strings.find(TI);
291 return Iter != Strings.end() ? std::get<1>(Iter->second) :
StringRef{};
295 StringIds::iterator Iter = Strings.find(TI);
296 return Iter != Strings.end() ? std::get<0>(Iter->second) : 0;
339 (StreamIdx ==
StreamTPI) ? RecordFromTypes : RecordFromIds;
340 Target.emplace(std::piecewise_construct, std::forward_as_tuple(TI),
341 std::forward_as_tuple(
Kind, Element));
345 NameTable &
Target = (StreamIdx ==
StreamTPI) ? NameFromTypes : NameFromIds;
351 (StreamIdx ==
StreamTPI) ? RecordFromTypes : RecordFromIds;
354 RecordTable::iterator Iter =
Target.find(TI);
355 if (Iter !=
Target.end()) {
356 Element = Iter->second.second;
357 if (Element || !Create)
364 Element->setOffsetFromTypeIndex();
365 Target[TI].second = Element;
372 NameTable &
Target = (StreamIdx ==
StreamTPI) ? NameFromTypes : NameFromIds;
377void LVStringRecords::addFilenames() {
378 for (StringIds::const_reference Entry : Strings) {
387 for (StringIds::reference Entry : Strings)
388 if (!std::get<2>(Entry.second))
389 std::get<2>(Entry.second) =
Scope;
396 DeducedScopes.insert(InnerComponent);
397 if (OuterComponent.
size())
398 UnresolvedScopes.insert(OuterComponent);
401void LVNamespaceDeduction::init() {
408 for (
const StringRef &Unresolved : UnresolvedScopes) {
410 for (
const StringRef &Component : Components) {
411 LookupSet::iterator Iter = DeducedScopes.find(Component);
412 if (Iter == DeducedScopes.end())
413 IdentifiedNamespaces.insert(Component);
418 auto Print = [&](LookupSet &Container,
const char *Title) {
419 auto Header = [&]() {
429 Print(DeducedScopes,
"Deducted Scopes");
430 Print(UnresolvedScopes,
"Unresolved Scopes");
431 Print(IdentifiedNamespaces,
"Namespaces");
437 for (
const StringRef &Component : Components)
441 if (Components.empty())
447 for (
const StringRef &Component : Components) {
449 Namespace =
find(Component);
453 Namespace = Shared->
Reader->createScopeNamespace();
454 Namespace->
setTag(dwarf::DW_TAG_namespace);
458 add(Component, Namespace);
468 Components.erase(std::remove_if(Components.begin(), Components.end(),
470 LookupSet::iterator Iter =
471 IdentifiedNamespaces.find(Component);
472 return Iter == IdentifiedNamespaces.end();
477 {
dbgs() <<
formatv(
"ScopedName: '{0}'\n", ScopedName.
str().c_str()); });
479 return get(Components);
483#define DEBUG_TYPE "CodeViewTypeVisitor"
504 if (
options().getInternalTag())
509 CurrentTypeIndex = TI;
558 TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::CurrentDirectory];
564 TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile];
576 printTypeIndex(
"TypeIndex", CurrentTypeIndex,
StreamTPI);
594 printTypeIndex(
"TypeIndex", CurrentTypeIndex,
StreamTPI);
595 printTypeIndex(
"FieldListType",
Enum.getFieldList(),
StreamTPI);
607 printTypeIndex(
"TypeIndex", CurrentTypeIndex,
StreamTPI);
608 printTypeIndex(
"Type", Func.getFunctionType(),
StreamTPI);
609 printTypeIndex(
"Parent", Func.getParentScope(),
StreamTPI);
621 printTypeIndex(
"TypeIndex", CurrentTypeIndex,
StreamTPI);
648 printTypeIndex(
"SourceFile",
Line.getSourceFile(),
StreamIPI);
678#define DEBUG_TYPE "CodeViewSymbolVisitor"
687 Reader->printRelocatedField(
Label, CoffSection, RelocOffset,
Offset,
708 return Reader->CVStringTable;
711void LVSymbolVisitor::printLocalVariableAddrRange(
713 DictScope S(W,
"LocalVariableAddrRange");
721void LVSymbolVisitor::printLocalVariableAddrGap(
725 W.
printHex(
"GapStartOffset", Gap.GapStartOffset);
745 if (
options().getInternalTag())
759 IsCompileUnit =
false;
807 if (
options().getGeneralCollectRanges()) {
813 Scope->addObject(LowPC, HighPC);
824 printTypeIndex(
"Type",
Local.Type);
830 Symbol->setName(
Local.Name);
838 Symbol->resetIsVariable();
840 if (
Local.Name.equals(
"this")) {
841 Symbol->setIsParameter();
842 Symbol->setIsArtificial();
845 bool(
Local.Offset > 0) ? Symbol->setIsParameter()
846 : Symbol->setIsVariable();
850 if (Symbol->getIsParameter())
851 Symbol->setTag(dwarf::DW_TAG_formal_parameter);
854 if (Element && Element->getIsScoped()) {
856 LVScope *Parent = Symbol->getFunctionParent();
869 Symbol->setType(Element);
879 printTypeIndex(
"Type",
Local.Type);
885 Symbol->setName(
Local.Name);
888 Symbol->resetIsVariable();
891 if (
Local.Name.equals(
"this")) {
892 Symbol->setIsArtificial();
893 Symbol->setIsParameter();
896 determineSymbolKind(Symbol,
Local.Register);
900 if (Symbol->getIsParameter())
901 Symbol->setTag(dwarf::DW_TAG_formal_parameter);
904 if (Element && Element->getIsScoped()) {
906 LVScope *Parent = Symbol->getFunctionParent();
919 Symbol->setType(Element);
965 Scope->setName(CurrentObjectName);
966 if (
options().getAttributeProducer())
967 Scope->setProducer(Compile2.
Version);
979 CurrentObjectName =
"";
1010 Scope->setName(CurrentObjectName);
1011 if (
options().getAttributeProducer())
1012 Scope->setProducer(Compile3.
Version);
1024 CurrentObjectName =
"";
1032 printTypeIndex(
"Type",
Constant.Type);
1040 Symbol->resetIncludeInPrint();
1058 if (
LVSymbol *Symbol = LocalSymbol) {
1059 Symbol->setHasCodeViewLocation();
1060 LocalSymbol =
nullptr;
1067 Symbol->addLocation(Attr, 0, 0, 0, 0);
1068 Symbol->addLocationOperands(
LVSmall(Attr), Operand1, 0);
1083 printLocalVariableAddrRange(DefRangeFramePointerRel.
Range,
1085 printLocalVariableAddrGap(DefRangeFramePointerRel.
Gaps);
1092 if (
LVSymbol *Symbol = LocalSymbol) {
1093 Symbol->setHasCodeViewLocation();
1094 LocalSymbol =
nullptr;
1106 Symbol->addLocationOperands(
LVSmall(Attr), Operand1, 0);
1125 printLocalVariableAddrRange(DefRangeRegisterRel.
Range,
1127 printLocalVariableAddrGap(DefRangeRegisterRel.
Gaps);
1130 if (
LVSymbol *Symbol = LocalSymbol) {
1131 Symbol->setHasCodeViewLocation();
1132 LocalSymbol =
nullptr;
1145 Symbol->addLocationOperands(
LVSmall(Attr), Operand1, Operand2);
1162 printLocalVariableAddrRange(DefRangeRegister.
Range,
1164 printLocalVariableAddrGap(DefRangeRegister.
Gaps);
1167 if (
LVSymbol *Symbol = LocalSymbol) {
1168 Symbol->setHasCodeViewLocation();
1169 LocalSymbol =
nullptr;
1180 Symbol->addLocationOperands(
LVSmall(Attr), Operand1, 0);
1199 printLocalVariableAddrRange(DefRangeSubfieldRegister.
Range,
1201 printLocalVariableAddrGap(DefRangeSubfieldRegister.
Gaps);
1204 if (
LVSymbol *Symbol = LocalSymbol) {
1205 Symbol->setHasCodeViewLocation();
1206 LocalSymbol =
nullptr;
1218 Symbol->addLocationOperands(
LVSmall(Attr), Operand1, 0);
1234 auto ExpectedProgram = Strings.getString(DefRangeSubfield.
Program);
1235 if (!ExpectedProgram) {
1237 return llvm::make_error<CodeViewError>(
1238 "String table offset outside of bounds of String Table!");
1243 printLocalVariableAddrRange(DefRangeSubfield.
Range,
1245 printLocalVariableAddrGap(DefRangeSubfield.
Gaps);
1248 if (
LVSymbol *Symbol = LocalSymbol) {
1249 Symbol->setHasCodeViewLocation();
1250 LocalSymbol =
nullptr;
1261 Symbol->addLocationOperands(
LVSmall(Attr), Operand1, 0);
1277 auto ExpectedProgram = Strings.getString(DefRange.
Program);
1278 if (!ExpectedProgram) {
1280 return llvm::make_error<CodeViewError>(
1281 "String table offset outside of bounds of String Table!");
1286 printLocalVariableAddrGap(DefRange.
Gaps);
1289 if (
LVSymbol *Symbol = LocalSymbol) {
1290 Symbol->setHasCodeViewLocation();
1291 LocalSymbol =
nullptr;
1302 Symbol->addLocationOperands(
LVSmall(Attr), Operand1, 0);
1322 if (FrameProcedureOptions::MarkedInline ==
1323 (
Flags & FrameProcedureOptions::MarkedInline))
1325 if (FrameProcedureOptions::Inlined ==
1326 (
Flags & FrameProcedureOptions::Inlined))
1344 printTypeIndex(
"Type",
Data.Type);
1354 Symbol->setName(
Data.Name);
1364 Symbol->resetIncludeInPrint();
1371 if (Symbol->getParentScope()->removeElement(Symbol))
1376 if (
Record.kind() == SymbolKind::S_GDATA32)
1377 Symbol->setIsExternal();
1389 LVScope *AbstractFunction = Reader->createScopeFunction();
1390 AbstractFunction->setIsSubprogram();
1391 AbstractFunction->
setTag(dwarf::DW_TAG_subprogram);
1393 AbstractFunction->setIsInlinedAbstract();
1400 CVFunctionType,
InlineSite.Inlinee, AbstractFunction))
1407 InlinedFunction->setName(
Name);
1408 InlinedFunction->setLinkageName(
Name);
1412 AbstractFunction, InlinedFunction,
InlineSite))
1422 printTypeIndex(
"Type",
Local.Type);
1428 Symbol->setName(
Local.Name);
1431 Symbol->resetIsVariable();
1434 if (
bool(
Local.Flags & LocalSymFlags::IsCompilerGenerated) ||
1435 Local.Name.equals(
"this")) {
1436 Symbol->setIsArtificial();
1437 Symbol->setIsParameter();
1439 bool(
Local.Flags & LocalSymFlags::IsParameter) ? Symbol->setIsParameter()
1440 : Symbol->setIsVariable();
1444 if (Symbol->getIsParameter())
1445 Symbol->setTag(dwarf::DW_TAG_formal_parameter);
1448 if (Element && Element->getIsScoped()) {
1450 LVScope *Parent = Symbol->getFunctionParent();
1457 Symbol->setType(Element);
1462 LocalSymbol = Symbol;
1475 CurrentObjectName = ObjName.
Name;
1481 if (InFunctionScope)
1482 return llvm::make_error<CodeViewError>(
"Visiting a ProcSym while inside "
1485 InFunctionScope =
true;
1541 if (
options().getGeneralCollectRanges()) {
1547 Function->addObject(LowPC, HighPC);
1550 if ((
options().getAttributePublics() ||
options().getPrintAnyLine()) &&
1575 std::optional<CVType> CVFunctionType;
1576 auto GetRecordType = [&]() ->
bool {
1577 CVFunctionType = Ids.
tryGetType(TIFunctionType);
1578 if (!CVFunctionType)
1583 if (CVFunctionType->kind() == LF_FUNC_ID)
1587 return (CVFunctionType->kind() == LF_MFUNC_ID);
1591 if (!GetRecordType()) {
1592 CVFunctionType = Types.
tryGetType(TIFunctionType);
1593 if (!CVFunctionType)
1594 return llvm::make_error<CodeViewError>(
"Invalid type index");
1598 *CVFunctionType, TIFunctionType,
Function))
1602 if (
Record.kind() == SymbolKind::S_GPROC32 ||
1603 Record.kind() == SymbolKind::S_GPROC32_ID)
1609 if (DemangledSymbol.find(
"scalar deleting dtor") != std::string::npos) {
1614 if (DemangledSymbol.find(
"dynamic atexit destructor for") !=
1626 InFunctionScope =
false;
1632 if (InFunctionScope)
1633 return llvm::make_error<CodeViewError>(
"Visiting a Thunk32Sym while inside "
1636 InFunctionScope =
true;
1652 printTypeIndex(
"Type",
UDT.Type);
1658 if (
Type->getParentScope()->removeElement(
Type))
1672 Type->resetIncludeInPrint();
1675 if (
UDT.Name.equals(RecordName))
1676 Type->resetIncludeInPrint();
1692#define DEBUG_TYPE "CodeViewLogicalVisitor"
1699 : Reader(Reader), W(W), Input(Input) {
1702 Shared = std::make_shared<LVShared>(Reader,
this);
1708 StreamIdx ==
StreamTPI ? types() : ids());
1721 << Element->
getName() <<
"\n";
1740 << Element->
getName() <<
"\n";
1791 if (Element->getIsFinalized())
1793 Element->setIsFinalized();
1802 LVType *PrevSubrange =
nullptr;
1810 Subrange->setTag(dwarf::DW_TAG_subrange_type);
1820 if (int64_t Count =
Subrange->getCount())
1835 while (CVEntry.
kind() == LF_ARRAY) {
1846 AddSubrangeType(AR);
1847 TIArrayType = TIElementType;
1853 CVType CVElementType =
Types.getType(TIElementType);
1854 if (CVElementType.
kind() == LF_MODIFIER) {
1856 Shared->TypeRecords.find(
StreamTPI, TIElementType);
1869 CVEntry =
Types.getType(TIElementType);
1871 const_cast<CVType &
>(CVEntry), AR)) {
1881 TIArrayType = Shared->ForwardReferences.remap(TIArrayType);
1927 TypeIndex TIName = BI.
getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile];
1948 if (
Class.hasUniqueName())
1953 if (Element->getIsFinalized())
1955 Element->setIsFinalized();
1961 Scope->setName(
Class.getName());
1962 if (
Class.hasUniqueName())
1963 Scope->setLinkageName(
Class.getUniqueName());
1965 if (
Class.isNested()) {
1966 Scope->setIsNested();
1967 createParents(
Class.getName(), Scope);
1970 if (
Class.isScoped())
1971 Scope->setIsScoped();
1975 if (!(
Class.isNested() ||
Class.isScoped())) {
1976 if (
LVScope *Namespace = Shared->NamespaceDeduction.get(
Class.getName()))
1985 TypeIndex ForwardType = Shared->ForwardReferences.find(
Class.getName());
1991 const_cast<CVType &
>(CVReference), ReferenceRecord))
2023 if (Scope->getIsFinalized())
2025 Scope->setIsFinalized();
2029 Scope->setName(
Enum.getName());
2030 if (
Enum.hasUniqueName())
2031 Scope->setLinkageName(
Enum.getUniqueName());
2035 if (
Enum.isNested()) {
2036 Scope->setIsNested();
2037 createParents(
Enum.getName(), Scope);
2040 if (
Enum.isScoped()) {
2041 Scope->setIsScoped();
2042 Scope->setIsEnumClass();
2046 if (!(
Enum.isNested() ||
Enum.isScoped())) {
2047 if (
LVScope *Namespace = Shared->NamespaceDeduction.get(
Enum.getName()))
2073 if (
Error Err = visitFieldListMemberStream(TI, Element,
FieldList.Data))
2099 TypeIndex TIParent = Func.getParentScope();
2100 if (FunctionDcl->getIsInlinedAbstract()) {
2101 FunctionDcl->setName(Func.getName());
2112 TypeIndex TIFunctionType = Func.getFunctionType();
2113 CVType CVFunctionType =
Types.getType(TIFunctionType);
2118 FunctionDcl->setIsFinalized();
2147 if (FunctionDcl->getIsInlinedAbstract()) {
2153 Shared->TypeRecords.find(
StreamTPI, Id.getClassType())))
2154 Class->addElement(FunctionDcl);
2157 TypeIndex TIFunctionType = Id.getFunctionType();
2183 MemberFunction->setIsFinalized();
2185 MemberFunction->setOffset(TI.
getIndex());
2186 MemberFunction->setOffsetFromTypeIndex();
2188 if (ProcessArgumentList) {
2189 ProcessArgumentList =
false;
2191 if (!MemberFunction->getIsStatic()) {
2196 createParameter(ThisPointer,
StringRef(), MemberFunction);
2197 This->setIsArtificial();
2224 Method.
Name = OverloadedMethodName;
2256 bool SeenModifier =
false;
2258 if (Mods &
uint16_t(ModifierOptions::Const)) {
2259 SeenModifier =
true;
2260 LastLink->
setTag(dwarf::DW_TAG_const_type);
2261 LastLink->setIsConst();
2264 if (Mods &
uint16_t(ModifierOptions::Volatile)) {
2272 LastLink->
setTag(dwarf::DW_TAG_volatile_type);
2273 LastLink->setIsVolatile();
2274 LastLink->
setName(
"volatile");
2276 if (Mods &
uint16_t(ModifierOptions::Unaligned)) {
2285 LastLink->setIsUnaligned();
2286 LastLink->
setName(
"unaligned");
2289 LastLink->
setType(ModifiedType);
2308 if (
Ptr.isPointerToMember()) {
2320 Pointee =
Ptr.isPointerToMember()
2321 ? Shared->TypeRecords.find(
StreamTPI,
Ptr.getReferentType())
2331 bool SeenModifier =
false;
2336 if (
Ptr.isRestrict()) {
2337 SeenModifier =
true;
2339 Restrict->setTag(dwarf::DW_TAG_restrict_type);
2346 if (Mode == PointerMode::LValueReference) {
2348 LVType *LReference = Reader->createType();
2349 LReference->setIsModifier();
2350 LastLink->
setType(LReference);
2351 LastLink = LReference;
2354 LastLink->
setTag(dwarf::DW_TAG_reference_type);
2355 LastLink->setIsReference();
2358 if (Mode == PointerMode::RValueReference) {
2360 LVType *RReference = Reader->createType();
2361 RReference->setIsModifier();
2362 LastLink->
setType(RReference);
2363 LastLink = RReference;
2366 LastLink->
setTag(dwarf::DW_TAG_rvalue_reference_type);
2367 LastLink->setIsRvalueReference();
2393 if (ProcessArgumentList) {
2394 ProcessArgumentList =
false;
2416 if (
Union.hasUniqueName())
2425 if (Scope->getIsFinalized())
2427 Scope->setIsFinalized();
2429 Scope->setName(
Union.getName());
2430 if (
Union.hasUniqueName())
2431 Scope->setLinkageName(
Union.getUniqueName());
2433 if (
Union.isNested()) {
2434 Scope->setIsNested();
2435 createParents(
Union.getName(), Scope);
2437 if (
LVScope *Namespace = Shared->NamespaceDeduction.get(
Union.getName()))
2443 if (!
Union.getFieldList().isNoneType()) {
2523 if (
LVScope *Namespace = Shared->NamespaceDeduction.get(
2524 String.getString(),
false)) {
2528 Scope->removeElement(Element);
2614 Symbol->setAccessibilityCode(
Base.getAccess());
2654 Enum.getValue().toString(
Value, 16,
true,
true);
2692 if (NestedType && NestedType->getIsNested()) {
2698 if (NestedTypeName.
size() && RecordName.
size()) {
2700 std::tie(OuterComponent, std::ignore) =
2704 if (OuterComponent.
size() && OuterComponent.
equals(RecordName)) {
2705 if (!NestedType->getIsScopedAlready()) {
2706 Scope->addElement(NestedType);
2707 NestedType->setIsScopedAlready();
2710 Typedef->resetIncludeInPrint();
2736 ProcessArgumentList =
true;
2738 MemberFunction->setIsFinalized();
2741 MemberFunction->setName(Method.
getName());
2742 MemberFunction->setAccessibilityCode(Method.
getAccess());
2745 if (
Kind == MethodKind::Static)
2746 MemberFunction->setIsStatic();
2747 MemberFunction->setVirtualityCode(
Kind);
2750 if (MethodOptions::CompilerGenerated ==
2751 (
Flags & MethodOptions::CompilerGenerated))
2752 MemberFunction->setIsArtificial();
2760 ProcessArgumentList =
false;
2780 OverloadedMethodName = Method.
getName();
2835 Symbol->setAccessibilityCode(
Base.getAccess());
2836 Symbol->setVirtualityCode(MethodKind::Virtual);
2854#define MEMBER_RECORD(EnumName, EnumVal, Name) \
2857 visitKnownMember<Name##Record>(Record, Callbacks, TI, Element)) \
2861#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
2862 MEMBER_RECORD(EnumVal, EnumVal, AliasName)
2863#define TYPE_RECORD(EnumName, EnumVal, Name)
2864#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
2865#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
2881#define TYPE_RECORD(EnumName, EnumVal, Name) \
2883 if (Error Err = visitKnownRecord<Name##Record>(Record, TI, Element)) \
2887#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
2888 TYPE_RECORD(EnumVal, EnumVal, AliasName)
2889#define MEMBER_RECORD(EnumName, EnumVal, Name)
2890#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
2891#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
2898Error LVLogicalVisitor::visitFieldListMemberStream(
2907 while (!Reader.empty()) {
2908 if (
Error Err = Reader.readEnum(Leaf))
2926 if (!ScopeStack.empty())
2928 InCompileUnitScope =
true;
2952 if (
options().getAttributeBase())
2959 case TypeLeafKind::LF_ENUMERATE:
2963 case TypeLeafKind::LF_MODIFIER:
2967 case TypeLeafKind::LF_POINTER:
2975 case TypeLeafKind::LF_BCLASS:
2976 case TypeLeafKind::LF_IVBCLASS:
2977 case TypeLeafKind::LF_VBCLASS:
2982 case TypeLeafKind::LF_MEMBER:
2983 case TypeLeafKind::LF_STMEMBER:
2990 case TypeLeafKind::LF_ARRAY:
2994 case TypeLeafKind::LF_CLASS:
2999 case TypeLeafKind::LF_ENUM:
3003 case TypeLeafKind::LF_METHOD:
3004 case TypeLeafKind::LF_ONEMETHOD:
3005 case TypeLeafKind::LF_PROCEDURE:
3010 case TypeLeafKind::LF_STRUCTURE:
3015 case TypeLeafKind::LF_UNION:
3034 case SymbolKind::S_UDT:
3040 case SymbolKind::S_CONSTANT:
3046 case SymbolKind::S_BPREL32:
3047 case SymbolKind::S_REGREL32:
3048 case SymbolKind::S_GDATA32:
3049 case SymbolKind::S_LDATA32:
3050 case SymbolKind::S_LOCAL:
3060 case SymbolKind::S_BLOCK32:
3065 case SymbolKind::S_COMPILE2:
3066 case SymbolKind::S_COMPILE3:
3071 case SymbolKind::S_INLINESITE:
3072 case SymbolKind::S_INLINESITE2:
3077 case SymbolKind::S_LPROC32:
3078 case SymbolKind::S_GPROC32:
3079 case SymbolKind::S_LPROC32_ID:
3080 case SymbolKind::S_GPROC32_ID:
3081 case SymbolKind::S_SEPCODE:
3082 case SymbolKind::S_THUNK32:
3102 Element->setIsFinalized();
3112 Element->setOffsetFromTypeIndex();
3123 Element->setOffsetFromTypeIndex();
3137 Symbol->setName(
Name);
3143 if (CVMemberType.
kind() == LF_BITFIELD) {
3151 Symbol->setAccessibilityCode(Access);
3158 LVSymbol *Parameter = Reader->createSymbol();
3160 Parameter->setIsParameter();
3161 Parameter->
setTag(dwarf::DW_TAG_formal_parameter);
3181 return static_cast<LVType *
>(Element);
3197 return static_cast<LVType *
>(Element);
3228 if (Components.size() < 2)
3230 Components.pop_back();
3232 LVStringRefs::size_type FirstNamespace;
3233 LVStringRefs::size_type FirstAggregate;
3234 std::tie(FirstNamespace, FirstAggregate) =
3235 Shared->NamespaceDeduction.find(Components);
3238 W.
printString(
"First Namespace", Components[FirstNamespace]);
3239 W.
printString(
"First NonNamespace", Components[FirstAggregate]);
3243 if (FirstNamespace < FirstAggregate) {
3244 Shared->NamespaceDeduction.get(
3246 Components.begin() + FirstAggregate));
3255 LVStringRefs(Components.begin(), Components.begin() + FirstAggregate));
3258 for (LVStringRefs::size_type
Index = FirstAggregate;
3261 Components.begin() +
Index + 1),
3263 TIAggregate = Shared->ForwardReferences.remap(
3264 Shared->TypeRecords.find(
StreamTPI, AggregateName));
3274 if (Aggregate && !Element->getIsScopedAlready()) {
3276 Element->setIsScopedAlready();
3283 TI = Shared->ForwardReferences.remap(TI);
3286 LVElement *Element = Shared->TypeRecords.find(StreamIdx, TI);
3294 return (TypeName.back() ==
'*') ? createPointerType(TI, TypeName)
3295 : createBaseType(TI, TypeName);
3303 if (Element->getIsFinalized())
3317 Element->setIsFinalized();
3324 for (
const TypeIndex &Entry : Shared->LineRecords) {
3340 if (
LVElement *Element = Shared->TypeRecords.find(
3344 Shared->StringRecords.findIndex(
Line.getSourceFile()));
3352 Shared->NamespaceDeduction.init();
3358 if (!
options().getInternalTag())
3363 auto NewLine = [&]() {
3376 Shared->TypeKinds.clear();
3379 OS <<
"\nSymbols:\n";
3382 Shared->SymbolKinds.clear();
3396 ParentLowPC = (*
Locations->begin())->getLowerAddress();
3403 LVInlineeInfo::iterator Iter = InlineeInfo.find(
InlineSite.Inlinee);
3404 if (Iter != InlineeInfo.end()) {
3405 LineNumber = Iter->second.first;
3414 dbgs() <<
"inlineSiteAnnotation\n"
3415 <<
"Abstract: " << AbstractFunction->
getName() <<
"\n"
3416 <<
"Inlined: " << InlinedFunction->
getName() <<
"\n"
3417 <<
"Parent: " << Parent->
getName() <<
"\n"
3418 <<
"Low PC: " <<
hexValue(ParentLowPC) <<
"\n";
3422 if (!
options().getPrintLines())
3429 int32_t LineOffset = LineNumber;
3433 auto UpdateCodeOffset = [&](
uint32_t Delta) {
3440 auto UpdateLineOffset = [&](int32_t Delta) {
3441 LineOffset += Delta;
3443 char Sign = Delta > 0 ?
'+' :
'-';
3444 dbgs() <<
formatv(
" line {0} ({1}{2})", LineOffset, Sign,
3448 auto UpdateFileOffset = [&](int32_t
Offset) {
3454 auto CreateLine = [&]() {
3458 Line->setLineNumber(LineOffset);
3465 bool SeenLowAddress =
false;
3466 bool SeenHighAddress =
false;
3470 for (
auto &Annot :
InlineSite.annotations()) {
3477 switch (Annot.OpCode) {
3478 case BinaryAnnotationsOpCode::ChangeCodeOffset:
3479 case BinaryAnnotationsOpCode::CodeOffset:
3480 case BinaryAnnotationsOpCode::ChangeCodeLength:
3481 UpdateCodeOffset(Annot.U1);
3483 if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeOffset) {
3486 SeenLowAddress =
true;
3489 if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeLength) {
3491 SeenHighAddress =
true;
3494 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
3495 UpdateCodeOffset(Annot.U2);
3498 case BinaryAnnotationsOpCode::ChangeLineOffset:
3499 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
3500 UpdateCodeOffset(Annot.U1);
3501 UpdateLineOffset(Annot.S1);
3504 BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset)
3507 case BinaryAnnotationsOpCode::ChangeFile:
3508 UpdateFileOffset(Annot.U1);
3514 if (SeenLowAddress && SeenHighAddress) {
3515 SeenLowAddress =
false;
3516 SeenHighAddress =
false;
3517 InlinedFunction->
addObject(LowPC, HighPC);
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
AMDGPU Lower Kernel Arguments
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
Provides read only access to a subclass of BinaryStream.
Stores all information relating to a compile unit, be it in its original instance in the object file ...
This is an important base class in LLVM.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringRef getName() const
virtual void printString(StringRef Value)
void indent(int Levels=1)
void unindent(int Levels=1)
void printEnum(StringRef Label, T Value, ArrayRef< EnumEntry< TEnum > > EnumValues)
void printFlags(StringRef Label, T Value, ArrayRef< EnumEntry< TFlag > > Flags, TFlag EnumMask1={}, TFlag EnumMask2={}, TFlag EnumMask3={})
virtual raw_ostream & getOStream()
virtual raw_ostream & startLine()
virtual void printNumber(StringRef Label, char Value)
void printHex(StringRef Label, T Value)
virtual void printBoolean(StringRef Label, bool Value)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr size_t size() const
size - Get the string size.
bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
Value(Type *Ty, unsigned scid)
void setName(const Twine &Name)
Change the name of the value.
TypeIndex getElementType() const
TypeIndex getIndexType() const
StringRef getName() const
uint8_t getBitSize() const
TypeIndex getType() const
uint8_t getBitOffset() const
ArrayRef< TypeIndex > getArgs() const
uint8_t getLanguage() const
uint32_t getFlags() const
CompileSym3Flags getFlags() const
SourceLanguage getLanguage() const
Represents a read-only view of a CodeView string table.
DefRangeFramePointerRelHeader Hdr
LocalVariableAddrRange Range
uint32_t getRelocationOffset() const
std::vector< LocalVariableAddrGap > Gaps
DefRangeRegisterRelHeader Hdr
bool hasSpilledUDTMember() const
uint32_t getRelocationOffset() const
uint16_t offsetInParent() const
std::vector< LocalVariableAddrGap > Gaps
LocalVariableAddrRange Range
uint32_t getRelocationOffset() const
std::vector< LocalVariableAddrGap > Gaps
LocalVariableAddrRange Range
DefRangeRegisterHeader Hdr
LocalVariableAddrRange Range
uint32_t getRelocationOffset() const
std::vector< LocalVariableAddrGap > Gaps
DefRangeSubfieldRegisterHeader Hdr
std::vector< LocalVariableAddrGap > Gaps
LocalVariableAddrRange Range
uint32_t getRelocationOffset() const
std::vector< LocalVariableAddrGap > Gaps
uint32_t getRelocationOffset() const
LocalVariableAddrRange Range
uint32_t getSignature() const
RegisterId getLocalFramePtrReg(CPUType CPU) const
Extract the register this frame uses to refer to local variables.
RegisterId getParamFramePtrReg(CPUType CPU) const
Extract the register this frame uses to refer to parameters.
FrameProcedureOptions Flags
Provides amortized O(1) random access to a CodeView type stream.
std::optional< CVType > tryGetType(TypeIndex Index)
CVType getType(TypeIndex Index) override
StringRef getTypeName(TypeIndex Index) override
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
TypeIndex getContinuationIndex() const
TypeIndex getReturnType() const
int32_t getThisPointerAdjustment() const
TypeIndex getArgumentList() const
uint16_t getParameterCount() const
TypeIndex getThisType() const
TypeIndex getClassType() const
std::vector< OneMethodRecord > Methods
int32_t getVFTableOffset() const
TypeIndex getType() const
bool isIntroducingVirtual() const
MemberAccess getAccess() const
MethodKind getMethodKind() const
StringRef getName() const
For method overload sets. LF_METHOD.
StringRef getName() const
uint16_t getNumOverloads() const
TypeIndex getMethodList() const
uint32_t getSignature() const
StringRef getPrecompFilePath() const
uint32_t getTypesCount() const
uint32_t getStartTypeIndex() const
uint32_t getRelocationOffset() const
TypeIndex getReturnType() const
TypeIndex getArgumentList() const
uint16_t getParameterCount() const
TypeIndex getFieldList() const
static Error deserializeAs(CVType &CVT, T &Record)
static TypeIndex fromArrayIndex(uint32_t Index)
SimpleTypeKind getSimpleKind() const
void setIndex(uint32_t I)
static const uint32_t FirstNonSimpleIndex
static StringRef simpleTypeName(TypeIndex TI)
uint32_t getIndex() const
StringRef getName() const
const GUID & getGuid() const
void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks)
virtual Error visitUnknownMember(CVMemberRecord &Record)
virtual Error visitMemberEnd(CVMemberRecord &Record)
virtual Error visitMemberBegin(CVMemberRecord &Record)
TypeIndex getSourceFile() const
uint16_t getModule() const
uint32_t getLineNumber() const
uint32_t getLineNumber() const
TypeIndex getSourceFile() const
TypeIndex getType() const
uint32_t getVFPtrOffset() const
TypeIndex getOverriddenVTable() const
ArrayRef< StringRef > getMethodNames() const
StringRef getName() const
TypeIndex getCompleteClass() const
uint32_t getEntryCount() const
void addInlineeLines(LVScope *Scope, LVLines &Lines)
LVAddress getSymbolTableAddress(StringRef Name)
LVAddress linearAddress(uint16_t Segment, uint32_t Offset, LVAddress Addendum=0)
void addToSymbolTable(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex=0)
void addModule(LVScope *Scope)
void getLinkageName(const llvm::object::coff_section *CoffSection, uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym)
static StringRef getSymbolKindName(SymbolKind Kind)
virtual void setCount(int64_t Value)
virtual void setBitSize(uint32_t Size)
virtual void updateLevel(LVScope *Parent, bool Moved=false)
virtual int64_t getCount() const
void setInlineCode(uint32_t Code)
virtual void setReference(LVElement *Element)
void setName(StringRef ElementName) override
StringRef getName() const override
void setType(LVElement *Element=nullptr)
void setFilenameIndex(size_t Index)
Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI, LVElement *Element)
void printRecords(raw_ostream &OS) const
void stopProcessArgumentList()
void printTypeEnd(CVType &Record)
Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks, TypeIndex TI, LVElement *Element)
Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base, TypeIndex TI, LVElement *Element)
void printMemberEnd(CVMemberRecord &Record)
void setCompileUnitName(std::string Name)
LVElement * CurrentElement
Error inlineSiteAnnotation(LVScope *AbstractFunction, LVScope *InlinedFunction, InlineSiteSym &InlineSite)
LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, llvm::pdb::InputFile &Input)
void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx)
Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI)
void pushScope(LVScope *Scope)
Error visitUnknownType(CVType &Record, TypeIndex TI)
void startProcessArgumentList()
void addElement(LVScope *Scope, bool IsCompileUnit)
void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)
LVElement * getElement(uint32_t StreamIdx, TypeIndex TI, LVScope *Parent=nullptr)
LVScope * getReaderScope() const
void printMemberBegin(CVMemberRecord &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)
Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element)
LVElement * createElement(TypeLeafKind Kind)
LVScope * getParentScope() const
void setOffset(LVOffset DieOffset)
LVOffset getOffset() const
void setLineNumber(uint32_t Number)
void setTag(dwarf::Tag Tag)
codeview::CPUType getCompileUnitCPUType()
void setCompileUnitCPUType(codeview::CPUType Type)
virtual bool isSystemEntry(LVElement *Element, StringRef Name={}) const
LVScopeCompileUnit * getCompileUnit() const
void setCompileUnit(LVScope *Scope)
void addPublicName(LVScope *Scope, LVAddress LowPC, LVAddress HighPC)
void addElement(LVElement *Element)
void addObject(LVLocation *Location)
const LVLocations * getRanges() const
void getLinkageName(uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym=nullptr)
void printRelocatedField(StringRef Label, uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym=nullptr)
DebugStringTableSubsectionRef getStringTable() override
StringRef getFileNameForFileOffset(uint32_t FileOffset) override
Error visitSymbolEnd(CVSymbol &Record) override
Error visitKnownRecord(CVSymbol &Record, BlockSym &Block) override
Error visitSymbolBegin(CVSymbol &Record) override
Error visitUnknownSymbol(CVSymbol &Record) override
Action to take on unknown symbols. By default, they are ignored.
Error visitMemberEnd(CVMemberRecord &Record) override
Error visitUnknownMember(CVMemberRecord &Record) override
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
Error visitMemberBegin(CVMemberRecord &Record) override
Error visitKnownRecord(CVType &Record, BuildInfoRecord &Args) override
Error visitUnknownType(CVType &Record) override
Action to take on unknown types. By default, they are ignored.
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char TypeName[]
Key for Kernel::Arg::Metadata::mTypeName.
PointerMode
Equivalent to CV_ptrmode_e.
MethodKind
Part of member attribute flags. (CV_methodprop_e)
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
bool symbolEndsScope(SymbolKind Kind)
Return true if this ssymbol ends a scope.
MethodOptions
Equivalent to CV_fldattr_t bitfield.
ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()
MemberAccess
Source-level access specifier. (CV_access_e)
bool symbolOpensScope(SymbolKind Kind)
Return true if this symbol opens a scope.
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
ArrayRef< EnumEntry< uint16_t > > getLocalFlagNames()
ArrayRef< EnumEntry< uint16_t > > getRegisterNames(CPUType Cpu)
bool isAggregate(CVType CVT)
Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, LF_CLASS, LF_INTERFACE,...
ArrayRef< EnumEntry< uint8_t > > getProcSymFlagNames()
TypeRecordKind
Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
uint64_t getSizeInBytesForTypeRecord(CVType CVT)
Given an arbitrary codeview type, return the type's size in the case of aggregate (LF_STRUCTURE,...
ArrayRef< EnumEntry< unsigned > > getCPUTypeNames()
ArrayRef< EnumEntry< SourceLanguage > > getSourceLanguageNames()
uint64_t getSizeInBytesForTypeIndex(TypeIndex TI)
Given an arbitrary codeview type index, determine its size.
TypeIndex getModifiedType(const CVType &CVT)
Given a CVType which is assumed to be an LF_MODIFIER, return the TypeIndex of the type that the LF_MO...
ArrayRef< EnumEntry< uint32_t > > getCompileSym3FlagNames()
void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, TypeCollection &Types)
@ DW_INL_declared_inlined
constexpr Tag DW_TAG_unaligned
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
FormattedNumber hexValue(uint64_t N, unsigned Width=HEX_WIDTH, bool Upper=false)
static TypeIndex getTrueType(TypeIndex &TI)
std::vector< StringRef > LVStringRefs
static StringRef getRecordName(LazyRandomTypeCollection &Types, TypeIndex TI)
std::vector< TypeIndex > LVLineRecords
LVStringRefs getAllLexicalComponents(StringRef Name)
std::string transformPath(StringRef Path)
LVLexicalComponent getInnerComponent(StringRef Name)
static const EnumEntry< TypeLeafKind > LeafTypeNames[]
std::set< SymbolKind > LVSymbolKinds
std::set< TypeLeafKind > LVTypeKinds
std::string getScopedName(const LVStringRefs &Components, StringRef BaseName={})
std::tuple< LVStringRefs::size_type, LVStringRefs::size_type > LVLexicalIndex
std::string formatTypeLeafKind(codeview::TypeLeafKind K)
Print(const T &, const DataFlowGraph &) -> Print< T >
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
std::string demangle(const std::string &MangledName)
Attempt to demangle a string using different demangling schemes.
std::tuple< uint64_t, uint32_t > InlineSite
detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
StringRef getTypeName()
We provide a function which tries to compute the (demangled) name of a type statically.
@ Mod
The access may modify the value stored in memory.
detail::RepeatAdapter< T > fmt_repeat(T &&Item, size_t Count)
void consumeError(Error Err)
Consume a Error without doing anything.
MethodOptions getFlags() const
Get the flags that are not included in access control or method properties.
LVShared(LVCodeViewReader *Reader, LVLogicalVisitor *Visitor)
LVLineRecords LineRecords
LVTypeRecords TypeRecords
LVCodeViewReader * Reader
LVLogicalVisitor * Visitor
LVNamespaceDeduction NamespaceDeduction
LVSymbolKinds SymbolKinds
LVStringRecords StringRecords
LVForwardReferences ForwardReferences