@@ -626,7 +626,8 @@ class MetadataReader {
626
626
}
627
627
628
628
// / Given a remote pointer to metadata, attempt to turn it into a type.
629
- BuiltType readTypeFromMetadata (StoredPointer MetadataAddress) {
629
+ BuiltType readTypeFromMetadata (StoredPointer MetadataAddress,
630
+ bool skipArtificialSubclasses = false ) {
630
631
auto Cached = TypeCache.find (MetadataAddress);
631
632
if (Cached != TypeCache.end ())
632
633
return Cached->second ;
@@ -643,7 +644,7 @@ class MetadataReader {
643
644
644
645
switch (Meta->getKind ()) {
645
646
case MetadataKind::Class:
646
- return readNominalTypeFromMetadata (Meta);
647
+ return readNominalTypeFromMetadata (Meta, skipArtificialSubclasses );
647
648
case MetadataKind::Struct:
648
649
return readNominalTypeFromMetadata (Meta);
649
650
case MetadataKind::Enum:
@@ -997,6 +998,20 @@ class MetadataReader {
997
998
return targetAddress + signext;
998
999
}
999
1000
1001
+ template <typename Offset>
1002
+ llvm::Optional<StoredPointer>
1003
+ resolveNullableRelativeOffset (StoredPointer targetAddress) {
1004
+ Offset relative;
1005
+ if (!Reader->readInteger (RemoteAddress (targetAddress), &relative))
1006
+ return llvm::None;
1007
+ if (relative == 0 )
1008
+ return 0 ;
1009
+ using SignedOffset = typename std::make_signed<Offset>::type;
1010
+ using SignedPointer = typename std::make_signed<StoredPointer>::type;
1011
+ auto signext = (SignedPointer)(SignedOffset)relative;
1012
+ return targetAddress + signext;
1013
+ }
1014
+
1000
1015
// / Given a pointer to an Objective-C class, try to read its class name.
1001
1016
bool readObjCClassName (StoredPointer classAddress, std::string &className) {
1002
1017
// The following algorithm only works on the non-fragile Apple runtime.
@@ -1118,12 +1133,39 @@ class MetadataReader {
1118
1133
return MetadataRef (address, metadata);
1119
1134
}
1120
1135
1121
- StoredPointer readAddressOfNominalTypeDescriptor (MetadataRef metadata) {
1136
+ StoredPointer readAddressOfNominalTypeDescriptor (MetadataRef &metadata,
1137
+ bool skipArtificialSubclasses = false ) {
1122
1138
switch (metadata->getKind ()) {
1123
1139
case MetadataKind::Class: {
1124
1140
auto classMeta = cast<TargetClassMetadata<Runtime>>(metadata);
1125
- return resolveRelativeOffset<StoredPointer>(metadata.getAddress () +
1126
- classMeta->offsetToDescriptorOffset ());
1141
+ while (true ) {
1142
+ auto descriptorAddress =
1143
+ resolveNullableRelativeOffset<StoredPointer>(metadata.getAddress () +
1144
+ classMeta->offsetToDescriptorOffset ());
1145
+
1146
+ // Propagate errors reading the offset.
1147
+ if (!descriptorAddress) return 0 ;
1148
+
1149
+ // If this class has a null descriptor, it's artificial,
1150
+ // and we need to skip it upon request. Otherwise, we're done.
1151
+ if (*descriptorAddress || !skipArtificialSubclasses)
1152
+ return *descriptorAddress;
1153
+
1154
+ auto superclassMetadataAddress = classMeta->SuperClass ;
1155
+ if (!superclassMetadataAddress)
1156
+ return 0 ;
1157
+
1158
+ auto superMeta = readMetadata (superclassMetadataAddress);
1159
+ if (!superMeta)
1160
+ return 0 ;
1161
+ auto superclassMeta =
1162
+ dyn_cast<TargetClassMetadata<Runtime>>(superMeta);
1163
+ if (!superclassMeta)
1164
+ return 0 ;
1165
+
1166
+ classMeta = superclassMeta;
1167
+ metadata = superMeta;
1168
+ }
1127
1169
}
1128
1170
1129
1171
case MetadataKind::Struct:
@@ -1241,11 +1283,24 @@ class MetadataReader {
1241
1283
return substitutions;
1242
1284
}
1243
1285
1244
- BuiltType readNominalTypeFromMetadata (MetadataRef metadata) {
1245
- auto descriptorAddress = readAddressOfNominalTypeDescriptor (metadata);
1286
+ BuiltType readNominalTypeFromMetadata (MetadataRef origMetadata,
1287
+ bool skipArtificialSubclasses = false ) {
1288
+ auto metadata = origMetadata;
1289
+ auto descriptorAddress =
1290
+ readAddressOfNominalTypeDescriptor (metadata,
1291
+ skipArtificialSubclasses);
1246
1292
if (!descriptorAddress)
1247
1293
return BuiltType ();
1248
1294
1295
+ // If we've skipped an artificial subclasses, check the cache at
1296
+ // the superclass. (This also protects against recursion.)
1297
+ if (skipArtificialSubclasses &&
1298
+ metadata.getAddress () != origMetadata.getAddress ()) {
1299
+ auto it = TypeCache.find (metadata.getAddress ());
1300
+ if (it != TypeCache.end ())
1301
+ return it->second ;
1302
+ }
1303
+
1249
1304
// Read the nominal type descriptor.
1250
1305
auto descriptor = readNominalTypeDescriptor (descriptorAddress);
1251
1306
if (!descriptor)
@@ -1277,6 +1332,14 @@ class MetadataReader {
1277
1332
if (!nominal) return BuiltType ();
1278
1333
1279
1334
TypeCache[metadata.getAddress ()] = nominal;
1335
+
1336
+ // If we've skipped an artificial subclass, remove the
1337
+ // recursion-protection entry we made for it.
1338
+ if (skipArtificialSubclasses &&
1339
+ metadata.getAddress () != origMetadata.getAddress ()) {
1340
+ TypeCache.erase (origMetadata.getAddress ());
1341
+ }
1342
+
1280
1343
return nominal;
1281
1344
}
1282
1345
0 commit comments