Loading...
cache-builder/dyld_app_cache_util.cpp dyld-960 dyld-1284.13
--- dyld/dyld-960/cache-builder/dyld_app_cache_util.cpp
+++ dyld/dyld-1284.13/cache-builder/dyld_app_cache_util.cpp
@@ -32,26 +32,30 @@
 #include <variant>
 
 #include <CoreFoundation/CFBundle.h>
+#include <CoreFoundation/CFNumber.h>
 #include <CoreFoundation/CFPropertyList.h>
 #include <CoreFoundation/CFStream.h>
 
 #include "kernel_collection_builder.h"
 #include "ClosureFileSystemPhysical.h"
 #include "FileUtils.h"
+#include "Header.h"
 #include "JSONWriter.h"
 #include "MachOAppCache.h"
 
-using namespace dyld3::json;
+using namespace json;
 
 using dyld3::closure::FileSystemPhysical;
 using dyld3::closure::LoadedFileInfo;
 using dyld3::GradedArchs;
 using dyld3::MachOAnalyzer;
 using dyld3::MachOAppCache;
-using dyld3::Platform;
-using dyld3::json::Node;
-
-__attribute__((noreturn))
+using json::Node;
+
+using mach_o::Header;
+using mach_o::Platform;
+
+__attribute__((__noreturn__))
 static void exit_usage(const char* missingOption = nullptr) {
     if ( missingOption != nullptr ) {
         fprintf(stderr, "Missing option '%s'\n", missingOption);
@@ -66,6 +70,7 @@
     fprintf(stderr, "  -kmod            print the kmod_info of an existing app cache\n");
     fprintf(stderr, "  -uuid            print the UUID of an existing app cache\n");
     fprintf(stderr, "  -fips            print the FIPS section of an existing app cache\n");
+    fprintf(stderr, "  -function-starts print the function starts of an app cache\n");
     fprintf(stderr, "\n");
 
     fprintf(stderr, "Usage: dyld_app_cache_util -validate file-path -arch arch -platform platform\n");
@@ -112,8 +117,10 @@
     bool printFixups            = false;
     bool printSymbols           = false;
     bool printUUID              = false;
+    bool printPrelinkInfo       = false;
     bool printKModInfo          = false;
     bool printFIPS              = false;
+    bool printFunctionStarts    = false;
 };
 
 struct ValidateOptions {
@@ -214,12 +221,20 @@
             exitOrGetState<DumpOptions>(options, arg).printUUID = true;
             continue;
         }
+        if (strcmp(arg, "-prelink-info") == 0) {
+            exitOrGetState<DumpOptions>(options, arg).printPrelinkInfo = true;
+            continue;
+        }
         if (strcmp(arg, "-kmod") == 0) {
             exitOrGetState<DumpOptions>(options, arg).printKModInfo = true;
             continue;
         }
         if (strcmp(arg, "-fips") == 0) {
             exitOrGetState<DumpOptions>(options, arg).printFIPS = true;
+            continue;
+        }
+        if (strcmp(arg, "-function-starts") == 0) {
+            exitOrGetState<DumpOptions>(options, arg).printFunctionStarts = true;
             continue;
         }
 
@@ -271,7 +286,7 @@
             exitOrGetState<CreateKernelCollectionOptions>(options, arg).volumeRoot = argv[++i];
             continue;
         }
-        if (strcmp(arg, "-bundle-id") == 0) {
+        if ( (strcmp(arg, "-bundle-id") == 0) || (strcmp(arg, "-b") == 0) ) {
             exitOrGetState<CreateKernelCollectionOptions>(options, arg).bundleIDs.push_back(argv[++i]);
             continue;
         }
@@ -313,32 +328,6 @@
     return true;
 }
 
