27
27
#include < iomanip>
28
28
#include < iostream>
29
29
#include < ostream>
30
+ #include < sstream>
30
31
#include < unordered_map>
31
32
#include < vector>
32
33
@@ -1035,88 +1036,111 @@ class TypeRefBuilder {
1035
1036
OpaquePointerReader(pointerReader),
1036
1037
OpaqueDynamicSymbolResolver(dynamicSymbolResolver) {}
1037
1038
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
+ }
1052
1053
1054
+ uintptr_t getParentDescriptorAddress (
1055
+ uintptr_t contextDescriptorAddress,
1056
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1057
+ *contextDescriptor) {
1053
1058
auto parentOffsetAddress = detail::applyRelativeOffset (
1054
1059
(const char *)contextDescriptorAddress,
1055
1060
(int32_t )contextDescriptor->getParentOffset ());
1056
- auto parentOffsetBytes = OpaqueByteReader (
1061
+ auto parentOfsetBytes = OpaqueByteReader (
1057
1062
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 ();
1063
1064
auto parentTargetAddress = detail::applyRelativeOffset (
1064
1065
(const char *)parentOffsetAddress, *parentFieldOffset);
1066
+ return parentTargetAddress;
1067
+ }
1065
1068
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 {
1070
1119
auto parentContextDescriptorBytes = OpaqueByteReader (
1071
- remote::RemoteAddress (descriptorAddress ),
1120
+ remote::RemoteAddress (parentContextDescriptorAddress ),
1072
1121
sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1073
1122
if (!parentContextDescriptorBytes.get ()) {
1074
1123
Error = " Failed to read context descriptor." ;
1075
- return llvm::None ;
1124
+ return ;
1076
1125
}
1077
- const ExternalContextDescriptor<ObjCInteropKind,
1078
- PointerSize> *parentContextDescriptor =
1126
+ const auto parentDescriptor =
1079
1127
(const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1080
1128
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);
1111
1138
}
1112
-
1113
- return optionalParentName;
1114
1139
};
1115
1140
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 ;
1120
1144
if (auto symbol = OpaquePointerReader (
1121
1145
remote::RemoteAddress (adjustedParentTargetAddress),
1122
1146
PointerSize)) {
@@ -1125,20 +1149,21 @@ class TypeRefBuilder {
1125
1149
auto demangledRoot =
1126
1150
Ctx.demangleSymbolAsNode (symbol->getSymbol ().str ());
1127
1151
assert (demangledRoot->getKind () == Node::Kind::Global);
1128
- optionalParentContextName =
1152
+ std::string nodeName =
1129
1153
nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
1154
+ chain.push_back (
1155
+ ContextNameInfo{nodeName, adjustedParentTargetAddress, false });
1130
1156
} else {
1131
- optionalParentContextName =
1132
- readContextParentName (adjustedParentTargetAddress);
1157
+ addParentNameAndRecurse (adjustedParentTargetAddress, chain);
1133
1158
}
1134
1159
} else {
1135
1160
Error = " Error reading external symbol address." ;
1136
- return llvm::None ;
1161
+ return ;
1137
1162
}
1138
1163
} else {
1139
- optionalParentContextName = readContextParentName (parentTargetAddress );
1164
+ addParentNameAndRecurse (parentDescriptorAddress, chain );
1140
1165
}
1141
- return optionalParentContextName ;
1166
+ return ;
1142
1167
}
1143
1168
1144
1169
llvm::Optional<std::string> readTypeNameFromTypeDescriptor (
@@ -1183,6 +1208,70 @@ class TypeRefBuilder {
1183
1208
return parentName;
1184
1209
}
1185
1210
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
+
1186
1275
llvm::Optional<std::string> readProtocolNameFromProtocolDescriptor (
1187
1276
uintptr_t protocolDescriptorAddress) {
1188
1277
std::string protocolName;
@@ -1307,14 +1396,14 @@ class TypeRefBuilder {
1307
1396
else
1308
1397
typeName = optionalTypeName.getValue ();
1309
1398
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 );
1318
1407
}
1319
1408
1320
1409
// / Extract protocol name from a Conformance Descriptor
@@ -1342,6 +1431,33 @@ class TypeRefBuilder {
1342
1431
(const char *)protocolDescriptorFieldAddress,
1343
1432
(int32_t )*protocolDescriptorOffset);
1344
1433
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
+
1345
1461
// Set low bit indicates that this is an indirect
1346
1462
// reference
1347
1463
if (protocolDescriptorTarget & 0x1 ) {
@@ -1360,16 +1476,9 @@ class TypeRefBuilder {
1360
1476
nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
1361
1477
} else {
1362
1478
// 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);
1373
1482
}
1374
1483
} else {
1375
1484
Error = " Error reading external protocol address." ;
@@ -1379,13 +1488,7 @@ class TypeRefBuilder {
1379
1488
// If this is a direct reference, get symbol name from the protocol
1380
1489
// descriptor.
1381
1490
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);
1389
1492
}
1390
1493
1391
1494
return protocolName;
0 commit comments