static InstanceKind PipeMemoryReader_receiveInstanceKind(const PipeMemoryReader *Reader) { int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_INSTANCE_KIND, 2); uint8_t KindValue = 0; PipeMemoryReader_collectBytesFromPipe(Reader, &KindValue, sizeof(KindValue)); return KindValue; }
static uintptr_t PipeMemoryReader_receiveInstanceAddress(const PipeMemoryReader *Reader) { int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_INSTANCE_ADDRESS, 2); uintptr_t InstanceAddress = 0; PipeMemoryReader_collectBytesFromPipe(Reader, (uint8_t *)&InstanceAddress, sizeof(InstanceAddress)); return InstanceAddress; }
static void PipeMemoryReader_receiveReflectionInfo(SwiftReflectionContextRef RC, const PipeMemoryReader *Reader) { int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_REFLECTION_INFO, 2); size_t NumReflectionInfos; PipeMemoryReader_collectBytesFromPipe(Reader, &NumReflectionInfos, sizeof(NumReflectionInfos)); if (NumReflectionInfos == 0) return; RemoteReflectionInfo *RemoteInfos = calloc(NumReflectionInfos, sizeof(RemoteReflectionInfo)); if (RemoteInfos == NULL) errorAndExit("malloc failed"); for (size_t i = 0; i < NumReflectionInfos; ++i) { RemoteInfos[i] = makeRemoteReflectionInfo( makeRemoteSection(Reader), makeRemoteSection(Reader), makeRemoteSection(Reader), makeRemoteSection(Reader), makeRemoteSection(Reader), makeRemoteSection(Reader)); } // Now pull in the remote sections into our address space. for (size_t i = 0; i < NumReflectionInfos; ++i) { RemoteReflectionInfo RemoteInfo = RemoteInfos[i]; void *Buffer = malloc(RemoteInfo.TotalSize); int Success = PipeMemoryReader_readBytes((void *)Reader, RemoteInfo.StartAddress, Buffer, RemoteInfo.TotalSize); if (!Success) errorAndExit("Couldn't read reflection information"); swift_reflection_info_t Info = { makeLocalSection(Buffer, RemoteInfo.fieldmd, RemoteInfo), makeLocalSection(Buffer, RemoteInfo.assocty, RemoteInfo), makeLocalSection(Buffer, RemoteInfo.builtin, RemoteInfo), makeLocalSection(Buffer, RemoteInfo.capture, RemoteInfo), makeLocalSection(Buffer, RemoteInfo.typeref, RemoteInfo), makeLocalSection(Buffer, RemoteInfo.reflstr, RemoteInfo), /*LocalStartAddress*/ (uintptr_t) Buffer, /*RemoteStartAddress*/ RemoteInfo.StartAddress, }; swift_reflection_addReflectionInfo(RC, Info); } free(RemoteInfos); }
uint64_t PipeMemoryReader_getStringLength(void *Context, swift_addr_t Address) { const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context; int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); uintptr_t TargetAddress = (uintptr_t)Address; write(WriteFD, REQUEST_STRING_LENGTH, 2); write(WriteFD, &TargetAddress, sizeof(TargetAddress)); uintptr_t Length = 0; PipeMemoryReader_collectBytesFromPipe(Reader, &Length, sizeof(Length)); return Length; }
static int PipeMemoryReader_readBytes(void *Context, swift_addr_t Address, void *Dest, uint64_t Size) { const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context; uintptr_t TargetAddress = Address; size_t TargetSize = (size_t)Size; int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_READ_BYTES, 2); write(WriteFD, &TargetAddress, sizeof(TargetAddress)); write(WriteFD, &TargetSize, sizeof(size_t)); PipeMemoryReader_collectBytesFromPipe(Reader, Dest, Size); return 1; }
static swift_addr_t PipeMemoryReader_getSymbolAddress(void *Context, const char *SymbolName, uint64_t Length) { const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context; uintptr_t Address = 0; int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_SYMBOL_ADDRESS, 2); write(WriteFD, SymbolName, Length); write(WriteFD, "\n", 1); PipeMemoryReader_collectBytesFromPipe(Reader, (uint8_t*)&Address, sizeof(Address)); return (uintptr_t)Address; }
static const void *PipeMemoryReader_readBytes(void *Context, swift_addr_t Address, uint64_t Size, void **outFreeContext) { const PipeMemoryReader *Reader = (const PipeMemoryReader *)Context; uintptr_t TargetAddress = Address; size_t TargetSize = (size_t)Size; int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_READ_BYTES, 2); write(WriteFD, &TargetAddress, sizeof(TargetAddress)); write(WriteFD, &TargetSize, sizeof(size_t)); void *Buf = malloc(Size); PipeMemoryReader_collectBytesFromPipe(Reader, Buf, Size); *outFreeContext = NULL; return Buf; }
static void PipeMemoryReader_receiveImages(SwiftReflectionContextRef RC, const PipeMemoryReader *Reader) { int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_IMAGES, 2); size_t NumReflectionInfos; PipeMemoryReader_collectBytesFromPipe(Reader, &NumReflectionInfos, sizeof(NumReflectionInfos)); if (NumReflectionInfos == 0) return; struct { uintptr_t Start, Size; } *Images; Images = calloc(NumReflectionInfos, sizeof(*Images)); PipeMemoryReader_collectBytesFromPipe(Reader, Images, NumReflectionInfos * sizeof(*Images)); for (size_t i = 0; i < NumReflectionInfos; ++i) { swift_reflection_addImage(RC, Images[i].Start); } free(Images); }
int doDumpHeapInstance(const char *BinaryFilename) { PipeMemoryReader Pipe = createPipeMemoryReader(); pid_t pid = _fork(); switch (pid) { case -1: errnoAndExit("Couldn't fork child process"); case 0: { // Child: close(PipeMemoryReader_getParentWriteFD(&Pipe)); close(PipeMemoryReader_getParentReadFD(&Pipe)); dup2(PipeMemoryReader_getChildReadFD(&Pipe), STDIN_FILENO); dup2(PipeMemoryReader_getChildWriteFD(&Pipe), STDOUT_FILENO); _execv(BinaryFilename, NULL); exit(EXIT_SUCCESS); } default: { // Parent close(PipeMemoryReader_getChildReadFD(&Pipe)); close(PipeMemoryReader_getChildWriteFD(&Pipe)); SwiftReflectionContextRef RC = swift_reflection_createReflectionContextWithDataLayout( (void *)&Pipe, PipeMemoryReader_queryDataLayout, PipeMemoryReader_freeBytes, PipeMemoryReader_readBytes, PipeMemoryReader_getStringLength, PipeMemoryReader_getSymbolAddress); uint8_t PointerSize = PipeMemoryReader_getPointerSize((void*)&Pipe); if (PointerSize != sizeof(uintptr_t)) errorAndExit("Child process had unexpected architecture"); #if defined(__APPLE__) && defined(__MACH__) PipeMemoryReader_receiveImages(RC, &Pipe); #else PipeMemoryReader_receiveReflectionInfo(RC, &Pipe); #endif while (1) { InstanceKind Kind = PipeMemoryReader_receiveInstanceKind(&Pipe); switch (Kind) { case Object: printf("Reflecting an object.\n"); if (!reflectHeapObject(RC, Pipe)) return EXIT_SUCCESS; break; case Existential: { static const char Name[] = MANGLING_PREFIX_STR "ypD"; swift_typeref_t AnyTR = swift_reflection_typeRefForMangledTypeName(RC, Name, sizeof(Name)-1); printf("Reflecting an existential.\n"); if (!reflectExistential(RC, Pipe, AnyTR)) return EXIT_SUCCESS; break; } case ErrorExistential: { static const char ErrorName[] = MANGLING_PREFIX_STR "s5Error_pD"; swift_typeref_t ErrorTR = swift_reflection_typeRefForMangledTypeName(RC, ErrorName, sizeof(ErrorName)-1); printf("Reflecting an error existential.\n"); if (!reflectExistential(RC, Pipe, ErrorTR)) return EXIT_SUCCESS; break; } case Closure: printf("Reflecting a closure.\n"); if (!reflectHeapObject(RC, Pipe)) return EXIT_SUCCESS; break; case None: swift_reflection_destroyReflectionContext(RC); printf("Done.\n"); return EXIT_SUCCESS; } } } } return EXIT_SUCCESS; }
static void PipeMemoryReader_sendDoneMessage(const PipeMemoryReader *Reader) { int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); write(WriteFD, REQUEST_DONE, 2); }
int doDumpHeapInstance(const char *BinaryFilename) { PipeMemoryReader Pipe = createPipeMemoryReader(); pid_t pid = _fork(); switch (pid) { case -1: errorAndExit("Couldn't fork child process"); exit(EXIT_FAILURE); case 0: { // Child: close(PipeMemoryReader_getParentWriteFD(&Pipe)); close(PipeMemoryReader_getParentReadFD(&Pipe)); dup2(PipeMemoryReader_getChildReadFD(&Pipe), STDIN_FILENO); dup2(PipeMemoryReader_getChildWriteFD(&Pipe), STDOUT_FILENO); _execv(BinaryFilename, NULL); exit(EXIT_SUCCESS); } default: { // Parent close(PipeMemoryReader_getChildReadFD(&Pipe)); close(PipeMemoryReader_getChildWriteFD(&Pipe)); SwiftReflectionContextRef RC = swift_reflection_createReflectionContext( (void*)&Pipe, PipeMemoryReader_getPointerSize, PipeMemoryReader_getSizeSize, PipeMemoryReader_readBytes, PipeMemoryReader_getStringLength, PipeMemoryReader_getSymbolAddress); uint8_t PointerSize = PipeMemoryReader_getPointerSize((void*)&Pipe); if (PointerSize != sizeof(uintptr_t)) errorAndExit("Child process had unexpected architecture"); PipeMemoryReader_receiveReflectionInfo(RC, &Pipe); while (1) { InstanceKind Kind = PipeMemoryReader_receiveInstanceKind(&Pipe); switch (Kind) { case Object: printf("Reflecting an object.\n"); if (!reflectHeapObject(RC, Pipe)) return EXIT_SUCCESS; break; case Existential: { swift_typeref_t AnyTR = swift_reflection_typeRefForMangledTypeName(RC, "_TtP_", 5); printf("Reflecting an existential.\n"); if (!reflectExistential(RC, Pipe, AnyTR)) return EXIT_SUCCESS; break; } case ErrorExistential: { swift_typeref_t ErrorTR = swift_reflection_typeRefForMangledTypeName(RC, "_TtPs5Error_", 21); printf("Reflecting an error existential.\n"); if (!reflectExistential(RC, Pipe, ErrorTR)) return EXIT_SUCCESS; break; } case Closure: printf("Reflecting a closure.\n"); if (!reflectHeapObject(RC, Pipe)) return EXIT_SUCCESS; break; case None: swift_reflection_destroyReflectionContext(RC); printf("Done.\n"); return EXIT_SUCCESS; } } } } return EXIT_SUCCESS; }