@@ -171,6 +171,38 @@ class MetadataReader {
171
171
StoredPointer IndexedClassesCountPointer;
172
172
StoredPointer LastIndexedClassesCount = 0 ;
173
173
174
+ enum class TaggedPointerEncodingKind {
175
+ // / We haven't checked yet.
176
+ Unknown,
177
+
178
+ // / There was an error trying to find out the tagged pointer encoding.
179
+ Error,
180
+
181
+ // / The "extended" encoding.
182
+ // /
183
+ // / 1 bit: is-tagged
184
+ // / 3 bits: class index (for objc_debug_taggedpointer_classes[])
185
+ // / 60 bits: payload
186
+ // /
187
+ // / Class index 0b111 represents 256 additional classes:
188
+ // /
189
+ // / 1 bit: is-tagged
190
+ // / 3 bits: 0b111
191
+ // / 8 bits: extended class index (for objc_debug_taggedpointer_ext_classes[])
192
+ // / 54 bits: payload
193
+ Extended
194
+ };
195
+ TaggedPointerEncodingKind TaggedPointerEncoding =
196
+ TaggedPointerEncodingKind::Unknown;
197
+ StoredPointer TaggedPointerMask;
198
+ StoredPointer TaggedPointerSlotShift;
199
+ StoredPointer TaggedPointerSlotMask;
200
+ StoredPointer TaggedPointerClasses;
201
+ StoredPointer TaggedPointerExtendedMask;
202
+ StoredPointer TaggedPointerExtendedSlotShift;
203
+ StoredPointer TaggedPointerExtendedSlotMask;
204
+ StoredPointer TaggedPointerExtendedClasses;
205
+
174
206
Demangle::NodeFactory Factory;
175
207
176
208
Demangle::NodeFactory &getNodeFactory () { return Factory; }
@@ -463,10 +495,28 @@ class MetadataReader {
463
495
if (!Meta) return BuiltType ();
464
496
465
497
switch (Meta->getKind ()) {
466
- case MetadataKind::Class:
467
- if (!cast<TargetClassMetadata<Runtime>>(Meta)->isTypeMetadata ())
468
- return BuiltType ();
498
+ case MetadataKind::Class: {
499
+ auto classMeta = cast<TargetClassMetadata<Runtime>>(Meta);
500
+ if (!classMeta->isTypeMetadata ()) {
501
+ std::string className;
502
+ if (!readObjCClassName (MetadataAddress, className))
503
+ return BuiltType ();
504
+
505
+ auto BuiltObjCClass = Builder.createObjCClassType (std::move (className));
506
+ if (!BuiltObjCClass) {
507
+ // Try the superclass.
508
+ if (!classMeta->Superclass )
509
+ return BuiltType ();
510
+
511
+ return readTypeFromMetadata (classMeta->Superclass ,
512
+ skipArtificialSubclasses);
513
+ }
514
+
515
+ TypeCache[MetadataAddress] = BuiltObjCClass;
516
+ return BuiltObjCClass;
517
+ }
469
518
return readNominalTypeFromMetadata (Meta, skipArtificialSubclasses);
519
+ }
470
520
case MetadataKind::Struct:
471
521
case MetadataKind::Enum:
472
522
case MetadataKind::Optional:
@@ -657,10 +707,48 @@ class MetadataReader {
657
707
return buildContextMangling (context, Dem);
658
708
}
659
709
710
+ bool isTaggedPointer (StoredPointer objectAddress) {
711
+ if (getTaggedPointerEncoding () != TaggedPointerEncodingKind::Extended)
712
+ return false ;
713
+
714
+ return objectAddress & TaggedPointerMask;
715
+ }
716
+
717
+ // / Read the isa pointer of an Object-C tagged pointer value.
718
+ Optional<StoredPointer>
719
+ readMetadataFromTaggedPointer (StoredPointer objectAddress) {
720
+ auto readArrayElement = [&](StoredPointer base, StoredPointer tag)
721
+ -> Optional<StoredPointer> {
722
+ StoredPointer addr = base + tag * sizeof (StoredPointer);
723
+ StoredPointer isa;
724
+ if (!Reader->readInteger (RemoteAddress (addr), &isa))
725
+ return None;
726
+ return isa;
727
+ };
728
+
729
+ // Extended pointers have a tag of 0b111, using 8 additional bits
730
+ // to specify the class.
731
+ if (TaggedPointerExtendedMask != 0 &&
732
+ ((objectAddress & TaggedPointerExtendedMask)
733
+ == TaggedPointerExtendedMask)) {
734
+ auto tag = ((objectAddress >> TaggedPointerExtendedSlotShift) &
735
+ TaggedPointerExtendedSlotMask);
736
+ return readArrayElement (TaggedPointerExtendedClasses, tag);
737
+ }
738
+
739
+ // Basic tagged pointers use a 3 bit tag to specify the class.
740
+ auto tag = ((objectAddress >> TaggedPointerSlotShift) &
741
+ TaggedPointerSlotMask);
742
+ return readArrayElement (TaggedPointerClasses, tag);
743
+ }
744
+
660
745
// / Read the isa pointer of a class or closure context instance and apply
661
746
// / the isa mask.
662
747
Optional<StoredPointer>
663
748
readMetadataFromInstance (StoredPointer objectAddress) {
749
+ if (isTaggedPointer (objectAddress))
750
+ return readMetadataFromTaggedPointer (objectAddress);
751
+
664
752
StoredPointer isa;
665
753
if (!Reader->readInteger (RemoteAddress (objectAddress), &isa))
666
754
return None;
@@ -2290,9 +2378,71 @@ class MetadataReader {
2290
2378
}
2291
2379
}
2292
2380
2381
+ # undef tryFindSymbol
2382
+ # undef tryReadSymbol
2383
+ # undef tryFindAndReadSymbol
2384
+
2293
2385
return finish (IsaEncodingKind::None);
2294
2386
}
2295
2387
2388
+ TaggedPointerEncodingKind getTaggedPointerEncoding () {
2389
+ if (TaggedPointerEncoding != TaggedPointerEncodingKind::Unknown)
2390
+ return TaggedPointerEncoding;
2391
+
2392
+ auto finish = [&](TaggedPointerEncodingKind result)
2393
+ -> TaggedPointerEncodingKind {
2394
+ TaggedPointerEncoding = result;
2395
+ return result;
2396
+ };
2397
+
2398
+ // / Look up the given global symbol and bind 'varname' to its
2399
+ // / address if its exists.
2400
+ # define tryFindSymbol (varname, symbolName ) \
2401
+ auto varname = Reader->getSymbolAddress (symbolName); \
2402
+ if (!varname) \
2403
+ return finish (TaggedPointerEncodingKind::Error)
2404
+ // / Read from the given pointer into 'dest'.
2405
+ # define tryReadSymbol (varname, dest ) do { \
2406
+ if (!Reader->readInteger (varname, &dest)) \
2407
+ return finish (TaggedPointerEncodingKind::Error); \
2408
+ } while (0 )
2409
+ // / Read from the given global symbol into 'dest'.
2410
+ # define tryFindAndReadSymbol (dest, symbolName ) do { \
2411
+ tryFindSymbol (_address, symbolName); \
2412
+ tryReadSymbol (_address, dest); \
2413
+ } while (0 )
2414
+
2415
+ tryFindAndReadSymbol (TaggedPointerMask,
2416
+ " objc_debug_taggedpointer_mask" );
2417
+ tryFindAndReadSymbol (TaggedPointerSlotShift,
2418
+ " objc_debug_taggedpointer_slot_shift" );
2419
+ tryFindAndReadSymbol (TaggedPointerSlotMask,
2420
+ " objc_debug_taggedpointer_slot_mask" );
2421
+ tryFindSymbol (TaggedPointerClassesAddr,
2422
+ " objc_debug_taggedpointer_classes" );
2423
+ if (!TaggedPointerClassesAddr)
2424
+ finish (TaggedPointerEncodingKind::Error);
2425
+ TaggedPointerClasses = TaggedPointerClassesAddr.getAddressData ();
2426
+ tryFindAndReadSymbol (TaggedPointerExtendedMask,
2427
+ " objc_debug_taggedpointer_ext_mask" );
2428
+ tryFindAndReadSymbol (TaggedPointerExtendedSlotShift,
2429
+ " objc_debug_taggedpointer_ext_slot_shift" );
2430
+ tryFindAndReadSymbol (TaggedPointerExtendedSlotMask,
2431
+ " objc_debug_taggedpointer_ext_slot_mask" );
2432
+ tryFindSymbol (TaggedPointerExtendedClassesAddr,
2433
+ " objc_debug_taggedpointer_ext_classes" );
2434
+ if (!TaggedPointerExtendedClassesAddr)
2435
+ finish (TaggedPointerEncodingKind::Error);
2436
+ TaggedPointerExtendedClasses =
2437
+ TaggedPointerExtendedClassesAddr.getAddressData ();
2438
+
2439
+ # undef tryFindSymbol
2440
+ # undef tryReadSymbol
2441
+ # undef tryFindAndReadSymbol
2442
+
2443
+ return finish (TaggedPointerEncodingKind::Extended);
2444
+ }
2445
+
2296
2446
template <class T >
2297
2447
static constexpr T roundUpToAlignment (T offset, T alignment) {
2298
2448
return (offset + alignment - 1 ) & ~(alignment - 1 );
0 commit comments