Skip to content

Commit ae9f1b1

Browse files
authored
Merge pull request #20363 from mikeash/remote-mirror-interop-for-4.2
2 parents c1a7b71 + 4ae12f3 commit ae9f1b1

File tree

8 files changed

+144
-142
lines changed

8 files changed

+144
-142
lines changed

include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ extern "C" {
3939

4040
/// Get the metadata version supported by the Remote Mirror library.
4141
SWIFT_REMOTE_MIRROR_LINKAGE
42-
uint16_t swift_reflection_getSupportedMetadataVersion();
42+
uint16_t swift_reflection_getSupportedMetadataVersion(void);
4343

4444
/// \returns An opaque reflection context.
4545
SWIFT_REMOTE_MIRROR_LINKAGE

include/swift/SwiftRemoteMirror/SwiftRemoteMirrorLegacyInterop.h

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "SwiftRemoteMirrorLegacyInteropTypes.h"
2626
#include "SwiftRemoteMirror.h"
2727

28+
#include <string.h>
2829
#include <dlfcn.h>
2930
#include <mach-o/getsect.h>
3031

@@ -37,14 +38,19 @@
3738
static inline SwiftReflectionInteropContextRef
3839
swift_reflection_interop_createReflectionContext(
3940
void *ReaderContext,
40-
void *LibraryHandle,
41-
void *LegacyLibraryHandle,
4241
uint8_t PointerSize,
4342
FreeBytesFunction FreeBytes,
4443
ReadBytesFunction ReadBytes,
4544
GetStringLengthFunction GetStringLength,
4645
GetSymbolAddressFunction GetSymbolAddress);
4746

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

284290
struct SwiftReflectionInteropContext {
285291
void *ReaderContext;
292+
uint8_t PointerSize;
286293
FreeBytesFunction FreeBytes;
287294
ReadBytesFunction ReadBytes;
288295
uint64_t (*GetStringLength)(void *reader_context,
@@ -291,8 +298,7 @@ struct SwiftReflectionInteropContext {
291298
const char *name,
292299
uint64_t name_length);
293300

294-
// Currently we support at most two libraries.
295-
struct SwiftReflectionInteropContextLibrary Libraries[2];
301+
struct SwiftReflectionInteropContextLibrary *Libraries;
296302
int LibraryCount;
297303

298304
struct SwiftReflectionInteropContextFreeList *FreeList;
@@ -381,12 +387,11 @@ swift_reflection_interop_libraryForObject(
381387
return swift_reflection_interop_libraryForAddress(ContextRef, Metadata);
382388
}
383389

384-
static inline void
390+
static inline int
385391
swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Context,
386-
void *Handle,
387-
int IsLegacy) {
392+
void *Handle) {
388393
if (Handle == NULL)
389-
return;
394+
return 0;
390395

391396
struct SwiftReflectionInteropContextLibrary *Library = &Context
392397
->Libraries[Context->LibraryCount];
@@ -397,14 +402,16 @@ swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Con
397402
#endif
398403
#define LOAD_NAMED(field, symbol) do { \
399404
Functions->field = (decltype(Functions->field))dlsym(Handle, symbol); \
400-
if (Functions->field == NULL) return; \
405+
if (Functions->field == NULL) return 0; \
401406
} while (0)
402407
#define LOAD(name) LOAD_NAMED(name, "swift_reflection_" #name)
403408

404409
LOAD(getSupportedMetadataVersion);
405410
uint16_t version = Functions->getSupportedMetadataVersion();
406411
if (version < SWIFT_LEGACY_METADATA_MIN_VERSION)
407-
return;
412+
return 0;
413+
414+
int IsLegacy = dlsym(Handle, "swift_reflection_addImage") == NULL;
408415

409416
if (IsLegacy) {
410417
LOAD_NAMED(createReflectionContextLegacy, "swift_reflection_createReflectionContext");
@@ -438,7 +445,7 @@ swift_reflection_interop_loadFunctions(struct SwiftReflectionInteropContext *Con
438445
Library->IsLegacy = IsLegacy;
439446
Context->LibraryCount++;
440447

441-
return;
448+
return 1;
442449

443450
#undef LOAD
444451
#undef LOAD_NAMED
@@ -470,6 +477,7 @@ swift_reflection_interop_readBytesAdapter(void *reader_context,
470477
static inline uint8_t
471478
swift_reflection_interop_getSizeAdapter(void *reader_context) {
472479
// Legacy library doesn't pay attention to these anyway.
480+
(void)reader_context;
473481
return sizeof(void *);
474482
}
475483

@@ -492,8 +500,6 @@ swift_reflection_interop_GetSymbolAddressAdapter(
492500
static inline SwiftReflectionInteropContextRef
493501
swift_reflection_interop_createReflectionContext(
494502
void *ReaderContext,
495-
void *LibraryHandle,
496-
void *LegacyLibraryHandle,
497503
uint8_t PointerSize,
498504
FreeBytesFunction FreeBytes,
499505
ReadBytesFunction ReadBytes,
@@ -503,15 +509,27 @@ swift_reflection_interop_createReflectionContext(
503509
SwiftReflectionInteropContextRef ContextRef =
504510
(SwiftReflectionInteropContextRef)calloc(sizeof(*ContextRef), 1);
505511

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

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

514-
FOREACH_LIBRARY {
521+
return ContextRef;
522+
}
523+
524+
static inline int
525+
swift_reflection_interop_addLibrary(
526+
SwiftReflectionInteropContextRef ContextRef, void *LibraryHandle) {
527+
size_t NewSize = (ContextRef->LibraryCount + 1) * sizeof(*ContextRef->Libraries);
528+
ContextRef->Libraries = realloc(ContextRef->Libraries, NewSize);
529+
int Success = swift_reflection_interop_loadFunctions(ContextRef, LibraryHandle);
530+
if (Success) {
531+
struct SwiftReflectionInteropContextLibrary *Library =
532+
&ContextRef->Libraries[ContextRef->LibraryCount - 1];
515533
if (Library->IsLegacy) {
516534
Library->Context = Library->Functions.createReflectionContextLegacy(
517535
ContextRef,
@@ -520,20 +538,12 @@ swift_reflection_interop_createReflectionContext(
520538
swift_reflection_interop_GetStringLengthAdapter,
521539
swift_reflection_interop_GetSymbolAddressAdapter);
522540
} else {
523-
Library->Context = Library->Functions.createReflectionContext(ReaderContext,
524-
PointerSize, FreeBytes, ReadBytes, GetStringLength, GetSymbolAddress);
541+
Library->Context = Library->Functions.createReflectionContext(
542+
ContextRef->ReaderContext,
543+
ContextRef->PointerSize, ContextRef->FreeBytes, ContextRef->ReadBytes, ContextRef->GetStringLength, ContextRef->GetSymbolAddress);
525544
}
526545
}
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;
546+
return Success;
537547
}
538548

539549
static inline void
@@ -542,6 +552,7 @@ swift_reflection_interop_destroyReflectionContext(
542552
FOREACH_LIBRARY {
543553
Library->Functions.destroyReflectionContext(Library->Context);
544554
}
555+
free(ContextRef->Libraries);
545556
struct SwiftReflectionInteropContextLegacyImageRangeList *LegacyImageRangeList
546557
= ContextRef->LegacyImageRangeList;
547558
while (LegacyImageRangeList != NULL) {
@@ -668,14 +679,14 @@ swift_reflection_interop_addImageLegacy(
668679
}
669680

670681
info.LocalStartAddress = (uintptr_t)Buf;
671-
info.RemoteStartAddress = ImageStart;
682+
info.RemoteStartAddress = (uintptr_t)ImageStart;
672683

673684
Library->Functions.addReflectionInfoLegacy(Library->Context, info);
674685

675686
// Find the data segment and add it to our list.
676687
unsigned long DataSize;
677688
const uint8_t *DataSegment = getsegmentdata(Header, "__DATA", &DataSize);
678-
uintptr_t DataSegmentStart = DataSegment - (const uint8_t *)Buf + ImageStart;
689+
uintptr_t DataSegmentStart = (uintptr_t)(DataSegment - (const uint8_t *)Buf + ImageStart);
679690

680691
struct SwiftReflectionInteropContextLegacyImageRangeList *Node =
681692
(struct SwiftReflectionInteropContextLegacyImageRangeList *)malloc(sizeof(*Node));
@@ -687,12 +698,12 @@ swift_reflection_interop_addImageLegacy(
687698
// If the buffer needs to be freed, save buffer and free context to free it when the
688699
// reflection context is destroyed.
689700
if (ContextRef->FreeBytes != NULL) {
690-
struct SwiftReflectionInteropContextFreeList *Node =
691-
(struct SwiftReflectionInteropContextFreeList *)malloc(sizeof(*Node));
692-
Node->Next = ContextRef->FreeList;
693-
Node->Pointer = Buf;
694-
Node->Context = FreeContext;
695-
ContextRef->FreeList = Node;
701+
struct SwiftReflectionInteropContextFreeList *FreeListNode =
702+
(struct SwiftReflectionInteropContextFreeList *)malloc(sizeof(*FreeListNode));
703+
FreeListNode->Next = ContextRef->FreeList;
704+
FreeListNode->Pointer = Buf;
705+
FreeListNode->Context = FreeContext;
706+
ContextRef->FreeList = FreeListNode;
696707
}
697708

698709
return 1;
@@ -736,7 +747,7 @@ swift_reflection_interop_lookupMetadata(SwiftReflectionInteropContextRef Context
736747
swift_reflection_interop_libraryForAddress(ContextRef, Metadata);
737748
if (Library != NULL) {
738749
Result.Metadata = Metadata;
739-
Result.Library = LIBRARY_INDEX;
750+
Result.Library = (int)LIBRARY_INDEX;
740751
}
741752
return Result;
742753
}
@@ -762,7 +773,7 @@ swift_reflection_interop_typeRefForInstance(SwiftReflectionInteropContextRef Con
762773
swift_typeref_t Typeref = Library->Functions.typeRefForInstance(Library->Context,
763774
Object);
764775
Result.Typeref = Typeref;
765-
Result.Library = LIBRARY_INDEX;
776+
Result.Library = (int)LIBRARY_INDEX;
766777
}
767778
return Result;
768779
}
@@ -780,7 +791,7 @@ swift_reflection_interop_typeRefForMangledTypeName(
780791
continue;
781792

782793
Result.Typeref = Typeref;
783-
Result.Library = LIBRARY_INDEX;
794+
Result.Library = (int)LIBRARY_INDEX;
784795
return Result;
785796
}
786797

@@ -867,7 +878,7 @@ swift_reflection_interop_childOfInstance(SwiftReflectionInteropContextRef Contex
867878
Result.Offset = LibResult.Offset;
868879
Result.Kind = LibResult.Kind;
869880
Result.TR.Typeref = LibResult.TR;
870-
Result.TR.Library = LIBRARY_INDEX;
881+
Result.TR.Library = (int)LIBRARY_INDEX;
871882
} else {
872883
Result.Kind = SWIFT_UNKNOWN;
873884
}

include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ typedef enum swift_layout_kind {
108108

109109
// References to other objects in the heap.
110110
SWIFT_STRONG_REFERENCE,
111-
#define REF_STORAGE(Name, name, NAME) \
112-
SWIFT_##NAME##_REFERENCE,
113-
#include "swift/AST/ReferenceStorage.def"
111+
SWIFT_UNOWNED_REFERENCE,
112+
SWIFT_WEAK_REFERENCE,
113+
SWIFT_UNMANAGED_REFERENCE,
114114

115115
// Layouts of heap objects. These are only ever returned from
116116
// swift_reflection_infoFor{Instance,Metadata}(), and not

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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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"
19+
" directories.")
20+
sys.exit(1)
21+
22+
absoluteArgs = [os.path.abspath(arg) for arg in args]
23+
swiftcs = [os.path.join(arg, 'bin', 'swiftc') for arg in absoluteArgs]
24+
mirrorlibs = [os.path.join(arg, 'lib', 'swift', 'macosx',
25+
'libswiftRemoteMirror.dylib')
26+
for arg in absoluteArgs]
27+
28+
os.chdir(os.path.dirname(sys.argv[0]))
29+
30+
# Build the remote mirror test harness program.
31+
subprocess.check_call(['clang',
32+
'-framework', 'Foundation',
33+
'-I', '../../../include/swift/SwiftRemoteMirror',
34+
'-I', '../../../include/',
35+
'-o', '/tmp/test',
36+
'-Wall', '-Wextra',
37+
'-g', 'test.m'])
38+
39+
# Build a test library with each Swift compiler passed in.
40+
for i, swiftc in enumerate(swiftcs):
41+
subprocess.check_call(
42+
['xcrun', swiftc, '-emit-library', 'test.swift',
43+
'-o', os.path.join('/tmp', 'libtest' + str(i) + '.dylib')])
44+
45+
# Run the test harness with all combinations of the remote mirror libraries.
46+
for i in range(len(swiftcs) + 1):
47+
for localMirrorlibs in itertools.combinations(mirrorlibs, i):
48+
for i, arg in enumerate(absoluteArgs):
49+
print 'Testing', arg, 'with mirror libs:'
50+
for l in localMirrorlibs:
51+
print '\t', l
52+
callArgs = ['/tmp/test']
53+
dylibPath = os.path.join('/tmp', 'libtest' + str(i) + '.dylib')
54+
callArgs.append(dylibPath)
55+
callArgs += list(localMirrorlibs)
56+
print ' '.join(callArgs)
57+
subprocess.call(callArgs)
58+
print 'DONE'
59+
print ''
60+
print localMirrorlibs

0 commit comments

Comments
 (0)