2727#include < iomanip>
2828#include < iostream>
2929#include < ostream>
30+ #include < sstream>
3031#include < unordered_map>
3132#include < vector>
3233
@@ -1035,88 +1036,111 @@ class TypeRefBuilder {
10351036 OpaquePointerReader(pointerReader),
10361037 OpaqueDynamicSymbolResolver(dynamicSymbolResolver) {}
10371038
1038- llvm::Optional<std::string>
1039- getParentContextName ( uintptr_t contextDescriptorAddress) {
1040- llvm::Optional<std::string> optionalParentContextName ;
1041- auto contextTypeDescriptorBytes = OpaqueByteReader (
1042- remote::RemoteAddress (contextDescriptorAddress),
1043- sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1044- if (!contextTypeDescriptorBytes. get ()) {
1045- Error = " Failed to read context descriptor. " ;
1046- return llvm::None;
1047- }
1048- const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1049- *contextDescriptor =
1050- ( const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1051- contextTypeDescriptorBytes. get ();
1039+ struct ContextNameInfo {
1040+ std::string name;
1041+ uintptr_t descriptorAddress ;
1042+ bool isAnonymous;
1043+
1044+ ~ContextNameInfo () {}
1045+ };
1046+
1047+ bool isModuleDescriptor (
1048+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1049+ *contextDescriptor) {
1050+ return isa<ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1051+ contextDescriptor);
1052+ }
10521053
1054+ uintptr_t getParentDescriptorAddress (
1055+ uintptr_t contextDescriptorAddress,
1056+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1057+ *contextDescriptor) {
10531058 auto parentOffsetAddress = detail::applyRelativeOffset (
10541059 (const char *)contextDescriptorAddress,
10551060 (int32_t )contextDescriptor->getParentOffset ());
1056- auto parentOffsetBytes = OpaqueByteReader (
1061+ auto parentOfsetBytes = OpaqueByteReader (
10571062 remote::RemoteAddress (parentOffsetAddress), sizeof (uint32_t ));
1058- if (!parentOffsetBytes.get ()) {
1059- Error = " Failed to parent offset in a type descriptor." ;
1060- return llvm::None;
1061- }
1062- auto parentFieldOffset = (const int32_t *)parentOffsetBytes.get ();
1063+ auto parentFieldOffset = (const int32_t *)parentOfsetBytes.get ();
10631064 auto parentTargetAddress = detail::applyRelativeOffset (
10641065 (const char *)parentOffsetAddress, *parentFieldOffset);
1066+ return parentTargetAddress;
1067+ }
10651068
1066- //
1067- auto readContextParentName =
1068- [&](uintptr_t descriptorAddress) -> llvm::Optional<std::string> {
1069- llvm::Optional<std::string> optionalParentName;
1069+ llvm::Optional<ContextNameInfo>
1070+ getContextName (uintptr_t contextDescriptorAddress,
1071+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1072+ *contextDescriptor) {
1073+ if (auto moduleDescriptor = dyn_cast<
1074+ ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1075+ contextDescriptor)) {
1076+ auto moduleDescriptorName = readModuleNameFromModuleDescriptor (
1077+ moduleDescriptor, contextDescriptorAddress);
1078+ if (!moduleDescriptorName.hasValue ())
1079+ return llvm::None;
1080+ else
1081+ return ContextNameInfo{moduleDescriptorName.getValue (),
1082+ contextDescriptorAddress, false };
1083+ } else if (auto typeDescriptor = dyn_cast<ExternalTypeContextDescriptor<
1084+ ObjCInteropKind, PointerSize>>(contextDescriptor)) {
1085+ auto typeDescriptorName = readTypeNameFromTypeDescriptor (
1086+ typeDescriptor, contextDescriptorAddress);
1087+ if (!typeDescriptorName.hasValue ())
1088+ return llvm::None;
1089+ else
1090+ return ContextNameInfo{typeDescriptorName.getValue (),
1091+ contextDescriptorAddress, false };
1092+ } else if (auto anonymousDescriptor =
1093+ dyn_cast<ExternalAnonymousContextDescriptor<
1094+ ObjCInteropKind, PointerSize>>(contextDescriptor)) {
1095+ auto anonymousDescriptorName = readAnonymousNameFromAnonymousDescriptor (
1096+ anonymousDescriptor, contextDescriptorAddress);
1097+ if (!anonymousDescriptorName.hasValue ())
1098+ return llvm::None;
1099+ else
1100+ return ContextNameInfo{anonymousDescriptorName.getValue (),
1101+ contextDescriptorAddress, true };
1102+ } else {
1103+ Error = " Unexpected type of context descriptor." ;
1104+ return llvm::None;
1105+ }
1106+ }
1107+
1108+ void getParentContextChain (
1109+ uintptr_t contextDescriptorAddress,
1110+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1111+ *contextDescriptor,
1112+ std::vector<ContextNameInfo> &chain) {
1113+ const auto parentDescriptorAddress = getParentDescriptorAddress (
1114+ contextDescriptorAddress, contextDescriptor);
1115+
1116+ auto addParentNameAndRecurse =
1117+ [&](uintptr_t parentContextDescriptorAddress,
1118+ std::vector<ContextNameInfo> &chain) -> void {
10701119 auto parentContextDescriptorBytes = OpaqueByteReader (
1071- remote::RemoteAddress (descriptorAddress ),
1120+ remote::RemoteAddress (parentContextDescriptorAddress ),
10721121 sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
10731122 if (!parentContextDescriptorBytes.get ()) {
10741123 Error = " Failed to read context descriptor." ;
1075- return llvm::None ;
1124+ return ;
10761125 }
1077- const ExternalContextDescriptor<ObjCInteropKind,
1078- PointerSize> *parentContextDescriptor =
1126+ const auto parentDescriptor =
10791127 (const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
10801128 parentContextDescriptorBytes.get ();
1081-
1082- if (auto moduleDescriptor = dyn_cast<
1083- ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1084- parentContextDescriptor)) {
1085- auto moduleDescriptorName = readModuleNameFromModuleDescriptor (
1086- moduleDescriptor, parentTargetAddress);
1087- if (!moduleDescriptorName.hasValue ())
1088- return llvm::None;
1089- else
1090- optionalParentName = moduleDescriptorName;
1091- } else if (auto typeDescriptor =
1092- dyn_cast<ExternalTypeContextDescriptor<ObjCInteropKind,
1093- PointerSize>>(
1094- parentContextDescriptor)) {
1095- auto typeDescriptorName = readTypeNameFromTypeDescriptor (
1096- typeDescriptor, parentTargetAddress);
1097- if (!typeDescriptorName.hasValue ())
1098- return llvm::None;
1099- else
1100- optionalParentName = typeDescriptorName;
1101- // Recurse to get this type's parent.
1102- auto optionalParentParentName =
1103- getParentContextName (descriptorAddress);
1104- if (optionalParentParentName.hasValue ()) {
1105- optionalParentName = optionalParentParentName.getValue () + " ." +
1106- optionalParentName.getValue ();
1107- }
1108- } else {
1109- Error = " Unexpected type of parent context descriptor." ;
1110- return llvm::None;
1129+ const auto parentNameInfo =
1130+ getContextName (parentContextDescriptorAddress, parentDescriptor);
1131+ if (!parentNameInfo.hasValue ()) {
1132+ return ;
1133+ }
1134+ chain.push_back (parentNameInfo.getValue ());
1135+ if (!isModuleDescriptor (parentDescriptor)) {
1136+ getParentContextChain (parentContextDescriptorAddress,
1137+ parentDescriptor, chain);
11111138 }
1112-
1113- return optionalParentName;
11141139 };
11151140
1116- // Set low bit indicates that this is an indirect
1117- // reference
1118- if (parentTargetAddress & 0x1 ) {
1119- auto adjustedParentTargetAddress = parentTargetAddress & ~0x1 ;
1141+ // Set low bit indicates that this is an indirect reference
1142+ if (parentDescriptorAddress & 0x1 ) {
1143+ auto adjustedParentTargetAddress = parentDescriptorAddress & ~0x1 ;
11201144 if (auto symbol = OpaquePointerReader (
11211145 remote::RemoteAddress (adjustedParentTargetAddress),
11221146 PointerSize)) {
@@ -1125,20 +1149,21 @@ class TypeRefBuilder {
11251149 auto demangledRoot =
11261150 Ctx.demangleSymbolAsNode (symbol->getSymbol ().str ());
11271151 assert (demangledRoot->getKind () == Node::Kind::Global);
1128- optionalParentContextName =
1152+ std::string nodeName =
11291153 nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
1154+ chain.push_back (
1155+ ContextNameInfo{nodeName, adjustedParentTargetAddress, false });
11301156 } else {
1131- optionalParentContextName =
1132- readContextParentName (adjustedParentTargetAddress);
1157+ addParentNameAndRecurse (adjustedParentTargetAddress, chain);
11331158 }
11341159 } else {
11351160 Error = " Error reading external symbol address." ;
1136- return llvm::None ;
1161+ return ;
11371162 }
11381163 } else {
1139- optionalParentContextName = readContextParentName (parentTargetAddress );
1164+ addParentNameAndRecurse (parentDescriptorAddress, chain );
11401165 }
1141- return optionalParentContextName ;
1166+ return ;
11421167 }
11431168
11441169 llvm::Optional<std::string> readTypeNameFromTypeDescriptor (
@@ -1183,6 +1208,70 @@ class TypeRefBuilder {
11831208 return parentName;
11841209 }
11851210
1211+ llvm::Optional<std::string> readAnonymousNameFromAnonymousDescriptor (
1212+ const ExternalAnonymousContextDescriptor<ObjCInteropKind, PointerSize>
1213+ *anonymousDescriptor,
1214+ uintptr_t anonymousDescriptorAddress) {
1215+ if (!anonymousDescriptor->hasMangledName ()) {
1216+ std::stringstream stream;
1217+ stream << " (unknown context at $" << std::hex
1218+ << anonymousDescriptorAddress << " )" ;
1219+ return stream.str ();
1220+ }
1221+ return llvm::None;
1222+ }
1223+
1224+ std::string constructFullyQualifiedNameFromContextChain (
1225+ const std::vector<ContextNameInfo> &contextNameChain) {
1226+ std::string newQualifiedTypeName = " " ;
1227+ std::vector<std::string> reversedQualifiedTypeNameMembers;
1228+
1229+ // Traverse the context chain, adding up context names.
1230+ // Anonymous contexts require special handling: when a type is nested in
1231+ // an anonymous context, its qualified name is printed as `(type_name in
1232+ // $hex_val)` where hex_val is the address of the descriptor of the
1233+ // anonymous parent context.
1234+ bool skipNext = false ;
1235+ for (size_t i = 0 ; i < contextNameChain.size (); ++i) {
1236+ if (skipNext) {
1237+ skipNext = false ;
1238+ continue ;
1239+ }
1240+ const auto &contextNameInfo = contextNameChain[i];
1241+ bool lastContext = (i == contextNameChain.size () - 1 );
1242+ bool currentContextIsAnonymous = contextNameInfo.isAnonymous ;
1243+ bool nextContextIsAnonymous =
1244+ lastContext ? false : contextNameChain[i + 1 ].isAnonymous ;
1245+ if (nextContextIsAnonymous && !currentContextIsAnonymous) {
1246+ std::stringstream stream;
1247+ stream << " (" << contextNameInfo.name << " in $" << std::hex
1248+ << contextNameChain[i + 1 ].descriptorAddress << " )" ;
1249+ reversedQualifiedTypeNameMembers.push_back (stream.str ());
1250+ skipNext = true ;
1251+ } else if (nextContextIsAnonymous && currentContextIsAnonymous) {
1252+
1253+ } else if (!nextContextIsAnonymous && !currentContextIsAnonymous) {
1254+ reversedQualifiedTypeNameMembers.push_back (contextNameInfo.name );
1255+ } else if (!nextContextIsAnonymous && currentContextIsAnonymous) {
1256+ reversedQualifiedTypeNameMembers.push_back (contextNameInfo.name );
1257+ } else {
1258+ llvm_unreachable (" Exhausted possibilities." );
1259+ }
1260+ }
1261+
1262+ // Combine the individual context name reps into a single fully-qualified
1263+ // name string
1264+ for (auto it = reversedQualifiedTypeNameMembers.rbegin ();
1265+ it != reversedQualifiedTypeNameMembers.rend (); ++it) {
1266+ newQualifiedTypeName.append (*it);
1267+ if (std::next (it) != reversedQualifiedTypeNameMembers.rend ()) {
1268+ newQualifiedTypeName.append (" ." );
1269+ }
1270+ }
1271+
1272+ return newQualifiedTypeName;
1273+ }
1274+
11861275 llvm::Optional<std::string> readProtocolNameFromProtocolDescriptor (
11871276 uintptr_t protocolDescriptorAddress) {
11881277 std::string protocolName;
@@ -1307,14 +1396,14 @@ class TypeRefBuilder {
13071396 else
13081397 typeName = optionalTypeName.getValue ();
13091398
1310- // Prepend the parent context name
1311- auto optionalParentName =
1312- getParentContextName ( contextTypeDescriptorAddress);
1313- if (optionalParentName. hasValue ()) {
1314- typeName = optionalParentName. getValue () + " . " + typeName ;
1315- }
1316-
1317- return std::make_pair (mangledTypeName, typeName );
1399+ std::vector<ContextNameInfo> contextNameChain;
1400+ contextNameChain. push_back (
1401+ ContextNameInfo{typeName, contextTypeDescriptorAddress, false } );
1402+ getParentContextChain (contextTypeDescriptorAddress, contextDescriptor,
1403+ contextNameChain) ;
1404+ std::string fullyQualifiedName =
1405+ constructFullyQualifiedNameFromContextChain (contextNameChain);
1406+ return std::make_pair (mangledTypeName, fullyQualifiedName );
13181407 }
13191408
13201409 // / Extract protocol name from a Conformance Descriptor
@@ -1342,6 +1431,33 @@ class TypeRefBuilder {
13421431 (const char *)protocolDescriptorFieldAddress,
13431432 (int32_t )*protocolDescriptorOffset);
13441433
1434+ auto constructFullyQualifiedProtocolName =
1435+ [&](uintptr_t protocolDescriptorAddress)
1436+ -> llvm::Optional<std::string> {
1437+ auto protocolName =
1438+ readProtocolNameFromProtocolDescriptor (protocolDescriptorAddress);
1439+
1440+ // Read the protocol conformance descriptor itself
1441+ auto protocolContextDescriptorBytes = OpaqueByteReader (
1442+ remote::RemoteAddress (protocolDescriptorAddress),
1443+ sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1444+ if (!protocolContextDescriptorBytes.get ()) {
1445+ Error = " Failed to read context (protocol) descriptor." ;
1446+ return llvm::None;
1447+ }
1448+ const ExternalContextDescriptor<ObjCInteropKind,
1449+ PointerSize> *protocolDescriptor =
1450+ (const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1451+ protocolContextDescriptorBytes.get ();
1452+
1453+ std::vector<ContextNameInfo> contextNameChain;
1454+ contextNameChain.push_back (ContextNameInfo{
1455+ protocolName.getValue (), protocolDescriptorAddress, false });
1456+ getParentContextChain (protocolDescriptorAddress, protocolDescriptor,
1457+ contextNameChain);
1458+ return constructFullyQualifiedNameFromContextChain (contextNameChain);
1459+ };
1460+
13451461 // Set low bit indicates that this is an indirect
13461462 // reference
13471463 if (protocolDescriptorTarget & 0x1 ) {
@@ -1360,16 +1476,9 @@ class TypeRefBuilder {
13601476 nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
13611477 } else {
13621478 // This is an absolute address of a protocol descriptor
1363- auto protocolDescriptorAddress = symbol->getOffset ();
1364- protocolName = readProtocolNameFromProtocolDescriptor (
1365- protocolDescriptorAddress);
1366- // Prepend the parent context name
1367- auto optionalParentName =
1368- getParentContextName (protocolDescriptorAddress);
1369- if (optionalParentName.hasValue ()) {
1370- protocolName =
1371- optionalParentName.getValue () + " ." + *protocolName;
1372- }
1479+ auto protocolDescriptorAddress = (uintptr_t )symbol->getOffset ();
1480+ protocolName =
1481+ constructFullyQualifiedProtocolName (protocolDescriptorAddress);
13731482 }
13741483 } else {
13751484 Error = " Error reading external protocol address." ;
@@ -1379,13 +1488,7 @@ class TypeRefBuilder {
13791488 // If this is a direct reference, get symbol name from the protocol
13801489 // descriptor.
13811490 protocolName =
1382- readProtocolNameFromProtocolDescriptor (protocolDescriptorTarget);
1383- // Prepend the parent context name
1384- auto optionalParentName =
1385- getParentContextName (protocolDescriptorTarget);
1386- if (optionalParentName.hasValue ()) {
1387- protocolName = optionalParentName.getValue () + " ." + *protocolName;
1388- }
1491+ constructFullyQualifiedProtocolName (protocolDescriptorTarget);
13891492 }
13901493
13911494 return protocolName;
0 commit comments