@@ -498,9 +498,46 @@ class MetadataReader {
498
498
using OwnedProtocolDescriptorRef =
499
499
std::unique_ptr<const TargetProtocolDescriptor<Runtime>, delete_with_free>;
500
500
501
- // / Cached isa mask.
502
- StoredPointer isaMask;
503
- bool hasIsaMask = false ;
501
+ enum class IsaEncodingKind {
502
+ // / We haven't checked yet.
503
+ Unknown,
504
+
505
+ // / There was an error trying to find out the isa encoding.
506
+ Error,
507
+
508
+ // / There's no special isa encoding.
509
+ None,
510
+
511
+ // / There's an unconditional mask to apply to the isa pointer.
512
+ // / - IsaMask stores the mask.
513
+ Masked,
514
+
515
+ // / Isa pointers are indexed. If applying a mask yields a magic value,
516
+ // / applying a different mask and shifting yields an index into a global
517
+ // / array of class pointers. Otherwise, the isa pointer is just a raw
518
+ // / class pointer.
519
+ // / - IsaIndexMask stores the index mask.
520
+ // / - IsaIndexShift stores the index shift.
521
+ // / - IsaMagicMask stores the magic value mask.
522
+ // / - IsaMagicValue stores the magic value.
523
+ // / - IndexedClassesPointer stores the pointer to the start of the
524
+ // / indexed classes array; this is constant throughout the program.
525
+ // / - IndexedClassesCountPointer stores a pointer to the number
526
+ // / of elements in the indexed classes array.
527
+ Indexed
528
+ };
529
+
530
+ IsaEncodingKind IsaEncoding = IsaEncodingKind::Unknown;
531
+ union {
532
+ StoredPointer IsaMask;
533
+ StoredPointer IsaIndexMask;
534
+ };
535
+ StoredPointer IsaIndexShift;
536
+ StoredPointer IsaMagicMask;
537
+ StoredPointer IsaMagicValue;
538
+ StoredPointer IndexedClassesPointer;
539
+ StoredPointer IndexedClassesCountPointer;
540
+ StoredPointer LastIndexedClassesCount = 0 ;
504
541
505
542
public:
506
543
BuilderType Builder;
@@ -535,15 +572,12 @@ class MetadataReader {
535
572
536
573
// / Get the remote process's swift_isaMask.
537
574
std::pair<bool , StoredPointer> readIsaMask () {
538
- auto address = Reader->getSymbolAddress (" swift_isaMask" );
539
- if (!address)
540
- return {false , 0 };
575
+ auto encoding = getIsaEncoding ();
576
+ if (encoding != IsaEncodingKind::Masked)
577
+ // Still return success if there's no isa encoding at all.
578
+ return {encoding == IsaEncodingKind::None, 0 };
541
579
542
- if (!Reader->readInteger (address, &isaMask))
543
- return {false , 0 };
544
-
545
- hasIsaMask = true ;
546
- return {true , isaMask};
580
+ return {true , IsaMask};
547
581
}
548
582
549
583
// / Given a remote pointer to metadata, attempt to discover its MetadataKind.
@@ -774,20 +808,64 @@ class MetadataReader {
774
808
775
809
// / Read the isa pointer of a class or closure context instance and apply
776
810
// / the isa mask.
777
- std::pair<bool , StoredPointer> readMetadataFromInstance (
778
- StoredPointer ObjectAddress) {
779
- StoredPointer isaMaskValue = ~0 ;
780
- auto isaMask = readIsaMask ();
781
- if (isaMask.first )
782
- isaMaskValue = isaMask.second ;
783
-
784
- StoredPointer MetadataAddress;
785
- if (!Reader->readBytes (RemoteAddress (ObjectAddress),
786
- (uint8_t *)&MetadataAddress,
787
- sizeof (StoredPointer)))
811
+ std::pair<bool , StoredPointer>
812
+ readMetadataFromInstance (StoredPointer objectAddress) {
813
+ StoredPointer isa;
814
+ if (!Reader->readInteger (RemoteAddress (objectAddress), &isa))
788
815
return {false , 0 };
789
816
790
- return {true , MetadataAddress & isaMaskValue};
817
+ switch (getIsaEncoding ()) {
818
+ case IsaEncodingKind::Unknown:
819
+ case IsaEncodingKind::Error:
820
+ return {false , 0 };
821
+
822
+ case IsaEncodingKind::None:
823
+ return {true , isa};
824
+
825
+ case IsaEncodingKind::Masked:
826
+ return {true , isa & IsaMask};
827
+
828
+ case IsaEncodingKind::Indexed: {
829
+ // If applying the magic mask doesn't give us the magic value,
830
+ // it's not an indexed isa.
831
+ if ((isa & IsaMagicMask) != IsaMagicValue)
832
+ return {true , isa};
833
+
834
+ // Extract the index.
835
+ auto classIndex = (isa & IsaIndexMask) >> IsaIndexShift;
836
+
837
+ // 0 is never a valid index.
838
+ if (classIndex == 0 ) {
839
+ return {false , 0 };
840
+
841
+ // If the index is out of range, it's an error; but check for an
842
+ // update first. (This will also trigger the first time because
843
+ // we initialize LastIndexedClassesCount to 0).
844
+ } else if (classIndex >= LastIndexedClassesCount) {
845
+ StoredPointer count;
846
+ if (!Reader->readInteger (RemoteAddress (IndexedClassesCountPointer),
847
+ &count)) {
848
+ return {false , 0 };
849
+ }
850
+
851
+ LastIndexedClassesCount = count;
852
+ if (classIndex >= count) {
853
+ return {false , 0 };
854
+ }
855
+ }
856
+
857
+ // Find the address of the appropriate array element.
858
+ RemoteAddress eltPointer =
859
+ RemoteAddress (IndexedClassesPointer
860
+ + classIndex * sizeof (StoredPointer));
861
+ StoredPointer metadataPointer;
862
+ if (!Reader->readInteger (eltPointer, &metadataPointer)) {
863
+ return {false , 0 };
864
+ }
865
+
866
+ return {true , metadataPointer};
867
+ }
868
+ }
791
869
}
792
870
793
871
// / Read the parent type metadata from a nested nominal type metadata.
@@ -1241,6 +1319,66 @@ class MetadataReader {
1241
1319
return dataPtr;
1242
1320
}
1243
1321
1322
+ IsaEncodingKind getIsaEncoding () {
1323
+ if (IsaEncoding != IsaEncodingKind::Unknown)
1324
+ return IsaEncoding;
1325
+
1326
+ auto finish = [&](IsaEncodingKind result) -> IsaEncodingKind {
1327
+ IsaEncoding = result;
1328
+ return result;
1329
+ };
1330
+
1331
+ // / Look up the given global symbol and bind 'varname' to its
1332
+ // / address if its exists.
1333
+ # define tryFindSymbol (varname, symbolName ) \
1334
+ auto varname = Reader->getSymbolAddress (symbolName); \
1335
+ if (!varname) \
1336
+ return finish (IsaEncodingKind::Error)
1337
+ // / Read from the given pointer into 'dest'.
1338
+ # define tryReadSymbol (varname, dest ) do { \
1339
+ if (!Reader->readInteger (varname, &dest)) \
1340
+ return finish (IsaEncodingKind::Error); \
1341
+ } while (0 )
1342
+ // / Read from the given global symbol into 'dest'.
1343
+ # define tryFindAndReadSymbol (dest, symbolName ) do { \
1344
+ tryFindSymbol (_address, symbolName); \
1345
+ tryReadSymbol (_address, dest); \
1346
+ } while (0 )
1347
+
1348
+ // Check for the magic-mask symbol that indicates that the ObjC
1349
+ // runtime is using indexed ISAs.
1350
+ if (auto magicMaskAddress =
1351
+ Reader->getSymbolAddress (" objc_debug_indexed_isa_magic_mask" )) {
1352
+ tryReadSymbol (magicMaskAddress, IsaMagicMask);
1353
+ if (IsaMagicMask != 0 ) {
1354
+ tryFindAndReadSymbol (IsaMagicValue,
1355
+ " objc_debug_indexed_isa_magic_value" );
1356
+ tryFindAndReadSymbol (IsaIndexMask,
1357
+ " objc_debug_indexed_isa_index_mask" );
1358
+ tryFindAndReadSymbol (IsaIndexShift,
1359
+ " objc_debug_indexed_isa_index_shift" );
1360
+ tryFindSymbol (indexedClasses, " objc_indexed_classes" );
1361
+ IndexedClassesPointer = indexedClasses.getAddressData ();
1362
+ tryFindSymbol (indexedClassesCount, " objc_indexed_classes_count" );
1363
+ IndexedClassesCountPointer = indexedClassesCount.getAddressData ();
1364
+
1365
+ return finish (IsaEncodingKind::Indexed);
1366
+ }
1367
+ }
1368
+
1369
+ // Check for the ISA mask symbol. This has to come second because
1370
+ // the standard library will define this even if the ObjC runtime
1371
+ // doesn't use it.
1372
+ if (auto maskAddress = Reader->getSymbolAddress (" swift_isaMask" )) {
1373
+ tryReadSymbol (maskAddress, IsaMask);
1374
+ if (IsaMask != 0 ) {
1375
+ return finish (IsaEncodingKind::Masked);
1376
+ }
1377
+ }
1378
+
1379
+ return finish (IsaEncodingKind::None);
1380
+ }
1381
+
1244
1382
template <class T >
1245
1383
static constexpr T roundUpToAlignment (T offset, T alignment) {
1246
1384
return (offset + alignment - 1 ) & ~(alignment - 1 );
0 commit comments