Skip to content

Commit 0ca8dec

Browse files
committed
[Tools] Add a library to build specialized generic metadata out of process.
This library uses GenericMetadataBuilder with a ReaderWriter that can read data and resolve pointers from MachO files, and emit a JSON representation of a dylib containing the built metadata. We use LLVM's binary file readers to parse the MachO files and resolve fixups so we can follow pointers. This code is somewhat MachO specific, but could be generalized to other formats that LLVM supports. rdar://116592577
1 parent feae5f1 commit 0ca8dec

File tree

31 files changed

+2477
-61
lines changed

31 files changed

+2477
-61
lines changed

CMakeLists.txt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,22 @@ option(SWIFT_BUILD_REMOTE_MIRROR
215215
"Build the Swift Remote Mirror Library"
216216
TRUE)
217217

218+
option(SWIFT_BUILD_TYPE_METADATA_EXTRACTOR
219+
"Build the Swift Type Metadata Extractor Library"
220+
TRUE)
221+
218222
option(SWIFT_BUILD_DYNAMIC_STDLIB
219223
"Build dynamic variants of the Swift standard library"
220224
TRUE)
221225

222226
option(SWIFT_BUILD_STATIC_STDLIB
223227
"Build static variants of the Swift standard library"
224228
FALSE)
225-
229+
226230
option(SWIFT_STDLIB_STATIC_PRINT
227231
"Build compile-time evaluated vprintf()"
228232
FALSE)
229-
233+
230234
option(SWIFT_STDLIB_ENABLE_UNICODE_DATA
231235
"Include Unicode data files in the standard library.
232236
NOTE: Disabling this will cause many String methods to crash."
@@ -1245,6 +1249,11 @@ if(SWIFT_BUILD_REMOTE_MIRROR)
12451249
message(STATUS "")
12461250
endif()
12471251

1252+
if(SWIFT_BUILD_TYPE_METADATA_EXTRACTOR)
1253+
message(STATUS "Building Swift Type Metadata Extractor for SDKs: ${SWIFT_SDKS}")
1254+
message(STATUS "")
1255+
endif()
1256+
12481257
#
12491258
# Find required dependencies.
12501259
#
@@ -1338,6 +1347,10 @@ else()
13381347
add_subdirectory(stdlib/public/SwiftRemoteMirror)
13391348
endif()
13401349

1350+
if(SWIFT_BUILD_TYPE_METADATA_EXTRACTOR)
1351+
add_subdirectory(stdlib/public/SwiftTypeMetadataExtractor)
1352+
endif()
1353+
13411354
# We might also want to build the things in libexec seaprately
13421355
if(SWIFT_BUILD_LIBEXEC)
13431356
add_subdirectory(stdlib/public/libexec)

cmake/modules/SwiftComponents.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
# * llvm-toolchain-dev-tools -- install LLVM development tools useful in a shared toolchain
7171
# * dev -- headers and libraries required to use Swift compiler as a library.
7272
set(_SWIFT_DEFINED_COMPONENTS
73-
"autolink-driver;back-deployment;compiler;clang-builtin-headers;clang-resource-dir-symlink;clang-builtin-headers-in-clang-resource-dir;libexec;stdlib;stdlib-experimental;sdk-overlay;static-mirror-lib;swift-syntax-lib;editor-integration;tools;testsuite-tools;toolchain-tools;toolchain-dev-tools;llvm-toolchain-dev-tools;dev;license;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers")
73+
"autolink-driver;back-deployment;compiler;clang-builtin-headers;clang-resource-dir-symlink;clang-builtin-headers-in-clang-resource-dir;libexec;stdlib;stdlib-experimental;sdk-overlay;static-mirror-lib;swift-syntax-lib;editor-integration;tools;testsuite-tools;toolchain-tools;toolchain-dev-tools;llvm-toolchain-dev-tools;dev;license;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers;swift-type-metadata-extractor;swift-type-metadata-extractor-headers")
7474

7575
# The default install components include all of the defined components, except
7676
# for the following exceptions.

include/swift/ABI/Metadata.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ template <typename Runtime>
151151
struct TargetTypeMetadataHeaderBase {
152152
/// A pointer to the value-witnesses for this type. This is only
153153
/// present for type metadata.
154-
TargetPointer<Runtime, const ValueWitnessTable> ValueWitnesses;
154+
TargetPointer<Runtime, const TargetValueWitnessTable<Runtime>> ValueWitnesses;
155155
};
156156

