blob: 22bcb95c77b9b44ce2fd57ce15e2f23fb8b8f08c [file] [log] [blame]
//===--- test.m - SwiftRemoteMirrorLegacyInterop test program. ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------------===//
///
/// \file
/// This is a test program that exercises the SwiftRemoteMirrorLegacyInterop header.
///
//===----------------------------------------------------------------------------===//
#import <dlfcn.h>
#import <Foundation/Foundation.h>
#import <mach/mach.h>
#import <mach-o/dyld.h>
#import "SwiftRemoteMirrorLegacyInterop.h"
void *Load(char *path) {
void *Handle = dlopen(path, RTLD_LAZY);
if (Handle == NULL) {
fprintf(stderr, "loading %s: %s\n", path, dlerror());
exit(1);
}
return Handle;
}
void Free(void *reader_context, const void *bytes, void *context) {
assert(reader_context == (void *)0xdeadbeef);
assert(context == (void *)0xfeedface);
free((void *)bytes);
}
const void *ReadBytes(void *context, swift_addr_t address, uint64_t size,
void **outFreeContext) {
assert(context == (void *)0xdeadbeef);
*outFreeContext = (void *)0xfeedface;
void *Buffer = malloc(size);
vm_size_t InOutSize = size;
kern_return_t result = vm_read_overwrite(mach_task_self(), address, size, (vm_address_t)Buffer, &InOutSize);
if (result != KERN_SUCCESS) abort();
if (InOutSize != size) abort();
return Buffer;
}
uint64_t GetStringLength(void *context, swift_addr_t address) {
assert(context == (void *)0xdeadbeef);
return strlen((char *)address);
}
swift_addr_t GetSymbolAddress(void *context, const char *name, uint64_t name_length) {
assert(context == (void *)0xdeadbeef);
return (swift_addr_t)dlsym(RTLD_DEFAULT, name);
}
int main(int argc, char **argv) {
if (argc != 4) {
fprintf(stderr, "usage: %s <libtestswift.dylib> <libswiftRemoteMirror4.dylib> "
"<libswiftRemoteMirror5.dylib>\n",
argv[0]);
exit(1);
}
char *TestLibPath = argv[1];
char *Mirror4Path = argv[2];
char *Mirror5Path = argv[3];
void *TestHandle = Load(TestLibPath);
intptr_t (*Test)(void) = dlsym(TestHandle, "test");
uintptr_t Obj = Test();
void *Mirror4Handle = Mirror4Path[0] == '-' ? NULL : Load(Mirror4Path);
void *Mirror5Handle = Mirror5Path[0] == '-' ? NULL : Load(Mirror5Path);
SwiftReflectionInteropContextRef Context =
swift_reflection_interop_createReflectionContext(
(void *)0xdeadbeef,
Mirror5Handle,
Mirror4Handle,
sizeof(void *),
Free,
ReadBytes,
GetStringLength,
GetSymbolAddress);
if (Context == NULL) {
fprintf(stderr, "Unable to create a reflection context!\n");
exit(1);
}
uint32_t ImageCount = _dyld_image_count();
for (uint32_t i = 0; i < ImageCount; i++) {
swift_addr_t Image = (swift_addr_t)_dyld_get_image_header(i);
swift_reflection_interop_addImage(Context, Image);
}
swift_typeref_interop_t Type = swift_reflection_interop_typeRefForInstance(Context, Obj);
if (Type.Typeref != 0) {
swift_typeinfo_t TypeInfo = swift_reflection_interop_infoForTypeRef(Context, Type);
printf("Kind:%u Size:%u Alignment:%u Stride:%u NumFields:%u\n",
TypeInfo.Kind, TypeInfo.Size, TypeInfo.Alignment, TypeInfo.Stride,
TypeInfo.NumFields);
} else {
printf("Unknown typeref!\n");
}
swift_typeinfo_t TypeInfo = swift_reflection_interop_infoForInstance(Context, Obj);
if (TypeInfo.Kind != SWIFT_UNKNOWN) {
printf("Kind:%u Size:%u Alignment:%u Stride:%u NumFields:%u\n",
TypeInfo.Kind, TypeInfo.Size, TypeInfo.Alignment, TypeInfo.Stride,
TypeInfo.NumFields);
for (unsigned i = 0; i < TypeInfo.NumFields; ++i) {
swift_childinfo_t ChildInfo = swift_reflection_interop_childOfInstance(
Context, Obj, i);
printf(" [%u]: %s Offset:%u Kind:%u\n", i,
ChildInfo.Name, ChildInfo.Offset, ChildInfo.Kind);
}
} else {
printf("Unknown typeinfo!\n");
}
swift_reflection_interop_destroyReflectionContext(Context);
}