-static Platform stringToPlatform(const std::string& str) {
-    if (str == "unknown")
-        return Platform::unknown;
-    if (str == "macOS")
-        return Platform::macOS;
-    if (str == "iOS")
-        return Platform::iOS;
-    if (str == "tvOS")
-        return Platform::tvOS;
-    if (str == "watchOS")
-        return Platform::watchOS;
-    if (str == "bridgeOS")
-        return Platform::bridgeOS;
-    if (str == "iOSMac")
-        return Platform::iOSMac;
-    if (str == "UIKitForMac")
-        return Platform::iOSMac;
-    if (str == "iOS_simulator")
-        return Platform::iOS_simulator;
-    if (str == "tvOS_simulator")
-        return Platform::tvOS_simulator;
-    if (str == "watchOS_simulator")
-        return Platform::watchOS_simulator;
-    return Platform::unknown;
-}
-
 static int dumpAppCache(const DumpOptions& options) {
     // Verify any required options
     if (gOpts.archs.size() != 1)
@@ -356,15 +345,12 @@
     }
 
     const GradedArchs& archs = GradedArchs::forName(gOpts.archs[0]);
-    Platform platform = Platform::unknown;
-    bool isKernelCollection = false;
+    Platform platform = Platform();
 
     // HACK: Pass a real option for building a kernel app cache
