Skip to content

Commit 47be50c

Browse files
committed
[RemoteMirror] Update interop to handle 4.2 libraries.
The Remote Mirror interop header now accepts an arbitrary number of remote mirror libraries so that it can have 4.1, 4.2, and 5.0 loaded side by side. rdar://problem/45808282
1 parent 5ade8dd commit 47be50c

File tree

6 files changed

+121
-126
lines changed

6 files changed

+121
-126
lines changed

include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,19 @@
3737
static inline SwiftReflectionInteropContextRef
3838
swift_reflection_interop_createReflectionContext(
3939
void *ReaderContext,
40-
void *LibraryHandle,
41-
void *LegacyLibraryHandle,
4240
uint8_t PointerSize,
4341
FreeBytesFunction FreeBytes,
4442
ReadBytesFunction ReadBytes,
4543
GetStringLengthFunction GetStringLength,
4644
GetSymbolAddressFunction GetSymbolAddress);
4745

46+
/// Add a library handle to the interop context. Returns 1 if the
47+
/// library was added successfully, 0 if a symbol couldn't be looked up
48+
/// or the reported metadata version is too old.
49+
static inline int
50+
swift_reflection_interop_addLibrary(
51+
SwiftReflectionInteropContextRef ContextRef, void *LibraryHandle);
52+
4853
static inline void
4954
swift_reflection_interop_destroyReflectionContext(
5055
SwiftReflectionInteropContextRef ContextRef);
@@ -283,6 +288,7 @@ struct SwiftReflectionInteropContextLegacyImageRangeList {
283288

284289
struct SwiftReflectionInteropContext {
285290
void *ReaderContext;
291+
uint8_t PointerSize;
286292
FreeBytesFunction FreeBytes;
287293
ReadBytesFunction ReadBytes;
288294
uint64_t (*GetStringLength)(void *reader_context,
@@ -291,8 +297,7 @@ struct SwiftReflectionInteropContext {
291297
const char *name,
292298
uint64_t name_length);
293299

294-
// Currently we support at most two libraries.
295-
struct SwiftReflectionInteropContextLibrary Libraries[2];
300+
struct SwiftReflectionInteropContextLibrary *Libraries;
296301
int LibraryCount;
297302

298303
struct SwiftReflectionInteropContextFreeList *FreeList;
@@ -381,12 +386,11 @@ swift_reflection_interop_libraryForObject(
381386
return swift_reflection_interop_libraryForAddress(ContextRef, Metadata);
382387
}
383388

384-
static inline void
389+
static inline int
385390
swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Context,
386-
void *Handle,
387-
int IsLegacy) {
391+
void *Handle) {
388392
if (Handle == NULL)
389-
return;
393+
return 0;
390394

391395
struct SwiftReflectionInteropContextLibrary *Library = &Context
392396
->Libraries[Context->LibraryCount];
@@ -397,14 +401,16 @@ swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Con
397401
#endif
398402
#define LOAD_NAMED(field, symbol) do { \
399403
Functions->field = (decltype(Functions->field))dlsym(Handle, symbol); \
400-
if (Functions->field == NULL) return; \
404+
if (Functions->field == NULL) return 0; \
401405
} while (0)
402406
#define LOAD(name) LOAD_NAMED(name, "swift_reflection_" #name)
403407

404408
LOAD(getSupportedMetadataVersion);
405409
uint16_t version = Functions->getSupportedMetadataVersion();
406410
if (version < SWIFT_LEGACY_METADATA_MIN_VERSION)
407-
return;
411+
return 0;
412+
413+
int IsLegacy = dlsym(Handle, "swift_reflection_addImage") == NULL;
408414

409415
if (IsLegacy) {
410416
LOAD_NAMED(createReflectionContextLegacy, "swift_reflection_createReflectionContext");
@@ -438,7 +444,7 @@ swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Con
438444
Library->IsLegacy = IsLegacy;
439445
Context->LibraryCount++;
440446

441-
return;
447+
return 1;
442448

443449
#undef LOAD
444450
#undef LOAD_NAMED
@@ -470,6 +476,7 @@ swift_reflection_interop_readBytesAdapter(void *reader_context,
470476
static inline uint8_t
471477
swift_reflection_interop_getSizeAdapter(void *reader_context) {
472478
// Legacy library doesn't pay attention to these anyway.
479+
(void)reader_context;
473480
return sizeof(void *);
474481
}
475482

@@ -492,8 +499,6 @@ swift_reflection_interop_GetSymbolAddressAdapter(
492499
static inline SwiftReflectionInteropContextRef
493500
swift_reflection_interop_createReflectionContext(
494501
void *ReaderContext,
495-
void *LibraryHandle,
496-
void *LegacyLibraryHandle,
497502
uint8_t PointerSize,
498503
FreeBytesFunction FreeBytes,
499504
ReadBytesFunction ReadBytes,
@@ -503,15 +508,27 @@ swift_reflection_interop_createReflectionContext(
503508
SwiftReflectionInteropContextRef ContextRef =
504509
(SwiftReflectionInteropContextRef)calloc(sizeof(*ContextRef), 1);
505510

506-
swift_reflection_interop_loadFunctions(ContextRef, LibraryHandle, 0);
507-
swift_reflection_interop_loadFunctions(ContextRef, LegacyLibraryHandle, 1);
511+
ContextRef->ReaderContext = ReaderContext;
512+
ContextRef->PointerSize = PointerSize;
513+
ContextRef->FreeBytes = FreeBytes;
514+
ContextRef->ReadBytes = ReadBytes;
515+
ContextRef->GetStringLength = GetStringLength;
516+
ContextRef->GetSymbolAddress = GetSymbolAddress;
508517

509-
if (ContextRef->LibraryCount == 0) {
510-
free(ContextRef);
511-
return NULL;
512-
}
518+
ContextRef->AddressToLibraryCache = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
513519

514-
FOREACH_LIBRARY {
520+
return ContextRef;
521+
}
522+
523+
static inline int
524+
swift_reflection_interop_addLibrary(
525+
SwiftReflectionInteropContextRef ContextRef, void *LibraryHandle) {
526+
size_t NewSize = (ContextRef->LibraryCount + 1) * sizeof(*ContextRef->Libraries);
527+
ContextRef->Libraries = realloc(ContextRef->Libraries, NewSize);
528+
int Success = swift_reflection_interop_loadFunctions(ContextRef, LibraryHandle);
529+
if (Success) {
530+
struct SwiftReflectionInteropContextLibrary *Library =
531+
&ContextRef->Libraries[ContextRef->LibraryCount - 1];
515532
if (Library->IsLegacy) {
516533
Library->Context = Library->Functions.createReflectionContextLegacy(
517534
ContextRef,
@@ -520,20 +537,12 @@ swift_reflection_interop_createReflectionContext(
520537
swift_reflection_interop_GetStringLengthAdapter,
521538
swift_reflection_interop_GetSymbolAddressAdapter);
522539
} else {
523-
Library->Context = Library->Functions.createReflectionContext(ReaderContext,
524-
PointerSize, FreeBytes, ReadBytes, GetStringLength, GetSymbolAddress);
540+
Library->Context = Library->Functions.createReflectionContext(
541+
ContextRef->ReaderContext,
542+
ContextRef->PointerSize, ContextRef->FreeBytes, ContextRef->ReadBytes, ContextRef->GetStringLength, ContextRef->GetSymbolAddress);
525543
}
526544
}
527-
528-
ContextRef->ReaderContext = ReaderContext;
529-
ContextRef->FreeBytes = FreeBytes;
530-
ContextRef->ReadBytes = ReadBytes;
531-
ContextRef->GetStringLength = GetStringLength;
532-
ContextRef->GetSymbolAddress = GetSymbolAddress;
533-
534-
ContextRef->AddressToLibraryCache = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
535-
536-
return ContextRef;
545+
return Success;
537546
}
538547

539548
static inline void
@@ -542,6 +551,7 @@ swift_reflection_interop_destroyReflectionContext(
542551
FOREACH_LIBRARY {
543552
Library->Functions.destroyReflectionContext(Library->Context);
544553
}
554+
free(ContextRef->Libraries);
545555
struct SwiftReflectionInteropContextLegacyImageRangeList *LegacyImageRangeList
546556
= ContextRef->LegacyImageRangeList;
547557
while (LegacyImageRangeList != NULL) {

unittests/Reflection/RemoteMirrorInterop/test.m

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,34 +57,28 @@ uint64_t GetStringLength(void *context, swift_addr_t address) {
5757
}
5858

5959
swift_addr_t GetSymbolAddress(void *context, const char *name, uint64_t name_length) {
60+
(void)name_length;
6061
assert(context == (void *)0xdeadbeef);
6162
return (swift_addr_t)dlsym(RTLD_DEFAULT, name);
6263
}
6364

6465
int main(int argc, char **argv) {
65-
if (argc != 4) {
66-
fprintf(stderr, "usage: %s <libtestswift.dylib> <libswiftRemoteMirror4.dylib> "
67-
"<libswiftRemoteMirror5.dylib>\n",
66+
if (argc < 2) {
67+
fprintf(stderr, "usage: %s <libtestswift.dylib> <libswiftRemoteMirror.dylib ...>\n",
6868
argv[0]);
6969
exit(1);
7070
}
7171

7272
char *TestLibPath = argv[1];
73-
char *Mirror4Path = argv[2];
74-
char *Mirror5Path = argv[3];
7573

7674
void *TestHandle = Load(TestLibPath);
7775
intptr_t (*Test)(void) = dlsym(TestHandle, "test");
7876

7977
uintptr_t Obj = Test();
8078

81-
void *Mirror4Handle = Mirror4Path[0] == '-' ? NULL : Load(Mirror4Path);
82-
void *Mirror5Handle = Mirror5Path[0] == '-' ? NULL : Load(Mirror5Path);
8379
SwiftReflectionInteropContextRef Context =
8480
swift_reflection_interop_createReflectionContext(
8581
(void *)0xdeadbeef,
86-
Mirror5Handle,
87-
Mirror4Handle,
8882
sizeof(void *),
8983
Free,
9084
ReadBytes,
@@ -95,6 +89,28 @@ int main(int argc, char **argv) {
9589
exit(1);
9690
}
9791

92+
for (int i = 2; i < argc; i++) {
93+
void *Handle = Load(argv[i]);
94+
int Success = swift_reflection_interop_addLibrary(Context, Handle);
95+
if (!Success) {
96+
fprintf(stderr, "Failed to add library at %s\n", argv[i]);
97+
exit(1);
98+
}
99+
}
100+
101+
int hasLegacy = 0;
102+
int hasNonLegacy = 0;
103+
for (int i = 0; i < Context->LibraryCount; i++) {
104+
if (Context->Libraries[i].IsLegacy)
105+
hasLegacy = 1;
106+
else
107+
hasNonLegacy = 1;
108+
}
109+
if (hasLegacy && !hasNonLegacy) {
110+
printf("We can't run tests with only a legacy library. Giving up.\n");
111+
exit(0);
112+
}
113+
98114
uint32_t ImageCount = _dyld_image_count();
99115
for (uint32_t i = 0; i < ImageCount; i++) {
100116
swift_addr_t Image = (swift_addr_t)_dyld_get_image_header(i);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python
2+
3+
# Exercise the SwiftRemoteMirrorLegacyInterop API. This works with
4+
# multiple versions of Swift. It builds Swift code using all versions,
5+
# and exercises the Interop API using various combinations of those
6+
# versions' Remote Mirror libraries.
7+
#
8+
# Invoke by passing the various Swift build directories as parameters.
9+
10+
import itertools
11+
import os
12+
import subprocess
13+
import sys
14+
15+
args = sys.argv[1:]
16+
if len(args) == 0:
17+
print >> sys.stderr, "Usage:", sys.argv[0], "swift-build-dirs..."
18+
print >> sys.stderr, "Note: pass paths to the swift-macosx-x86_64 directories."
19+
sys.exit(1)
20+
21+
swiftcs = [os.path.join(arg, 'bin', 'swiftc') for arg in args]
22+
mirrorlibs = [os.path.join(arg, 'lib', 'swift', 'macosx', 'libswiftRemoteMirror.dylib')
23+
for arg in args]
24+
25+
os.chdir(os.path.dirname(sys.argv[0]))
26+
27+
# Build the remote mirror test harness program.
28+
subprocess.check_call(['clang',
29+
'-framework', 'Foundation',
30+
'-I', '../../../include/swift/SwiftRemoteMirror',
31+
'-I', '../../../include/',
32+
'-o', '/tmp/test',
33+
'-Wall', '-Wextra',
34+
'-g', 'test.m'])
35+
36+
# Build a test library with each Swift compiler passed in.
37+
for i, swiftc in enumerate(swiftcs):
38+
subprocess.check_call(['xcrun', swiftc, '-emit-library', 'test.swift',
39+
'-o', os.path.join('/tmp', 'libtest' + str(i) + '.dylib')])
40+
41+
# Run the test harness with all combinations of the remote mirror libraries.
42+
for i in range(len(swiftcs) + 1):
43+
for localMirrorlibs in itertools.combinations(mirrorlibs, i):
44+
for i, arg in enumerate(args):
45+
print 'Testing', arg, 'with mirror libs:'
46+
for l in localMirrorlibs:
47+
print '\t', l
48+
callArgs = (['/tmp/test', os.path.join('/tmp', 'libtest' + str(i) + '.dylib')]
49+
+ list(localMirrorlibs))
50+
print ' '.join(callArgs)
51+
subprocess.call(callArgs)
52+
print 'DONE'
53+
print ''
54+
print localMirrorlibs

unittests/Reflection/RemoteMirrorInterop/test.sh

Lines changed: 0 additions & 63 deletions
This file was deleted.

unittests/Reflection/RemoteMirrorInterop/test4.swift

Lines changed: 0 additions & 11 deletions
This file was deleted.

unittests/Reflection/RemoteMirrorInterop/test5.swift

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)