Skip to content

Commit 0b4ae4d

Browse files
authored
Merge pull request #85462 from mikeash/remote-mirror-function-type-global-actor-fix
[Reflection] Improve size computation for remote type metadata reading.
2 parents 99f27fc + d6fc306 commit 0b4ae4d

File tree

3 files changed

+148
-96
lines changed

3 files changed

+148
-96
lines changed

include/swift/ABI/TrailingObjects.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,15 @@ class swift_ptrauth_struct_derived(BaseTy) TrailingObjects
421421
}
422422
};
423423

424+
// Helper function to determine at build time if a type has TrailingObjects.
425+
// This is useful for determining if trailingTypeCount and
426+
// sizeWithTrailingTypeCount are available for code that reads TrailingObjects
427+
// values in a generalized fashion.
428+
template <typename T>
429+
static constexpr bool typeHasTrailingObjects() {
430+
return std::is_base_of_v<trailing_objects_internal::TrailingObjectsBase, T>;
431+
}
432+
424433
} // end namespace ABI
425434
} // end namespace swift
426435

include/swift/Remote/MetadataReader.h

Lines changed: 80 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,33 +1493,33 @@ class MetadataReader {
14931493
break;
14941494
case ContextDescriptorKind::Extension:
14951495
success =
1496-
readFullContextDescriptor<TargetExtensionContextDescriptor<Runtime>>(
1497-
remoteAddress, ptr);
1496+
readFullTrailingObjects<TargetExtensionContextDescriptor<Runtime>>(
1497+
remoteAddress, ptr, sizeof(TargetContextDescriptor<Runtime>));
14981498
break;
14991499
case ContextDescriptorKind::Anonymous:
15001500
success =
1501-
readFullContextDescriptor<TargetAnonymousContextDescriptor<Runtime>>(
1502-
remoteAddress, ptr);
1501+
readFullTrailingObjects<TargetAnonymousContextDescriptor<Runtime>>(
1502+
remoteAddress, ptr, sizeof(TargetContextDescriptor<Runtime>));
15031503
break;
15041504
case ContextDescriptorKind::Class:
1505-
success = readFullContextDescriptor<TargetClassDescriptor<Runtime>>(
1506-
remoteAddress, ptr);
1505+
success = readFullTrailingObjects<TargetClassDescriptor<Runtime>>(
1506+
remoteAddress, ptr, sizeof(TargetContextDescriptor<Runtime>));
15071507
break;
15081508
case ContextDescriptorKind::Enum:
1509-
success = readFullContextDescriptor<TargetEnumDescriptor<Runtime>>(
1510-
remoteAddress, ptr);
1509+
success = readFullTrailingObjects<TargetEnumDescriptor<Runtime>>(
1510+
remoteAddress, ptr, sizeof(TargetContextDescriptor<Runtime>));
15111511
break;
15121512
case ContextDescriptorKind::Struct:
1513-
success = readFullContextDescriptor<TargetStructDescriptor<Runtime>>(
1514-
remoteAddress, ptr);
1513+
success = readFullTrailingObjects<TargetStructDescriptor<Runtime>>(
1514+
remoteAddress, ptr, sizeof(TargetContextDescriptor<Runtime>));
15151515
break;
15161516
case ContextDescriptorKind::Protocol:
1517-
success = readFullContextDescriptor<TargetProtocolDescriptor<Runtime>>(
1518-
remoteAddress, ptr);
1517+
success = readFullTrailingObjects<TargetProtocolDescriptor<Runtime>>(
1518+
remoteAddress, ptr, sizeof(TargetContextDescriptor<Runtime>));
15191519
break;
15201520
case ContextDescriptorKind::OpaqueType:
1521-
success = readFullContextDescriptor<TargetOpaqueTypeDescriptor<Runtime>>(
1522-
remoteAddress, ptr);
1521+
success = readFullTrailingObjects<TargetOpaqueTypeDescriptor<Runtime>>(
1522+
remoteAddress, ptr, sizeof(TargetContextDescriptor<Runtime>));
15231523
break;
15241524
default:
15251525
// We don't know about this kind of context.
@@ -1535,12 +1535,18 @@ class MetadataReader {
15351535
return ContextDescriptorRef(remoteAddress, descriptor);
15361536
}
15371537

1538-
template <typename DescriptorTy>
1539-
bool readFullContextDescriptor(RemoteAddress address,
1540-
MemoryReader::ReadBytesResult &ptr) {
1538+
/// Read all memory occupied by a value with TrailingObjects. This will
1539+
/// incrementally read pieces of the object to figure out the full size of it.
1540+
/// - address: The address of the value.
1541+
/// - ptr: The bytes that have been read so far. On return, the full object.
1542+
/// - existingByteCount: The number of bytes in ptr.
1543+
template <typename BaseTy>
1544+
bool readFullTrailingObjects(RemoteAddress address,
1545+
MemoryReader::ReadBytesResult &ptr,
1546+
size_t existingByteCount) {
15411547
// Read the full base descriptor if it's bigger than what we have so far.
1542-
if (sizeof(DescriptorTy) > sizeof(TargetContextDescriptor<Runtime>)) {
1543-
ptr = Reader->template readObj<DescriptorTy>(address);
1548+
if (sizeof(BaseTy) > existingByteCount) {
1549+
ptr = Reader->template readObj<BaseTy>(address);
15441550
if (!ptr)
15451551
return false;
15461552
}
@@ -1556,13 +1562,17 @@ class MetadataReader {
15561562
// size. Once we've walked through all the trailing objects, we've read
15571563
// everything.
15581564

1559-
size_t sizeSoFar = sizeof(DescriptorTy);
1565+
size_t sizeSoFar = sizeof(BaseTy);
15601566

1561-
for (size_t i = 0; i < DescriptorTy::trailingTypeCount(); i++) {
1562-
const DescriptorTy *descriptorSoFar =
1563-
reinterpret_cast<const DescriptorTy *>(ptr.get());
1567+
for (size_t i = 0; i < BaseTy::trailingTypeCount(); i++) {
1568+
const BaseTy *descriptorSoFar =
1569+
reinterpret_cast<const BaseTy *>(ptr.get());
15641570
size_t thisSize = descriptorSoFar->sizeWithTrailingTypeCount(i);
15651571
if (thisSize > sizeSoFar) {
1572+
// Make sure we haven't ended up with a ridiculous size.
1573+
if (thisSize > MaxMetadataSize)
1574+
return false;
1575+
15661576
ptr = Reader->readBytes(address, thisSize);
15671577
if (!ptr)
15681578
return false;
@@ -2141,45 +2151,22 @@ class MetadataReader {
21412151

21422152
switch (getEnumeratedMetadataKind(KindValue)) {
21432153
case MetadataKind::Class:
2144-
2145-
return _readMetadata<TargetClassMetadataType>(address);
2146-
2154+
return _readMetadataFixedSize<TargetClassMetadataType>(address);
21472155
case MetadataKind::Enum:
2148-
return _readMetadata<TargetEnumMetadata>(address);
2156+
return _readMetadataFixedSize<TargetEnumMetadata>(address);
21492157
case MetadataKind::ErrorObject:
2150-
return _readMetadata<TargetEnumMetadata>(address);
2151-
case MetadataKind::Existential: {
2152-
RemoteAddress flagsAddress = address + sizeof(StoredPointer);
2153-
2154-
ExistentialTypeFlags::int_type flagsData;
2155-
if (!Reader->readInteger(flagsAddress, &flagsData))
2156-
return nullptr;
2157-
2158-
ExistentialTypeFlags flags(flagsData);
2159-
2160-
RemoteAddress numProtocolsAddress = flagsAddress + sizeof(flagsData);
2161-
uint32_t numProtocols;
2162-
if (!Reader->readInteger(numProtocolsAddress, &numProtocols))
2163-
return nullptr;
2164-
2165-
// Make sure the number of protocols is reasonable
2166-
if (numProtocols >= 256)
2167-
return nullptr;
2168-
2169-
auto totalSize = sizeof(TargetExistentialTypeMetadata<Runtime>)
2170-
+ numProtocols *
2171-
sizeof(ConstTargetMetadataPointer<Runtime, TargetProtocolDescriptor>);
2172-
2173-
if (flags.hasSuperclassConstraint())
2174-
totalSize += sizeof(StoredPointer);
2175-
2176-
return _readMetadata(address, totalSize);
2177-
}
2158+
return _readMetadataFixedSize<TargetMetadata>(address);
2159+
case MetadataKind::Existential:
2160+
return _readMetadataVariableSize<TargetExistentialTypeMetadata>(
2161+
address);
21782162
case MetadataKind::ExistentialMetatype:
2179-
return _readMetadata<TargetExistentialMetatypeMetadata>(address);
2163+
return _readMetadataFixedSize<TargetExistentialMetatypeMetadata>(
2164+
address);
21802165
case MetadataKind::ExtendedExistential: {
21812166
// We need to read the shape in order to figure out how large
2182-
// the generalization arguments are.
2167+
// the generalization arguments are. This prevents us from using
2168+
// _readMetadataVariableSize, which requires the Shape field to be
2169+
// dereferenceable here.
21832170
RemoteAddress shapeAddress = address + sizeof(StoredPointer);
21842171
RemoteAddress signedShapePtr;
21852172
if (!Reader->template readRemoteAddress<StoredPointer>(shapeAddress,
@@ -2198,46 +2185,24 @@ class MetadataReader {
21982185
return _readMetadata(address, totalSize);
21992186
}
22002187
case MetadataKind::ForeignClass:
2201-
return _readMetadata<TargetForeignClassMetadata>(address);
2188+
return _readMetadataFixedSize<TargetForeignClassMetadata>(address);
22022189
case MetadataKind::ForeignReferenceType:
2203-
return _readMetadata<TargetForeignReferenceTypeMetadata>(address);
2204-
case MetadataKind::Function: {
2205-
StoredSize flagsValue;
2206-
auto flagsAddr =
2207-
address + TargetFunctionTypeMetadata<Runtime>::OffsetToFlags;
2208-
if (!Reader->readInteger(flagsAddr, &flagsValue))
2209-
return nullptr;
2210-
2211-
auto flags =
2212-
TargetFunctionTypeFlags<StoredSize>::fromIntValue(flagsValue);
2213-
2214-
auto totalSize =
2215-
sizeof(TargetFunctionTypeMetadata<Runtime>) +
2216-
flags.getNumParameters() * sizeof(FunctionTypeMetadata::Parameter);
2217-
2218-
if (flags.hasParameterFlags())
2219-
totalSize += flags.getNumParameters() * sizeof(uint32_t);
2220-
2221-
if (flags.isDifferentiable())
2222-
totalSize = roundUpToAlignment(totalSize, sizeof(StoredPointer)) +
2223-
sizeof(TargetFunctionMetadataDifferentiabilityKind<
2224-
typename Runtime::StoredSize>);
2225-
2226-
return _readMetadata(address,
2227-
roundUpToAlignment(totalSize, sizeof(StoredPointer)));
2228-
}
2190+
return _readMetadataFixedSize<TargetForeignReferenceTypeMetadata>(
2191+
address);
2192+
case MetadataKind::Function:
2193+
return _readMetadataVariableSize<TargetFunctionTypeMetadata>(address);
22292194
case MetadataKind::HeapGenericLocalVariable:
2230-
return _readMetadata<TargetGenericBoxHeapMetadata>(address);
2195+
return _readMetadataFixedSize<TargetGenericBoxHeapMetadata>(address);
22312196
case MetadataKind::HeapLocalVariable:
2232-
return _readMetadata<TargetHeapLocalVariableMetadata>(address);
2197+
return _readMetadataFixedSize<TargetHeapLocalVariableMetadata>(address);
22332198
case MetadataKind::Metatype:
2234-
return _readMetadata<TargetMetatypeMetadata>(address);
2199+
return _readMetadataFixedSize<TargetMetatypeMetadata>(address);
22352200
case MetadataKind::ObjCClassWrapper:
2236-
return _readMetadata<TargetObjCClassWrapperMetadata>(address);
2201+
return _readMetadataFixedSize<TargetObjCClassWrapperMetadata>(address);
22372202
case MetadataKind::Optional:
2238-
return _readMetadata<TargetEnumMetadata>(address);
2203+
return _readMetadataFixedSize<TargetEnumMetadata>(address);
22392204
case MetadataKind::Struct:
2240-
return _readMetadata<TargetStructMetadata>(address);
2205+
return _readMetadataFixedSize<TargetStructMetadata>(address);
22412206
case MetadataKind::Tuple: {
22422207
auto numElementsAddress = address +
22432208
TargetTupleTypeMetadata<Runtime>::getOffsetToNumElements();
@@ -2255,7 +2220,7 @@ class MetadataReader {
22552220
}
22562221
case MetadataKind::Opaque:
22572222
default:
2258-
return _readMetadata<TargetOpaqueMetadata>(address);
2223+
return _readMetadataFixedSize<TargetOpaqueMetadata>(address);
22592224
}
22602225

22612226
// We can fall out here if the value wasn't actually a valid
@@ -2333,20 +2298,39 @@ class MetadataReader {
23332298

23342299
private:
23352300
template <template <class R> class M>
2336-
MetadataRef _readMetadata(RemoteAddress address) {
2301+
MetadataRef _readMetadataFixedSize(RemoteAddress address) {
2302+
static_assert(!ABI::typeHasTrailingObjects<M<Runtime>>(),
2303+
"Type must not have trailing objects. Use "
2304+
"_readMetadataVariableSize for types that have them.");
2305+
23372306
return _readMetadata(address, sizeof(M<Runtime>));
23382307
}
23392308

2309+
template <template <class R> class M>
2310+
MetadataRef _readMetadataVariableSize(RemoteAddress address) {
2311+
static_assert(ABI::typeHasTrailingObjects<M<Runtime>>(),
2312+
"Type must have trailing objects. Use _readMetadataFixedSize "
2313+
"for types that don't.");
2314+
2315+
MemoryReader::ReadBytesResult bytes;
2316+
auto readResult = readFullTrailingObjects<M<Runtime>>(address, bytes, 0);
2317+
if (!readResult)
2318+
return nullptr;
2319+
return _cacheMetadata(address, bytes);
2320+
}
2321+
23402322
MetadataRef _readMetadata(RemoteAddress address, size_t sizeAfter) {
23412323
if (sizeAfter > MaxMetadataSize)
23422324
return nullptr;
23432325
auto readResult = Reader->readBytes(address, sizeAfter);
2344-
if (!readResult)
2345-
return nullptr;
2326+
return _cacheMetadata(address, readResult);
2327+
}
23462328

2329+
MetadataRef _cacheMetadata(RemoteAddress address,
2330+
MemoryReader::ReadBytesResult &bytes) {
23472331
auto metadata =
2348-
reinterpret_cast<const TargetMetadata<Runtime> *>(readResult.get());
2349-
MetadataCache.insert(std::make_pair(address, std::move(readResult)));
2332+
reinterpret_cast<const TargetMetadata<Runtime> *>(bytes.get());
2333+
MetadataCache.insert(std::make_pair(address, std::move(bytes)));
23502334
return MetadataRef(address, metadata);
23512335
}
23522336

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Target Swift 5.5 so functions with global actors are encoded as a proper
2+
// mangled name, not a function accessor. Remote Mirror can't call function
3+
// accessors and will fail to read the type.
4+
// RUN: %empty-directory(%t)
5+
// RUN: %target-build-swift -target %target-swift-5.5-abi-triple -lswiftSwiftReflectionTest %s -o %t/function_types
6+
// RUN: %target-codesign %t/function_types
7+
8+
// RUN: %target-run %target-swift-reflection-test %t/function_types | %FileCheck %s --check-prefix=CHECK
9+
10+
// REQUIRES: reflection_test_support
11+
// REQUIRES: executable_test
12+
// UNSUPPORTED: use_os_stdlib
13+
// UNSUPPORTED: asan
14+
15+
import SwiftReflectionTest
16+
17+
struct S {
18+
var f = { @MainActor in }
19+
}
20+
21+
// This Task is necessary to ensure that the concurrency runtime is brought in.
22+
// Without that, the type lookup for @MainActor may fail.
23+
Task {}
24+
25+
// CHECK: Type reference:
26+
// CHECK: (struct function_types.S)
27+
28+
// CHECK: Type info:
29+
// CHECK: (struct size=
30+
// CHECK: (field name=f offset=0
31+
// CHECK: (thick_function size=
32+
// CHECK: (field name=function offset=0
33+
// CHECK: (builtin size=
34+
// CHECK: (field name=context
35+
// CHECK: (reference kind=strong refcounting=native)))))
36+
// CHECK: Mangled name: $s14function_types1SV
37+
// CHECK: Demangled name: function_types.S
38+
reflect(any: S())
39+
40+
// CHECK: Type reference:
41+
// CHECK: (function
42+
// CHECK: (global-actor
43+
// CHECK: (class Swift.MainActor))
44+
// CHECK: (parameters)
45+
// CHECK: (result
46+
// CHECK: (tuple))
47+
48+
// CHECK: Type info:
49+
// CHECK: (thick_function size=
50+
// CHECK: (field name=function offset=0
51+
// CHECK: (builtin size=
52+
// CHECK: (field name=context offset=
53+
// CHECK: (reference kind=strong refcounting=native)))
54+
// CHECK: Mangled name: $syyScMYcc
55+
// CHECK: Demangled name: @Swift.MainActor () -> ()
56+
reflect(any: S().f)
57+
58+
doneReflecting()
59+

0 commit comments

Comments
 (0)