Skip to content

Commit db61333

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 db61333

40 files changed

+3481
-211
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_EXTERNAL_GENERIC_METADATA_BUILDER
219+
"Build the Swift External Generic Metadata Builder 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_EXTERNAL_GENERIC_METADATA_BUILDER)
1253+
message(STATUS "Building Swift External Generic Metadata Builder 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_EXTERNAL_GENERIC_METADATA_BUILDER)
1351+
add_subdirectory(stdlib/public/ExternalGenericMetadataBuilder)
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-external-generic-metadata-builder;swift-external-generic-metadata-builder-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_EXTERNAL_GENERIC_METADATA_BUILDER)
8+
add_subdirectory(ExternalGenericMetadataBuilder)
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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(swift_external_generic_metadata_builder_headers)
2+
list(APPEND swift_external_generic_metadata_builder_headers
3+
ExternalGenericMetadataBuilder.h
4+
module.modulemap)
5+
swift_install_in_component(FILES
6+
${swift_external_generic_metadata_builder_headers}
7+
DESTINATION
8+
"include/swift/ExternalGenericMetadataBuilder"
9+
COMPONENT
10+
swift-external-generic-metadata-builder-headers)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===--- ExternalGenericMetadataBuilder.h - Public interface ----*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file
14+
/// This header declares functions in the libswiftReflection library,
15+
/// which provides mechanisms for reflecting heap information in a
16+
/// remote Swift process.
17+
///
18+
//===----------------------------------------------------------------------===//
19+
20+
#ifndef SWIFT_EXTERNAL_GENERIC_METADATA_BUILDER_H
21+
#define SWIFT_EXTERNAL_GENERIC_METADATA_BUILDER_H
22+
23+
#include <stdint.h>
24+
25+
#include "swift/shims/Visibility.h"
26+
27+
#ifdef __cplusplus
28+
extern "C" {
29+
#endif
30+
31+
struct SwiftExternalMetadataBuilder;
32+
struct mach_header;
33+
34+
// Create a builder object with the given platform and architecture name.
35+
SWIFT_ATTRIBUTE_FOR_EXPORTS
36+
struct SwiftExternalMetadataBuilder *
37+
swift_externalMetadataBuilder_create(int platform, const char *arch);
38+
39+
// Destroy a builder object.
40+
SWIFT_ATTRIBUTE_FOR_EXPORTS
41+
void swift_externalMetadataBuilder_destroy(
42+
struct SwiftExternalMetadataBuilder *);
43+
44+
// Returns an error string if the dylib could not be added
45+
// The builder owns the string, so the caller does not have to free it
46+
// The mach_header* is the raw dylib from disk/memory, before the shared cache
47+
// builder has created its own copy of it
48+
SWIFT_ATTRIBUTE_FOR_EXPORTS
49+
const char *swift_externalMetadataBuilder_addDylib(
50+
struct SwiftExternalMetadataBuilder *, const char *install_name,
51+
const struct mach_header *, uint64_t size);
52+
53+
SWIFT_ATTRIBUTE_FOR_EXPORTS
54+
const char *swift_externalMetadataBuilder_readNamesJSON(
55+
struct SwiftExternalMetadataBuilder *, const char *names_json);
56+
57+
// Returns an error string if the dylib could not be added
58+
// The builder owns the string, so the caller does not have to free it
59+
SWIFT_ATTRIBUTE_FOR_EXPORTS
60+
const char *swift_externalMetadataBuilder_buildMetadata(
61+
struct SwiftExternalMetadataBuilder *);
62+
63+
// Get the JSON for the built metadata.
64+
SWIFT_ATTRIBUTE_FOR_EXPORTS
65+
const char *swift_externalMetadataBuilder_getMetadataJSON(
66+
struct SwiftExternalMetadataBuilder *);
67+
68+
// Convenience function that works with the filesystem and handles everything in
69+
// one call.
70+
SWIFT_ATTRIBUTE_FOR_EXPORTS
71+
int swift_type_metadata_extract(const char *inputPath, // mangled names
72+
const char *dylibSearchPath, // images to add
73+
const char *arch,
74+
const char *outputPath // json output
75+
);
76+
77+
#ifdef __cplusplus
78+
} // extern "C"
79+
#endif
80+
81+
#endif // SWIFT_EXTERNAL_GENERIC_METADATA_BUILDER_H
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module ExternalGenericMetadataBuilder {
2+
header "ExternalGenericMetadataBuilder.h"
3+
export *
4+
}

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.

0 commit comments

Comments
 (0)