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
@@ -1027,88 +1028,111 @@ class TypeRefBuilder {
1027
1028
OpaqueStringReader (stringReader), OpaquePointerReader(pointerReader) {
1028
1029
}
1029
1030
1030
- llvm::Optional<std::string>
1031
- getParentContextName ( uintptr_t contextDescriptorAddress) {
1032
- llvm::Optional<std::string> optionalParentContextName ;
1033
- auto contextTypeDescriptorBytes = OpaqueByteReader (
1034
- remote::RemoteAddress (contextDescriptorAddress),
1035
- sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1036
- if (!contextTypeDescriptorBytes. get ()) {
1037
- Error = " Failed to read context descriptor. " ;
1038
- return llvm::None;
1039
- }
1040
- const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1041
- *contextDescriptor =
1042
- ( const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1043
- contextTypeDescriptorBytes. get ();
1031
+ struct ContextNameInfo {
1032
+ std::string name;
1033
+ uintptr_t descriptorAddress ;
1034
+ bool isAnonymous;
1035
+
1036
+ ~ContextNameInfo () {}
1037
+ };
1038
+
1039
+ bool isModuleDescriptor (
1040
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1041
+ *contextDescriptor) {
1042
+ return isa<ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1043
+ contextDescriptor);
1044
+ }
1044
1045
1046
+ uintptr_t getParentDescriptorAddress (
1047
+ uintptr_t contextDescriptorAddress,
1048
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1049
+ *contextDescriptor) {
1045
1050
auto parentOffsetAddress = detail::applyRelativeOffset (
1046
1051
(const char *)contextDescriptorAddress,
1047
1052
(int32_t )contextDescriptor->getParentOffset ());
1048
- auto parentOffsetBytes = OpaqueByteReader (
1053
+ auto parentOfsetBytes = OpaqueByteReader (
1049
1054
remote::RemoteAddress (parentOffsetAddress), sizeof (uint32_t ));
1050
- if (!parentOffsetBytes.get ()) {
1051
- Error = " Failed to parent offset in a type descriptor." ;
1052
- return llvm::None;
1053
- }
1054
- auto parentFieldOffset = (const int32_t *)parentOffsetBytes.get ();
1055
+ auto parentFieldOffset = (const int32_t *)parentOfsetBytes.get ();
1055
1056
auto parentTargetAddress = detail::applyRelativeOffset (
1056
1057
(const char *)parentOffsetAddress, *parentFieldOffset);
1058
+ return parentTargetAddress;
1059
+ }
1057
1060
1058
- //
1059
- auto readContextParentName =
1060
- [&](uintptr_t descriptorAddress) -> llvm::Optional<std::string> {
1061
- llvm::Optional<std::string> optionalParentName;
1061
+ llvm::Optional<ContextNameInfo>
1062
+ getContextName (uintptr_t contextDescriptorAddress,
1063
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1064
+ *contextDescriptor) {
1065
+ if (auto moduleDescriptor = dyn_cast<
1066
+ ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1067
+ contextDescriptor)) {
1068
+ auto moduleDescriptorName = readModuleNameFromModuleDescriptor (
1069
+ moduleDescriptor, contextDescriptorAddress);
1070
+ if (!moduleDescriptorName.hasValue ())
1071
+ return llvm::None;
1072
+ else
1073
+ return ContextNameInfo{moduleDescriptorName.getValue (),
1074
+ contextDescriptorAddress, false };
1075
+ } else if (auto typeDescriptor = dyn_cast<ExternalTypeContextDescriptor<
1076
+ ObjCInteropKind, PointerSize>>(contextDescriptor)) {
1077
+ auto typeDescriptorName = readTypeNameFromTypeDescriptor (
1078
+ typeDescriptor, contextDescriptorAddress);
1079
+ if (!typeDescriptorName.hasValue ())
1080
+ return llvm::None;
1081
+ else
1082
+ return ContextNameInfo{typeDescriptorName.getValue (),
1083
+ contextDescriptorAddress, false };
1084
+ } else if (auto anonymousDescriptor =
1085
+ dyn_cast<ExternalAnonymousContextDescriptor<
1086
+ ObjCInteropKind, PointerSize>>(contextDescriptor)) {
1087
+ auto anonymousDescriptorName = readAnonymousNameFromAnonymousDescriptor (
1088
+ anonymousDescriptor, contextDescriptorAddress);
1089
+ if (!anonymousDescriptorName.hasValue ())
1090
+ return llvm::None;
1091
+ else
1092
+ return ContextNameInfo{anonymousDescriptorName.getValue (),
1093
+ contextDescriptorAddress, true };
1094
+ } else {
1095
+ Error = " Unexpected type of context descriptor." ;
1096
+ return llvm::None;
1097
+ }
1098
+ }
1099
+
1100
+ void getParentContextChain (
1101
+ uintptr_t contextDescriptorAddress,
1102
+ const ExternalContextDescriptor<ObjCInteropKind, PointerSize>
1103
+ *contextDescriptor,
1104
+ std::vector<ContextNameInfo> &chain) {
1105
+ const auto parentDescriptorAddress = getParentDescriptorAddress (
1106
+ contextDescriptorAddress, contextDescriptor);
1107
+
1108
+ auto addParentNameAndRecurse =
1109
+ [&](uintptr_t parentContextDescriptorAddress,
1110
+ std::vector<ContextNameInfo> &chain) -> void {
1062
1111
auto parentContextDescriptorBytes = OpaqueByteReader (
1063
- remote::RemoteAddress (descriptorAddress ),
1112
+ remote::RemoteAddress (parentContextDescriptorAddress ),
1064
1113
sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1065
1114
if (!parentContextDescriptorBytes.get ()) {
1066
1115
Error = " Failed to read context descriptor." ;
1067
- return llvm::None ;
1116
+ return ;
1068
1117
}
1069
- const ExternalContextDescriptor<ObjCInteropKind,
1070
- PointerSize> *parentContextDescriptor =
1118
+ const auto parentDescriptor =
1071
1119
(const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1072
1120
parentContextDescriptorBytes.get ();
1073
-
1074
- if (auto moduleDescriptor = dyn_cast<
1075
- ExternalModuleContextDescriptor<ObjCInteropKind, PointerSize>>(
1076
- parentContextDescriptor)) {
1077
- auto moduleDescriptorName = readModuleNameFromModuleDescriptor (
1078
- moduleDescriptor, parentTargetAddress);
1079
- if (!moduleDescriptorName.hasValue ())
1080
- return llvm::None;
1081
- else
1082
- optionalParentName = moduleDescriptorName;
1083
- } else if (auto typeDescriptor =
1084
- dyn_cast<ExternalTypeContextDescriptor<ObjCInteropKind,
1085
- PointerSize>>(
1086
- parentContextDescriptor)) {
1087
- auto typeDescriptorName = readTypeNameFromTypeDescriptor (
1088
- typeDescriptor, parentTargetAddress);
1089
- if (!typeDescriptorName.hasValue ())
1090
- return llvm::None;
1091
- else
1092
- optionalParentName = typeDescriptorName;
1093
- // Recurse to get this type's parent.
1094
- auto optionalParentParentName =
1095
- getParentContextName (descriptorAddress);
1096
- if (optionalParentParentName.hasValue ()) {
1097
- optionalParentName = optionalParentParentName.getValue () + " ." +
1098
- optionalParentName.getValue ();
1099
- }
1100
- } else {
1101
- Error = " Unexpected type of parent context descriptor." ;
1102
- return llvm::None;
1121
+ const auto parentNameInfo =
1122
+ getContextName (parentContextDescriptorAddress, parentDescriptor);
1123
+ if (!parentNameInfo.hasValue ()) {
1124
+ return ;
1125
+ }
1126
+ chain.push_back (parentNameInfo.getValue ());
1127
+ if (!isModuleDescriptor (parentDescriptor)) {
1128
+ getParentContextChain (parentContextDescriptorAddress,
1129
+ parentDescriptor, chain);
1103
1130
}
1104
-
1105
- return optionalParentName;
1106
1131
};
1107
1132
1108
- // Set low bit indicates that this is an indirect
1109
- // reference
1110
- if (parentTargetAddress & 0x1 ) {
1111
- auto adjustedParentTargetAddress = parentTargetAddress & ~0x1 ;
1133
+ // Set low bit indicates that this is an indirect reference
1134
+ if (parentDescriptorAddress & 0x1 ) {
1135
+ auto adjustedParentTargetAddress = parentDescriptorAddress & ~0x1 ;
1112
1136
if (auto symbol = OpaquePointerReader (
1113
1137
remote::RemoteAddress (adjustedParentTargetAddress),
1114
1138
PointerSize)) {
@@ -1117,20 +1141,21 @@ class TypeRefBuilder {
1117
1141
auto demangledRoot =
1118
1142
Ctx.demangleSymbolAsNode (symbol->getSymbol ().str ());
1119
1143
assert (demangledRoot->getKind () == Node::Kind::Global);
1120
- optionalParentContextName =
1144
+ std::string nodeName =
1121
1145
nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
1146
+ chain.push_back (
1147
+ ContextNameInfo{nodeName, adjustedParentTargetAddress, false });
1122
1148
} else {
1123
- optionalParentContextName =
1124
- readContextParentName (adjustedParentTargetAddress);
1149
+ addParentNameAndRecurse (adjustedParentTargetAddress, chain);
1125
1150
}
1126
1151
} else {
1127
1152
Error = " Error reading external symbol address." ;
1128
- return llvm::None ;
1153
+ return ;
1129
1154
}
1130
1155
} else {
1131
- optionalParentContextName = readContextParentName (parentTargetAddress );
1156
+ addParentNameAndRecurse (parentDescriptorAddress, chain );
1132
1157
}
1133
- return optionalParentContextName ;
1158
+ return ;
1134
1159
}
1135
1160
1136
1161
llvm::Optional<std::string> readTypeNameFromTypeDescriptor (
@@ -1175,6 +1200,70 @@ class TypeRefBuilder {
1175
1200
return parentName;
1176
1201
}
1177
1202
1203
+ llvm::Optional<std::string> readAnonymousNameFromAnonymousDescriptor (
1204
+ const ExternalAnonymousContextDescriptor<ObjCInteropKind, PointerSize>
1205
+ *anonymousDescriptor,
1206
+ uintptr_t anonymousDescriptorAddress) {
1207
+ if (!anonymousDescriptor->hasMangledName ()) {
1208
+ std::stringstream stream;
1209
+ stream << " (unknown context at $" << std::hex
1210
+ << anonymousDescriptorAddress << " )" ;
1211
+ return stream.str ();
1212
+ }
1213
+ return llvm::None;
1214
+ }
1215
+
1216
+ std::string constructFullyQualifiedNameFromContextChain (
1217
+ const std::vector<ContextNameInfo> &contextNameChain) {
1218
+ std::string newQualifiedTypeName = " " ;
1219
+ std::vector<std::string> reversedQualifiedTypeNameMembers;
1220
+
1221
+ // Traverse the context chain, adding up context names.
1222
+ // Anonymous contexts require special handling: when a type is nested in
1223
+ // an anonymous context, its qualified name is printed as `(type_name in
1224
+ // $hex_val)` where hex_val is the address of the descriptor of the
1225
+ // anonymous parent context.
1226
+ bool skipNext = false ;
1227
+ for (size_t i = 0 ; i < contextNameChain.size (); ++i) {
1228
+ if (skipNext) {
1229
+ skipNext = false ;
1230
+ continue ;
1231
+ }
1232
+ const auto &contextNameInfo = contextNameChain[i];
1233
+ bool lastContext = (i == contextNameChain.size () - 1 );
1234
+ bool currentContextIsAnonymous = contextNameInfo.isAnonymous ;
1235
+ bool nextContextIsAnonymous =
1236
+ lastContext ? false : contextNameChain[i + 1 ].isAnonymous ;
1237
+ if (nextContextIsAnonymous && !currentContextIsAnonymous) {
1238
+ std::stringstream stream;
1239
+ stream << " (" << contextNameInfo.name << " in $" << std::hex
1240
+ << contextNameChain[i + 1 ].descriptorAddress << " )" ;
1241
+ reversedQualifiedTypeNameMembers.push_back (stream.str ());
1242
+ skipNext = true ;
1243
+ } else if (nextContextIsAnonymous && currentContextIsAnonymous) {
1244
+
1245
+ } else if (!nextContextIsAnonymous && !currentContextIsAnonymous) {
1246
+ reversedQualifiedTypeNameMembers.push_back (contextNameInfo.name );
1247
+ } else if (!nextContextIsAnonymous && currentContextIsAnonymous) {
1248
+ reversedQualifiedTypeNameMembers.push_back (contextNameInfo.name );
1249
+ } else {
1250
+ llvm_unreachable (" Exhausted possibilities." );
1251
+ }
1252
+ }
1253
+
1254
+ // Combine the individual context name reps into a single fully-qualified
1255
+ // name string
1256
+ for (auto it = reversedQualifiedTypeNameMembers.rbegin ();
1257
+ it != reversedQualifiedTypeNameMembers.rend (); ++it) {
1258
+ newQualifiedTypeName.append (*it);
1259
+ if (std::next (it) != reversedQualifiedTypeNameMembers.rend ()) {
1260
+ newQualifiedTypeName.append (" ." );
1261
+ }
1262
+ }
1263
+
1264
+ return newQualifiedTypeName;
1265
+ }
1266
+
1178
1267
llvm::Optional<std::string> readProtocolNameFromProtocolDescriptor (
1179
1268
uintptr_t protocolDescriptorAddress) {
1180
1269
std::string protocolName;
@@ -1297,14 +1386,14 @@ class TypeRefBuilder {
1297
1386
else
1298
1387
typeName = optionalTypeName.getValue ();
1299
1388
1300
- // Prepend the parent context name
1301
- auto optionalParentName =
1302
- getParentContextName ( contextTypeDescriptorAddress);
1303
- if (optionalParentName. hasValue ()) {
1304
- typeName = optionalParentName. getValue () + " . " + typeName ;
1305
- }
1306
-
1307
- return std::make_pair (mangledTypeName, typeName );
1389
+ std::vector<ContextNameInfo> contextNameChain;
1390
+ contextNameChain. push_back (
1391
+ ContextNameInfo{typeName, contextTypeDescriptorAddress, false } );
1392
+ getParentContextChain (contextTypeDescriptorAddress, contextDescriptor,
1393
+ contextNameChain) ;
1394
+ std::string fullyQualifiedName =
1395
+ constructFullyQualifiedNameFromContextChain (contextNameChain);
1396
+ return std::make_pair (mangledTypeName, fullyQualifiedName );
1308
1397
}
1309
1398
1310
1399
// / Extract protocol name from a Conformance Descriptor
@@ -1332,6 +1421,33 @@ class TypeRefBuilder {
1332
1421
(const char *)protocolDescriptorFieldAddress,
1333
1422
(int32_t )*protocolDescriptorOffset);
1334
1423
1424
+ auto constructFullyQualifiedProtocolName =
1425
+ [&](uintptr_t protocolDescriptorAddress)
1426
+ -> llvm::Optional<std::string> {
1427
+ auto protocolName =
1428
+ readProtocolNameFromProtocolDescriptor (protocolDescriptorAddress);
1429
+
1430
+ // Read the protocol conformance descriptor itself
1431
+ auto protocolContextDescriptorBytes = OpaqueByteReader (
1432
+ remote::RemoteAddress (protocolDescriptorAddress),
1433
+ sizeof (ExternalContextDescriptor<ObjCInteropKind, PointerSize>));
1434
+ if (!protocolContextDescriptorBytes.get ()) {
1435
+ Error = " Failed to read context (protocol) descriptor." ;
1436
+ return llvm::None;
1437
+ }
1438
+ const ExternalContextDescriptor<ObjCInteropKind,
1439
+ PointerSize> *protocolDescriptor =
1440
+ (const ExternalContextDescriptor<ObjCInteropKind, PointerSize> *)
1441
+ protocolContextDescriptorBytes.get ();
1442
+
1443
+ std::vector<ContextNameInfo> contextNameChain;
1444
+ contextNameChain.push_back (ContextNameInfo{
1445
+ protocolName.getValue (), protocolDescriptorAddress, false });
1446
+ getParentContextChain (protocolDescriptorAddress, protocolDescriptor,
1447
+ contextNameChain);
1448
+ return constructFullyQualifiedNameFromContextChain (contextNameChain);
1449
+ };
1450
+
1335
1451
// Set low bit indicates that this is an indirect
1336
1452
// reference
1337
1453
if (protocolDescriptorTarget & 0x1 ) {
@@ -1350,16 +1466,9 @@ class TypeRefBuilder {
1350
1466
nodeToString (demangledRoot->getChild (0 )->getChild (0 ));
1351
1467
} else {
1352
1468
// This is an absolute address of a protocol descriptor
1353
- auto protocolDescriptorAddress = symbol->getOffset ();
1354
- protocolName = readProtocolNameFromProtocolDescriptor (
1355
- protocolDescriptorAddress);
1356
- // Prepend the parent context name
1357
- auto optionalParentName =
1358
- getParentContextName (protocolDescriptorAddress);
1359
- if (optionalParentName.hasValue ()) {
1360
- protocolName =
1361
- optionalParentName.getValue () + " ." + *protocolName;
1362
- }
1469
+ auto protocolDescriptorAddress = (uintptr_t )symbol->getOffset ();
1470
+ protocolName =
1471
+ constructFullyQualifiedProtocolName (protocolDescriptorAddress);
1363
1472
}
1364
1473
} else {
1365
1474
Error = " Error reading external protocol address." ;
@@ -1369,13 +1478,7 @@ class TypeRefBuilder {
1369
1478
// If this is a direct reference, get symbol name from the protocol
1370
1479
// descriptor.
1371
1480
protocolName =
1372
- readProtocolNameFromProtocolDescriptor (protocolDescriptorTarget);
1373
- // Prepend the parent context name
1374
- auto optionalParentName =
1375
- getParentContextName (protocolDescriptorTarget);
1376
- if (optionalParentName.hasValue ()) {
1377
- protocolName = optionalParentName.getValue () + " ." + *protocolName;
1378
- }
1481
+ constructFullyQualifiedProtocolName (protocolDescriptorTarget);
1379
1482
}
1380
1483
1381
1484
return protocolName;
0 commit comments