157157
template <typename Runtime>
@@ -329,7 +329,7 @@ struct TargetMetadata {
329329
return asFullMetadata(this)->layoutString;
330330
}
331331

332-
const ValueWitnessTable *getValueWitnesses() const {
332+
const TargetValueWitnessTable<Runtime> *getValueWitnesses() const {
333333
return asFullMetadata(this)->ValueWitnesses;
334334
}
335335

@@ -2979,7 +2979,7 @@ template <typename Runtime>
29792979
struct swift_ptrauth_struct_context_descriptor(ModuleContextDescriptor)
29802980
TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
29812981
/// The module name.
2982-
RelativeDirectPointer<const char, /*nullable*/ false> Name;
2982+
TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;
29832983

29842984
/// Is this module a special C-imported module?
29852985
bool isCImportedContext() const {
@@ -3036,7 +3036,7 @@ struct swift_ptrauth_struct_context_descriptor(ExtensionContextDescriptor)
30363036
///
30373037
/// Note that the Parent of the extension will be the module context the
30383038
/// extension is declared inside.
3039-
RelativeDirectPointer<const char> ExtendedContext;
3039+
TargetRelativeDirectPointer<Runtime, const char> ExtendedContext;
30403040

30413041
using TrailingGenericContextObjects::getGenericContext;
30423042

@@ -3527,10 +3527,10 @@ struct TargetGenericValueMetadataPattern final :
35273527

35283528
/// The value-witness table. Indirectable so that we can re-use tables
35293529
/// from other libraries if that seems wise.
3530-
TargetRelativeIndirectablePointer<Runtime, const ValueWitnessTable>
3530+
TargetRelativeIndirectablePointer<Runtime, const TargetValueWitnessTable<Runtime>>
35313531
ValueWitnesses;
35323532

3533-
const ValueWitnessTable *getValueWitnessesPattern() const {
3533+
const TargetValueWitnessTable<Runtime> *getValueWitnessesPattern() const {
35343534
return ValueWitnesses.get();
35353535
}
35363536

@@ -3825,9 +3825,11 @@ class swift_ptrauth_struct_context_descriptor(TypeContextDescriptor)
38253825
/*Nullable*/ true> AccessFunctionPtr;
38263826

38273827
/// A pointer to the field descriptor for the type, if any.
3828-
TargetRelativeDirectPointer<Runtime, const reflection::FieldDescriptor,
3829-
/*nullable*/ true> Fields;
3830-
3828+
TargetRelativeDirectPointer<Runtime,
3829+
const reflection::TargetFieldDescriptor<Runtime>,
3830+
/*nullable*/ true>
3831+
Fields;
3832+
38313833
bool isReflectable() const { return (bool)Fields; }
38323834

38333835
MetadataAccessFunction getAccessFunction() const {

include/swift/ABI/TargetLayout.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ struct RuntimeTarget<8> {
6363
};
6464

6565
namespace reflection {
66-
class FieldDescriptor;
66+
template <typename Runtime>
67+
class TargetFieldDescriptor;
6768
}
6869

6970
/// In-process native runtime target.

include/swift/Basic/RelativePointer.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,12 @@ class RelativeDirectPointerIntPairImpl {
590590
using ValueTy = PointeeTy;
591591
using PointerTy = PointeeTy*;
592592

593+
Offset getOffset() const & {
594+
return RelativeOffsetPlusInt & ~getMask();
595+
}
596+
593597
PointerTy getPointer() const & {
594-
Offset offset = (RelativeOffsetPlusInt & ~getMask());
598+
Offset offset = getOffset();
595599

596600
// Check for null.
597601
if (Nullable && offset == 0)
@@ -624,6 +628,7 @@ class RelativeDirectPointerIntPair<PointeeTy, IntTy, Nullable, Offset,
624628
{
625629
using super = RelativeDirectPointerIntPairImpl<PointeeTy, IntTy, Nullable, Offset>;
626630
public:
631+
using super::getOffset;
627632
using super::getPointer;
628633
using super::getInt;
629634
using super::getOpaqueValue;

include/swift/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ if(SWIFT_BUILD_REMOTE_MIRROR)
44
add_subdirectory(SwiftRemoteMirror)
55
endif()
66

7+
if(SWIFT_BUILD_TYPE_METADATA_EXTRACTOR)
8+
add_subdirectory(SwiftTypeMetadataExtractor)
9+
endif()
10+
711
if(SWIFT_INCLUDE_TOOLS)
812
configure_file(Config.h.in ${CMAKE_CURRENT_BINARY_DIR}/Config.h
913
ESCAPE_QUOTES @ONLY)

include/swift/Demangling/Demangle.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ class Node {
264264
// Only to be used by the demangler parsers.
265265
void removeChildAt(unsigned Pos);
266266

267+
void replaceChild(unsigned Pos, NodePointer Child);
268+
267269
// Reverses the order of children.
268270
void reverseChildren(size_t StartingAt = 0);
269271

include/swift/RemoteInspection/Records.h

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#ifndef SWIFT_REFLECTION_RECORDS_H
1818
#define SWIFT_REFLECTION_RECORDS_H
1919

20-
#include "swift/Basic/RelativePointer.h"
20+
#include "swift/ABI/TargetLayout.h"
2121
#include "swift/Demangling/Demangle.h"
2222
#include "llvm/ADT/ArrayRef.h"
2323

@@ -82,14 +82,15 @@ class FieldRecordFlags {
8282
}
8383
};
8484

85-
class FieldRecord {
85+
template <typename Runtime>
86+
class TargetFieldRecord {
8687
const FieldRecordFlags Flags;
8788

8889
public:
89-
const RelativeDirectPointer<const char> MangledTypeName;
90-
const RelativeDirectPointer<const char> FieldName;
90+
const TargetRelativeDirectPointer<Runtime, const char> MangledTypeName;
91+
const TargetRelativeDirectPointer<Runtime, const char> FieldName;
9192

92-
FieldRecord() = delete;
93+
TargetFieldRecord() = delete;
9394

9495
bool hasMangledTypeName() const {
9596
return MangledTypeName;
@@ -111,36 +112,37 @@ class FieldRecord {
111112
return Flags.isVar();
112113
}
113114
};
115+
using FieldRecord = TargetFieldRecord<InProcess>;
114116

115-
struct FieldRecordIterator {
116-
const FieldRecord *Cur;
117-
const FieldRecord * const End;
117+
template <typename Runtime>
118+
struct TargetFieldRecordIterator {
119+
const TargetFieldRecord<Runtime> *Cur;
120+
const TargetFieldRecord<Runtime> *const End;
118121

119-
FieldRecordIterator(const FieldRecord *Cur, const FieldRecord * const End)
120-
: Cur(Cur), End(End) {}
122+
TargetFieldRecordIterator(const TargetFieldRecord<Runtime> *Cur,
123+
const TargetFieldRecord<Runtime> *const End)
124+
: Cur(Cur), End(End) {}
121125

122-
const FieldRecord &operator*() const {
123-
return *Cur;
124-
}
126+
const TargetFieldRecord<Runtime> &operator*() const { return *Cur; }
125127

126-
const FieldRecord *operator->() const {
127-
return Cur;
128-
}
128+
const TargetFieldRecord<Runtime> *operator->() const { return Cur; }
129129

130-
FieldRecordIterator &operator++() {
130+
TargetFieldRecordIterator &operator++() {
131131
++Cur;
132132
return *this;
133133
}
134134

135-
bool operator==(const FieldRecordIterator &other) const {
135+
bool operator==(const TargetFieldRecordIterator &other) const {
136136
return Cur == other.Cur && End == other.End;
137137
}
138138

139-
bool operator!=(const FieldRecordIterator &other) const {
139+
bool operator!=(const TargetFieldRecordIterator &other) const {
140140
return !(*this == other);
141141
}
142142
};
143143

144+
using FieldRecordIterator = TargetFieldRecordIterator<InProcess>;
145+
144146
enum class FieldDescriptorKind : uint16_t {
145147
// Swift nominal types.
146148
Struct,
@@ -173,16 +175,17 @@ enum class FieldDescriptorKind : uint16_t {
173175

174176
// Field descriptors contain a collection of field records for a single
175177
// class, struct or enum declaration.
176-
class FieldDescriptor {
177-
const FieldRecord *getFieldRecordBuffer() const {
178-
return reinterpret_cast<const FieldRecord *>(this + 1);
178+
template <typename Runtime>
179+
class TargetFieldDescriptor {
180+
const TargetFieldRecord<Runtime> *getFieldRecordBuffer() const {
181+
return reinterpret_cast<const TargetFieldRecord<Runtime> *>(this + 1);
179182
}
180183

181184
public:
182-
const RelativeDirectPointer<const char> MangledTypeName;
183-
const RelativeDirectPointer<const char> Superclass;
185+
const TargetRelativeDirectPointer<Runtime, const char> MangledTypeName;
186+
const TargetRelativeDirectPointer<Runtime, const char> Superclass;
184187

185-
FieldDescriptor() = delete;
188+
TargetFieldDescriptor() = delete;
186189

187190
const FieldDescriptorKind Kind;
188191
const uint16_t FieldRecordSize;
@@ -222,7 +225,7 @@ class FieldDescriptor {
222225
return const_iterator { End, End };
223226
}
224227

225-
llvm::ArrayRef<FieldRecord> getFields() const {
228+
llvm::ArrayRef<TargetFieldRecord<Runtime>> getFields() const {
226229
return {getFieldRecordBuffer(), NumFields};
227230
}
228231

@@ -242,6 +245,7 @@ class FieldDescriptor {
242245
return Demangle::makeSymbolicMangledNameStringRef(Superclass.get());
243246
}
244247
};
248+
using FieldDescriptor = TargetFieldDescriptor<InProcess>;
245249

246250
// Associated type records describe the mapping from an associated
247251
// type to the type witness of a conformance.

include/swift/Runtime/Enum.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "swift/Runtime/Config.h"
2121

2222
namespace swift {
23-
23+
2424
struct OpaqueValue;
2525
struct InProcess;
2626

@@ -139,7 +139,7 @@ void swift_initEnumMetadataMultiPayloadWithLayoutString(EnumMetadata *enumType,
139139
SWIFT_RUNTIME_EXPORT
140140
unsigned swift_getEnumCaseMultiPayload(const OpaqueValue *value,
141141
const EnumMetadata *enumType);
142-
142+
143143
/// Store the tag value for the given case into a multi-payload enum,
144144
/// whose associated payload (if any) has already been initialized.
145145
SWIFT_RUNTIME_EXPORT

include/swift/Runtime/GenericMetadataBuilder.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ class GenericMetadataBuilder {
313313
installGenericArguments(WritableData<FullMetadata<Metadata>> data,
314314
Size metadataOffset,
315315
Buffer<const ValueTypeDescriptor> descriptionBuffer,
316-
const GenericArgument *arguments) {
316+
llvm::ArrayRef<GenericArgument> arguments) {
317317
METADATA_BUILDER_LOG("Building %s",
318318
ERROR_CHECK(getDescriptorName(descriptionBuffer)));
319319
char *metadataBase = reinterpret_cast<char *>(data.ptr);
@@ -325,6 +325,11 @@ class GenericMetadataBuilder {
325325
(reinterpret_cast<Pointer<const Metadata> *>(metadata) +
326326
getGenericArgumentOffset(
327327
descriptionBuffer.template cast<const TypeContextDescriptor>()));
328+
329+
if (arguments.size() < header.NumKeyArguments) {
330+
return BuilderError("Not enough generic arguments, %zu provided, %" PRId32 " required", arguments.size(), header.NumKeyArguments);
331+
}
332+
328333
METADATA_BUILDER_LOG(
329334
"Installing %" PRIu16 " generic arguments at offset %" PRId32,
330335
header.NumKeyArguments,
@@ -353,7 +358,7 @@ class GenericMetadataBuilder {
353358
/// Allocate and build a metadata structure.
354359
BuilderErrorOr<ConstructedMetadata>
355360
buildGenericMetadata(Buffer<const TypeContextDescriptor> descriptionBuffer,
356-
const GenericArgument *arguments,
361+
llvm::ArrayRef<GenericArgument> arguments,
357362
Buffer<const GenericMetadataPattern> patternBuffer,
358363
size_t extraDataSize) {
359364
auto description = descriptionBuffer.ptr;
@@ -377,7 +382,7 @@ class GenericMetadataBuilder {
377382

378383
BuilderErrorOr<ConstructedMetadata> buildGenericValueMetadata(
379384
Buffer<const ValueTypeDescriptor> descriptionBuffer,
380-
const GenericArgument *arguments,
385+
llvm::ArrayRef<GenericArgument> arguments,
381386
Buffer<const GenericValueMetadataPattern> patternBuffer,
382387
size_t extraDataSize) {
383388
auto *pattern = patternBuffer.ptr;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(swift_type_metadata_extractor_headers)
2+
list(APPEND swift_type_metadata_extractor_headers
3+
SwiftTypeMetadataExtractor.h
4+
module.modulemap)
5+
swift_install_in_component(FILES
6+
${swift_type_metadata_extractor_headers}
7+
DESTINATION
8+
"include/swift/SwiftTypeMetadataExtractor"
9+
COMPONENT
10+
swift-type-metadata-extractor-headers)

0 commit comments

Comments
 (0)