-    if (!strcmp(gOpts.platform, "kernel")) {
-        isKernelCollection = true;
-    } else {
-        platform = stringToPlatform(gOpts.platform);
-        if (platform == Platform::unknown) {
+    if (strcmp(gOpts.platform, "kernel") != 0) {
+        platform = Platform::byName(gOpts.platform);
+        if ( platform.empty() ) {
             fprintf(stderr, "Could not create app cache because: unknown platform '%s'\n", gOpts.platform);
             return 1;
         }
@@ -390,13 +376,13 @@
         // Add the segments for the app cache
         __block Node appCacheSegmentsNode;
         __block bool hasError = false;
-        appCacheMA->forEachSegment(^(const dyld3::MachOFile::SegmentInfo &info, bool &stopSegment) {
+        ((const Header*)appCacheMA)->forEachSegment(^(const Header::SegmentInfo &info, bool &stopSegment) {
             Node segmentNode;
-            segmentNode.map["name"] = makeNode(info.segName);
-            segmentNode.map["vmAddr"] = makeNode(hex(info.vmAddr));
-            segmentNode.map["vmSize"] = makeNode(hex(info.vmSize));
-            segmentNode.map["vmEnd"] = makeNode(hex(info.vmAddr + info.vmSize));
-            switch (info.protections) {
+            segmentNode.map["name"] = makeNode(info.segmentName.data());
+            segmentNode.map["vmAddr"] = makeNode(hex(info.vmaddr));
+            segmentNode.map["vmSize"] = makeNode(hex(info.vmsize));
+            segmentNode.map["vmEnd"] = makeNode(hex(info.vmaddr + info.vmsize));
+            switch (info.initProt) {
                 case VM_PROT_READ:
                     segmentNode.map["permissions"] = makeNode("r--");
                     break;
@@ -416,21 +402,21 @@
                     segmentNode.map["permissions"] = makeNode("rwx");
                     break;
                 default:
-                    fprintf(stderr, "Unknown permissions on segment '%s'\n", info.segName);
+                    fprintf(stderr, "Unknown permissions on segment '%.*s'\n", (int)info.segmentName.size(), info.segmentName.data());
                     hasError = true;
                     stopSegment = true;
             }
 
             __block Node sectionsNode;
-            appCacheMA->forEachSection(^(const dyld3::MachOAnalyzer::SectionInfo &sectInfo, bool malformedSectionRange, bool &stopSection) {
-                if ( strncmp(sectInfo.segInfo.segName, info.segName, 16) != 0 )
+            ((const Header*)appCacheMA)->forEachSection(^(const Header::SectionInfo &sectInfo, bool &stopSection) {
+                if ( sectInfo.segmentName != info.segmentName )
                     return;
 
                 Node sectionNode;
-                sectionNode.map["name"] = makeNode(sectInfo.sectName);
-                sectionNode.map["vmAddr"] = makeNode(hex(sectInfo.sectAddr));
-                sectionNode.map["vmSize"] = makeNode(hex(sectInfo.sectSize));
-                sectionNode.map["vmEnd"] = makeNode(hex(sectInfo.sectAddr + sectInfo.sectSize));
+                sectionNode.map["name"] = makeNode(std::string(sectInfo.sectionName));
+                sectionNode.map["vmAddr"] = makeNode(hex(sectInfo.address));
+                sectionNode.map["vmSize"] = makeNode(hex(sectInfo.size));
+                sectionNode.map["vmEnd"] = makeNode(hex(sectInfo.address + sectInfo.size));
 
                 sectionsNode.array.push_back(sectionNode);
             });
@@ -458,14 +444,14 @@
         __block Node dylibsNode;
         appCacheMA->forEachDylib(diag, ^(const MachOAnalyzer *ma, const char *name, bool &stop) {
             __block Node segmentsNode;
-            ma->forEachSegment(^(const dyld3::MachOFile::SegmentInfo &info, bool &stopSegment) {
+            ((const Header*)ma)->forEachSegment(^(const Header::SegmentInfo &info, bool &stopSegment) {
                 Node segmentNode;
-                segmentNode.map["name"] = makeNode(info.segName);
-                segmentNode.map["vmAddr"] = makeNode(hex(info.vmAddr));
-                segmentNode.map["vmSize"] = makeNode(hex(info.vmSize));
-                segmentNode.map["vmEnd"] = makeNode(hex(info.vmAddr + info.vmSize));
-
-                switch (info.protections) {
+                segmentNode.map["name"] = makeNode(info.segmentName.data());
+                segmentNode.map["vmAddr"] = makeNode(hex(info.vmaddr));
+                segmentNode.map["vmSize"] = makeNode(hex(info.vmsize));
+                segmentNode.map["vmEnd"] = makeNode(hex(info.vmaddr + info.vmsize));
+
+                switch (info.initProt) {
                     case VM_PROT_READ:
                         segmentNode.map["permissions"] = makeNode("r--");
                         break;
@@ -482,21 +468,21 @@
                         segmentNode.map["permissions"] = makeNode("r-x");
                         break;
                     default:
-                        fprintf(stderr, "Unknown permissions on segment '%s'\n", info.segName);
+                        fprintf(stderr, "Unknown permissions on segment '%.*s'\n", (int)info.segmentName.size(), info.segmentName.data());
                         hasError = true;
                         stop = true;
                 }
 
                 __block Node sectionsNode;
-                ma->forEachSection(^(const dyld3::MachOAnalyzer::SectionInfo &sectInfo, bool malformedSectionRange, bool &stopSection) {
-                    if ( strncmp(sectInfo.segInfo.segName, info.segName, 16) != 0 )
+                ((const Header*)ma)->forEachSection(^(const Header::SectionInfo &sectInfo, bool &stopSection) {
+                    if ( sectInfo.segmentName != info.segmentName )
                         return;
 
                     Node sectionNode;
-                    sectionNode.map["name"] = makeNode(sectInfo.sectName);
-                    sectionNode.map["vmAddr"] = makeNode(hex(sectInfo.sectAddr));
-                    sectionNode.map["vmSize"] = makeNode(hex(sectInfo.sectSize));
-                    sectionNode.map["vmEnd"] = makeNode(hex(sectInfo.sectAddr + sectInfo.sectSize));
+                    sectionNode.map["name"] = makeNode(std::string(sectInfo.sectionName));
+                    sectionNode.map["vmAddr"] = makeNode(hex(sectInfo.address));
+                    sectionNode.map["vmSize"] = makeNode(hex(sectInfo.size));
+                    sectionNode.map["vmEnd"] = makeNode(hex(sectInfo.address + sectInfo.size));
 
                     sectionsNode.array.push_back(sectionNode);
                 });
@@ -531,8 +517,8 @@
         uint64_t    entryOffset;
         bool        usesCRT;
         Node        entryPointNode;
-        if ( appCacheMA->getEntry(entryOffset, usesCRT) ) {
-            entryPointNode.value = hex(appCacheMA->preferredLoadAddress() + entryOffset);
+        if ( ((const Header*)appCacheMA)->getEntry(entryOffset, usesCRT) ) {
+            entryPointNode.value = hex(((const Header*)appCacheMA)->preferredLoadAddress() + entryOffset);
         }
 
         topNode.map["entrypoint"] = entryPointNode;
@@ -544,11 +530,11 @@
         __block Node topNode;
 
         __block uint64_t baseAddress = ~0ULL;
-        appCacheMA->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo& info, bool& stop) {
-            baseAddress = std::min(baseAddress, info.vmAddr);
+        ((const Header*)appCacheMA)->forEachSegment(^(const Header::SegmentInfo& info, bool& stop) {
+            baseAddress = std::min(baseAddress, info.vmaddr);
         });
         uint64_t cacheBaseAddress = baseAddress;
-        uint64_t textSegVMAddr = appCacheMA->preferredLoadAddress();
+        uint64_t textSegVMAddr = ((const Header*)appCacheMA)->preferredLoadAddress();
 
         auto getFixupsNode = [cacheBaseAddress, textSegVMAddr](const dyld3::MachOAnalyzer* ma) {
             __block Node fixupsNode;
@@ -577,7 +563,7 @@
                         case DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: {
                             uint64_t targetVMOffset = fixupLoc->kernel64.target;
                             uint64_t targetVMAddr = targetVMOffset + cacheBaseAddress;
-                            std::string level = "kc(" + decimal(fixupLoc->kernel64.cacheLevel) + ")";
+                            std::string level = "kc(" + unpaddedDecimal(fixupLoc->kernel64.cacheLevel) + ")";
                             std::string fixup = level + " + " + hex(targetVMAddr);
                             if (fixupLoc->kernel64.isAuth) {
                                 fixup += " auth(";
@@ -585,7 +571,7 @@
                                 fixup += " ";
                                 fixup += fixupLoc->kernel64.addrDiv ? "addr" : "!addr";
                                 fixup += " ";
-                                fixup += decimal(fixupLoc->kernel64.diversity);
+                                fixup += unpaddedDecimal(fixupLoc->kernel64.diversity);
                                 fixup += ")";
                             }
                             fixupsNode.map[hex(vmOffset)] = makeNode(fixup);
@@ -600,10 +586,10 @@
             diag.assertNoError();
 
             ma->forEachRebase(diag, ^(const char *opcodeName, const dyld3::MachOAnalyzer::LinkEditInfo &leInfo,
-                                      const dyld3::MachOAnalyzer::SegmentInfo *segments,
+                                      const Header::SegmentInfo *segments,
                                       bool segIndexSet, uint32_t pointerSize, uint8_t segmentIndex,
                                       uint64_t segmentOffset, dyld3::MachOAnalyzer::Rebase kind, bool &stop) {
-                uint64_t rebaseVmAddr  = segments[segmentIndex].vmAddr + segmentOffset;
+                uint64_t rebaseVmAddr  = segments[segmentIndex].vmaddr + segmentOffset;
                 uint64_t runtimeOffset = rebaseVmAddr - textSegVMAddr;
                 const uint8_t* fixupLoc = (const uint8_t*)ma + runtimeOffset;
 
@@ -703,7 +689,7 @@
         // add uuid
         Node appUUIDNode;
         uuid_t appUUID = {};
-        if ( appCacheMA->getUuid(appUUID) ) {
+        if ( ((Header*)appCacheMA)->getUuid(appUUID) ) {
             uuid_string_t uuidString;
             uuid_unparse_upper(appUUID, uuidString);
             appUUIDNode.value = uuidString;
@@ -757,6 +743,56 @@
         printJSON(topNode, 0, std::cout);
     }
 
+    if (options.printPrelinkInfo) {
+        __block Node topNode;
+
+        const uint8_t* prelinkInfoBuffer = nullptr;
+        uint64_t prelinkInfoBufferSize = 0;
+        prelinkInfoBuffer = (const uint8_t*)appCacheMA->findSectionContent("__PRELINK_INFO", "__info", prelinkInfoBufferSize);
+        if ( prelinkInfoBuffer != nullptr ) {
+            CFReadStreamRef readStreamRef = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, prelinkInfoBuffer, prelinkInfoBufferSize, kCFAllocatorNull);
+            if ( !CFReadStreamOpen(readStreamRef) ) {
+                fprintf(stderr, "Could not open plist stream\n");
+                exit(1);
+            }
+            CFErrorRef errorRef = nullptr;
+            CFPropertyListRef plistRef = CFPropertyListCreateWithStream(kCFAllocatorDefault, readStreamRef, prelinkInfoBufferSize, kCFPropertyListImmutable, nullptr, &errorRef);
+            if ( errorRef != nullptr ) {
+                CFStringRef stringRef = CFErrorCopyFailureReason(errorRef);
+                fprintf(stderr, "Could not read plist because: %s\n", CFStringGetCStringPtr(stringRef, kCFStringEncodingASCII));
+                CFRelease(stringRef);
+                exit(1);
+            }
+            assert(CFGetTypeID(plistRef) == CFDictionaryGetTypeID());
+            CFArrayRef kextPrelinkInfosRef = (CFArrayRef)CFDictionaryGetValue((CFDictionaryRef)plistRef, CFSTR("_PrelinkInfoDictionary"));
+            if ( kextPrelinkInfosRef != nullptr ) {
+                assert(CFGetTypeID(kextPrelinkInfosRef) == CFArrayGetTypeID());
+
+                CFIndex count = CFArrayGetCount(kextPrelinkInfosRef);
+                for ( CFIndex index = 0; index != count; ++index ) {
+                    CFDictionaryRef kextInfoRef = (CFDictionaryRef)CFArrayGetValueAtIndex(kextPrelinkInfosRef, index);
+                    assert(CFGetTypeID(kextInfoRef) == CFDictionaryGetTypeID());
+
+                    CFStringRef bundleIDRef = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)kextInfoRef, CFSTR("CFBundleIdentifier"));
+                    CFNumberRef executableSizeRef = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)kextInfoRef, CFSTR("_PrelinkExecutableSize"));
+
+                    const char* bundleName = CFStringGetCStringPtr(bundleIDRef, kCFStringEncodingASCII);
+                    uint64_t execSize = 0;
+                    CFNumberGetValue(executableSizeRef, CFNumberGetType(executableSizeRef), &execSize);
+
+                    Node kextNode;
+                    kextNode.map["bundle-id"] = json::makeNode(bundleName);
+                    kextNode.map["executable-size"] = json::hex(execSize);
+                    topNode.array.push_back(std::move(kextNode));
+                }
+            }
+            CFRelease(plistRef);
+            CFRelease(readStreamRef);
+        }
+
+        printJSON(topNode, 0, std::cout);
+    }
+
     if (options.printKModInfo) {
         __block Node topNode;
 
@@ -779,7 +815,7 @@
                 ma->forEachLocalSymbol(diag, ^(const char* aSymbolName, uint64_t n_value, uint8_t n_type,
                                                uint8_t n_sect, uint16_t n_desc, bool& stopSymbols) {
                     if ( strcmp(aSymbolName, "_kmod_info") == 0 ) {
-                        kmodInfoVMOffset = n_value - ma->preferredLoadAddress();
+                        kmodInfoVMOffset = n_value - ((const Header*)ma)->preferredLoadAddress();
                         found = true;
                         stopSymbols = true;
                     }
@@ -789,7 +825,7 @@
             if ( found ) {
                 dyld3::MachOAppCache::KModInfo64_v1* kmodInfo = (dyld3::MachOAppCache::KModInfo64_v1*)((uint8_t*)ma + kmodInfoVMOffset);
                 Node kmodInfoNode;
-                kmodInfoNode.map["info-version"] = makeNode(decimal(kmodInfo->info_version));
+                kmodInfoNode.map["info-version"] = makeNode(unpaddedDecimal(kmodInfo->info_version));
                 kmodInfoNode.map["name"] = makeNode((const char*)&kmodInfo->name[0]);
                 kmodInfoNode.map["version"] = makeNode((const char*)&kmodInfo->version[0]);
                 kmodInfoNode.map["address"] = makeNode(hex(kmodInfo->address));
@@ -844,6 +880,37 @@
         printJSON(topNode, 0, std::cout);
     }
 
+    if (options.printFunctionStarts) {
+        __block Node topNode;
+
+        auto getStartsNode = [](const dyld3::MachOAnalyzer* ma) {
+            __block Node functionStartsNode;
+
+            uint64_t loadAddress = ((const Header*)ma)->preferredLoadAddress();
+            ma->forEachFunctionStart(^(uint64_t runtimeOffset) {
+                Node functionStart = makeNode(hex(loadAddress + runtimeOffset));
+                functionStartsNode.array.push_back(functionStart);
+            });
+
+            return functionStartsNode;
+        };
+
+        topNode.map["function-starts"] = getStartsNode(appCacheMA);
+
+        __block Node dylibsNode;
+        appCacheMA->forEachDylib(diag, ^(const MachOAnalyzer *ma, const char *name, bool &stop) {
+            Node dylibNode;
+            dylibNode.map["name"] = makeNode(name);
+            dylibNode.map["function-starts"] = getStartsNode(ma);
+
+            dylibsNode.array.push_back(dylibNode);
+        });
+
+        topNode.map["dylibs"] = dylibsNode;
+
+        printJSON(topNode, 0, std::cout);
+    }
+
     return 0;
 }
 
@@ -857,7 +924,7 @@
         exit_usage();
 
     const GradedArchs& archs = GradedArchs::forName(gOpts.archs[0]);
-    Platform platform = Platform::unknown;
+    Platform platform = Platform();
 
     // HACK: Pass a real option for building a kernel app cache
     if (strcmp(gOpts.platform, "kernel")) {
@@ -947,7 +1014,7 @@
 createKernelCollectionForArch(const CreateKernelCollectionOptions& options, const char* arch,
                               Diagnostics& diag) {
     const GradedArchs& archs = GradedArchs::forName(arch);
-    Platform platform = Platform::unknown;
+    Platform platform = Platform();
 
 
     KernelCollectionBuilder* kcb = nullptr;
@@ -967,12 +1034,14 @@
         }
         LoadedFileInfo info;
         char realerPath[MAXPATHLEN];
-        bool loadedFile = fileSystem.loadFile(kernelCollectionPath, info, realerPath, ^(const char *format, ...) {
+        void (^fileErrorLog)(const char *format, ...) __printflike(1, 2)
+        = ^(const char *format, ...) __printflike(1, 2) {
             va_list list;
             va_start(list, format);
-            diag.error(format, list);
+            diag.error(format, va_list_wrap(list));
             va_end(list);
-        });
+        };
+        bool loadedFile = fileSystem.loadFile(kernelCollectionPath, info, realerPath, fileErrorLog);
         if ( !loadedFile )
             return false;
         CFStringRef pathStringRef = CFStringCreateWithCString(kCFAllocatorDefault, kernelCollectionPath, kCFStringEncodingASCII);
@@ -992,17 +1061,19 @@
             exit(1);
         case baseKC: {
             if (!fileSystem.fileExists(options.kernelPath)) {
-                fprintf(stderr, "Kernel path does not exist: '%s'\n", options.kernelPath);
+                fprintf(stderr, "Kernel path does not exist: %s\n", options.kernelPath);
                 return {};
             }
             LoadedFileInfo info;
             char realerPath[MAXPATHLEN];
-            bool loadedFile = fileSystem.loadFile(options.kernelPath, info, realerPath, ^(const char *format, ...) {
+            void (^fileErrorLog)(const char *format, ...) __printflike(1, 2)
+            = ^(const char *format, ...) __printflike(1, 2) {
                 va_list list;
                 va_start(list, format);
-                diag.error(format, list);
+                diag.error(format, va_list_wrap(list));
                 va_end(list);
-            });
+            };
+            bool loadedFile = fileSystem.loadFile(options.kernelPath, info, realerPath, fileErrorLog);
             if ( !loadedFile )
                 return {};
             CFStringRef pathStringRef = CFStringCreateWithCString(kCFAllocatorDefault, options.kernelPath, kCFStringEncodingASCII);
@@ -1011,7 +1082,7 @@
                 uint64_t errorCount = 0;
                 const char* const* errors = getErrors(kcb, &errorCount);
                 for (uint64_t i = 0; i != errorCount; ++i)
-                    diag.error("Could not load kernel file because: (%s)", errors[i]);
+                    diag.error("Could not load kernel file because: '%s'", errors[i]);
                 return {};
             }
             CFRelease(dataRef);
@@ -1353,13 +1424,14 @@
             bool isCodeless = bundleData.executablePath.empty();
             if ( !isCodeless ) {
                 char realerPath[MAXPATHLEN];
-                bool loadedFile = fileSystem.loadFile(bundleData.executablePath.c_str(), info, realerPath,
-                                                      ^(const char *format, ...) {
+                void (^fileErrorLog)(const char *format, ...) __printflike(1, 2)
+                = ^(const char *format, ...) __printflike(1, 2) {
                     va_list list;
                     va_start(list, format);
-                    diag.error(format, list);
+                    diag.error(format, va_list_wrap(list));
                     va_end(list);
-                });
+                };
+                bool loadedFile = fileSystem.loadFile(bundleData.executablePath.c_str(), info, realerPath, fileErrorLog);
                 if ( !loadedFile )
                     return {};
             }
@@ -1393,7 +1465,7 @@
                 } else if ( stripModeString == "all" ) {
                     stripMode = binaryStripAll;
                 } else {
-                    diag.error("Unknown strip mode: (%s)", stripModeString.c_str());
+                    diag.error("Unknown strip mode: '%s'", stripModeString.c_str());
                     return {};
                 }
             }
@@ -1406,7 +1478,7 @@
                 uint64_t errorCount = 0;
                 const char* const* errors = getErrors(kcb, &errorCount);
                 for (uint64_t i = 0; i != errorCount; ++i)
-                    diag.error("Could not load kext file because: (%s)", errors[i]);
+                    diag.error("Could not load kext file because: '%s'", errors[i]);
                 return {};
             }
 
@@ -1509,7 +1581,7 @@
 
             const void* buffer = mmap(NULL, (size_t)stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
             if (buffer == MAP_FAILED) {
-                diag.error("mmap() for file at '%s' failed, errno=%d\n", sectData.payloadFilePath, errno);
+                diag.error("mmap() for file at %s failed, errno=%d\n", sectData.payloadFilePath, errno);
                 ::close(fd);
                 return {};
             }
@@ -1522,7 +1594,7 @@
             uint64_t errorCount = 0;
             const char* const* errors = getErrors(kcb, &errorCount);
             for (uint64_t i = 0; i != errorCount; ++i)
-                diag.error("Could not load section data file because: (%s)", errors[i]);
+                diag.error("Could not load section data file because: '%s'", errors[i]);
             return {};
         }
     }
@@ -1573,7 +1645,7 @@
             uint64_t errorCount = 0;
             const char* const* errors = getErrors(kcb, &errorCount);
             for (uint64_t i = 0; i != errorCount; ++i)
-                diag.error("Could not prelink data file because: (%s)", errors[i]);
+                diag.error("Could not prelink data file because: '%s'", errors[i]);
             return {};
         }
     }
@@ -1584,7 +1656,7 @@
     if ( errors != nullptr ) {
         if ( !options.printJSONErrors ) {
             for (uint64_t i = 0; i != errorCount; ++i) {
-                fprintf(stderr, "Could not build kernel collection because (%s)\n", errors[i]);
+                fprintf(stderr, "Could not build kernel collection because '%s'\n", errors[i]);
             }
         }
         CFDictionaryRef errorDictRef = getKextErrors(kcb);