mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Reflection: Fix class layout start offset calculations
Fixes <rdar://problem/29115967>.
This commit is contained in:
@@ -564,18 +564,18 @@ public:
|
||||
/// instance size and alignment.
|
||||
std::tuple<bool, unsigned, unsigned>
|
||||
readInstanceSizeAndAlignmentFromClassMetadata(StoredPointer MetadataAddress) {
|
||||
auto superMeta = readMetadata(MetadataAddress);
|
||||
if (!superMeta || superMeta->getKind() != MetadataKind::Class)
|
||||
auto meta = readMetadata(MetadataAddress);
|
||||
if (!meta || meta->getKind() != MetadataKind::Class)
|
||||
return std::make_tuple(false, 0, 0);
|
||||
|
||||
auto super = cast<TargetClassMetadata<Runtime>>(superMeta);
|
||||
auto classMeta = cast<TargetClassMetadata<Runtime>>(meta);
|
||||
|
||||
// See swift_initClassMetadata_UniversalStrategy()
|
||||
uint32_t size, align;
|
||||
if (super->isTypeMetadata()) {
|
||||
size = super->getInstanceSize();
|
||||
align = super->getInstanceAlignMask() + 1;
|
||||
} else {
|
||||
|
||||
// If this class is defined in Objective-C, return the value of the
|
||||
// InstanceStart field from the ROData.
|
||||
if (!classMeta->isTypeMetadata()) {
|
||||
// The following algorithm only works on the non-fragile Apple runtime.
|
||||
|
||||
// Grab the RO-data pointer. This part is not ABI.
|
||||
@@ -583,14 +583,71 @@ public:
|
||||
if (!roDataPtr)
|
||||
return std::make_tuple(false, 0, 0);
|
||||
|
||||
auto address = roDataPtr + sizeof(uint32_t) * 2;
|
||||
// Get the address of the InstanceStart field.
|
||||
auto address = roDataPtr + sizeof(uint32_t) * 1;
|
||||
|
||||
align = 16; // malloc alignment guarantee
|
||||
align = 16;
|
||||
|
||||
if (!Reader->readInteger(RemoteAddress(address), &size))
|
||||
return std::make_tuple(false, 0, 0);
|
||||
|
||||
assert((size & (align - 1)) == 0);
|
||||
return std::make_tuple(true, size, align);
|
||||
}
|
||||
|
||||
// Otherwise, it is a Swift class. Get the superclass.
|
||||
auto superAddr = readSuperClassFromClassMetadata(MetadataAddress);
|
||||
if (superAddr) {
|
||||
auto superMeta = readMetadata(superAddr);
|
||||
if (!superMeta || superMeta->getKind() != MetadataKind::Class)
|
||||
return std::make_tuple(false, 0, 0);
|
||||
|
||||
auto superclassMeta = cast<TargetClassMetadata<Runtime>>(superMeta);
|
||||
|
||||
// If the superclass is an Objective-C class, we start layout
|
||||
// from the InstanceSize of the superclass, aligned up to
|
||||
// 16 bytes.
|
||||
if (superclassMeta->isTypeMetadata()) {
|
||||
// Superclass is a Swift class. Get the size of an instance,
|
||||
// and start layout from that.
|
||||
size = superclassMeta->getInstanceSize();
|
||||
align = 1;
|
||||
|
||||
return std::make_tuple(true, size, align);
|
||||
}
|
||||
|
||||
std::string superName;
|
||||
if (!readObjCClassName(superAddr, superName))
|
||||
return std::make_tuple(false, 0, 0);
|
||||
|
||||
if (superName != "SwiftObject") {
|
||||
// Grab the RO-data pointer. This part is not ABI.
|
||||
StoredPointer roDataPtr = readObjCRODataPtr(superAddr);
|
||||
if (!roDataPtr)
|
||||
return std::make_tuple(false, 0, 0);
|
||||
|
||||
// Get the address of the InstanceSize field.
|
||||
auto address = roDataPtr + sizeof(uint32_t) * 2;
|
||||
|
||||
// malloc alignment boundary.
|
||||
align = 16;
|
||||
|
||||
if (!Reader->readInteger(RemoteAddress(address), &size))
|
||||
return std::make_tuple(false, 0, 0);
|
||||
|
||||
// Round up to the alignment boundary.
|
||||
size = (size + (align - 1)) & ~(align - 1);
|
||||
|
||||
return std::make_tuple(true, size, align);
|
||||
}
|
||||
|
||||
// Fall through.
|
||||
}
|
||||
|
||||
// No superclass, just an object header. 12 bytes on 32-bit, 16 on 64-bit
|
||||
size = Reader->getPointerSize() + sizeof(uint64_t);
|
||||
align = 1;
|
||||
|
||||
return std::make_tuple(true, size, align);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user