Loading...
common/CachePatching.cpp dyld-1286.10 dyld-1042.1
--- dyld/dyld-1286.10/common/CachePatching.cpp
+++ dyld/dyld-1042.1/common/CachePatching.cpp
@@ -23,7 +23,7 @@
  */
 
 #include "CachePatching.h"
-#include "../cache_builder/Error.h"
+#include "Error.h"
 #include "Types.h"
 
 #if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
@@ -55,8 +55,6 @@
             return ((PatchTableV2*)this)->numImages();
         case 3:
             return ((PatchTableV3*)this)->numImages();
-        case 4:
-            return ((PatchTableV4*)this)->numImages();
         default:
             assert("Unknown patch table version");
             break;
@@ -71,8 +69,6 @@
             return ((PatchTableV2*)this)->patchableExportCount(imageIndex);
         case 3:
             return ((PatchTableV3*)this)->patchableExportCount(imageIndex);
-        case 4:
-            return ((PatchTableV4*)this)->patchableExportCount(imageIndex);
         default:
             assert("Unknown patch table version");
             break;
@@ -87,8 +83,6 @@
             return ((PatchTableV2*)this)->imageHasClient(imageIndex, userImageIndex);
         case 3:
             return ((PatchTableV3*)this)->imageHasClient(imageIndex, userImageIndex);
-        case 4:
-            return ((PatchTableV4*)this)->imageHasClient(imageIndex, userImageIndex);
         default:
             assert("Unknown patch table version");
             break;
@@ -103,8 +97,6 @@
             return ((PatchTableV2*)this)->forEachPatchableExport(imageIndex, handler);
         case 3:
             return ((PatchTableV3*)this)->forEachPatchableExport(imageIndex, handler);
-        case 4:
-            return ((PatchTableV4*)this)->forEachPatchableExport(imageIndex, handler);
         default:
             assert("Unknown patch table version");
             break;
@@ -122,9 +114,6 @@
         case 3:
             return ((PatchTableV3*)this)->forEachPatchableUseOfExport(imageIndex, dylibVMOffsetOfImpl,
                                                                       handler);
-        case 4:
-            return ((PatchTableV4*)this)->forEachPatchableUseOfExport(imageIndex, dylibVMOffsetOfImpl,
-                                                                      handler);
         default:
             assert("Unknown patch table version");
             break;
@@ -142,9 +131,6 @@
                                                                              userImageIndex, handler);
         case 3:
             return ((PatchTableV3*)this)->forEachPatchableUseOfExportInImage(imageIndex, dylibVMOffsetOfImpl,
-                                                                             userImageIndex, handler);
-        case 4:
-            return ((PatchTableV4*)this)->forEachPatchableUseOfExportInImage(imageIndex, dylibVMOffsetOfImpl,
                                                                              userImageIndex, handler);
         default:
             assert("Unknown patch table version");
@@ -168,11 +154,6 @@
                                                                            cacheUnslidAddress,
                                                                            getDylibHandler,
                                                                            handler);
-        case 4:
-            return ((PatchTableV4*)this)->forEachPatchableCacheUseOfExport(imageIndex, dylibVMOffsetOfImpl,
-                                                                           cacheUnslidAddress,
-                                                                           getDylibHandler,
-                                                                           handler);
         default:
             assert("Unknown patch table version");
             break;
@@ -189,9 +170,6 @@
         case 3:
             return ((PatchTableV3*)this)->forEachPatchableGOTUseOfExport(imageIndex, dylibVMOffsetOfImpl,
                                                                          handler);
-        case 4:
-            return ((PatchTableV4*)this)->forEachPatchableGOTUseOfExport(imageIndex, dylibVMOffsetOfImpl,
-                                                                         handler);
         default:
             assert("Unknown patch table version");
             break;
@@ -200,18 +178,19 @@
 
 const char* PatchTable::patchKindName(PatchKind patchKind)
 {
+    const char* name = "(unknown patch kind)";
     switch ( patchKind ) {
         case PatchKind::regular:
-            return "";
+            name = "";
             break;
         case PatchKind::cfObj2:
-            return "(CF obj2)";
+            name = "(CF obj2)";
             break;
         case PatchKind::objcClass:
-            return "(objc class)";
-            break;
-    }
-    return "(unknown patch kind)";
+            name = "(objc class)";
+            break;
+    }
+    return name;
 }
 
 //
@@ -373,7 +352,7 @@
                 pmd.authenticated     = loc.authenticated;
                 pmd.key               = loc.key;
                 pmd.usesAddrDiversity = loc.usesAddressDiversity;
-                handler(imageClient.clientDylibIndex, loc.dylibOffsetOfUse, pmd, loc.getAddend(), false);
+                handler(imageClient.clientDylibIndex, loc.dylibOffsetOfUse, pmd, loc.getAddend());
             }
 
             // We found the export, so we're done with this client.  There might be uses in other
@@ -410,7 +389,7 @@
             pmd.authenticated     = loc.authenticated;
             pmd.key               = loc.key;
             pmd.usesAddrDiversity = loc.usesAddressDiversity;
-            handler(loc.dylibOffsetOfUse, pmd, loc.getAddend(), false);
+            handler(loc.dylibOffsetOfUse, pmd, loc.getAddend());
         }
 
         // We found the export, so we're done
@@ -455,7 +434,7 @@
                 pmd.authenticated     = loc.authenticated;
                 pmd.key               = loc.key;
                 pmd.usesAddrDiversity = loc.usesAddressDiversity;
-                handler(cacheOffset, pmd, loc.getAddend(), false);
+                handler(cacheOffset, pmd, loc.getAddend());
             }
         }
     }
@@ -553,182 +532,7 @@
         pmd.authenticated     = loc.authenticated;
         pmd.key               = loc.key;
         pmd.usesAddrDiversity = loc.usesAddressDiversity;
-        handler(loc.cacheOffsetOfUse, pmd, loc.getAddend(), false);
-    }
-}
-
-//
-// MARK: --- PatchTableV4 methods ---
-//
-
-const dyld_cache_patch_info_v4* PatchTableV4::info() const
-{
-    return (dyld_cache_patch_info_v4*)this->table;
-}
-
-std::span<dyld_cache_patchable_location_v4> PatchTableV4::patchableLocations() const
-{
-    uint64_t offset = info()->patchLocationArrayAddr - this->tableVMAddr;
-    return { (dyld_cache_patchable_location_v4*)(this->table + offset), (size_t)info()->patchLocationArrayCount };
-}
-
-std::span<dyld_cache_patchable_location_v4_got> PatchTableV4::gotPatchableLocations() const
-{
-    uint64_t offset = info()->gotLocationArrayAddr - this->tableVMAddr;
-    return { (dyld_cache_patchable_location_v4_got*)(this->table + offset), (size_t)info()->gotLocationArrayCount };
-}
-
-// This is extremely inefficient, so only used by tests and cache util
-#if BUILDING_CACHE_BUILDER_UNIT_TESTS || BUILDING_SHARED_CACHE_UTIL
-void PatchTableV4::forEachPatchableUseOfExport(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl,
-                                               ExportUseHandler handler) const
-{
-    std::span<dyld_cache_image_clients_v2>      imageClients = this->clientsForImage(imageIndex);
-    std::span<dyld_cache_image_export_v2>       cacheImageExports = this->imageExports();
-    std::span<dyld_cache_patchable_export_v2>   cacheClientExports = this->clientExports();
-    std::span<dyld_cache_patchable_location_v4> cachePatchableLocations = this->patchableLocations();
-
-    // Each image has a list of clients
-    for ( const dyld_cache_image_clients_v2& imageClient : imageClients ) {
-        // Each client has a list of exports from the image
-        auto exportsForClient = cacheClientExports.subspan(imageClient.patchExportsStartIndex,
-                                                           imageClient.patchExportsCount);
-        for ( const dyld_cache_patchable_export_v2& clientExport : exportsForClient ) {
-            const dyld_cache_image_export_v2& imageExport = cacheImageExports[clientExport.imageExportIndex];
-
-            // Skip exports which aren't the one we are looking for
-            if ( imageExport.dylibOffsetOfImpl != dylibVMOffsetOfImpl )
-                continue;
-
-            // The client may have multiple locations to patch for the same symbol
-            auto patchableLocationsForExport = cachePatchableLocations.subspan(clientExport.patchLocationsStartIndex,
-                                                                               clientExport.patchLocationsCount);
-            for ( const dyld_cache_patchable_location_v4& loc : patchableLocationsForExport ) {
-                dyld3::MachOFile::PointerMetaData pmd;
-                loc.getPMD(pmd);
-                handler(imageClient.clientDylibIndex, loc.dylibOffsetOfUse, pmd, loc.getAddend(), loc.isWeakImport());
-            }
-
-            // We found the export, so we're done with this client.  There might be uses in other
-            // clients though
-            break;
-        }
-    }
-}
-#endif // BUILDING_CACHE_BUILDER_UNIT_TESTS || BUILDING_SHARED_CACHE_UTIL
-
-void PatchTableV4::forEachPatchableUseOfExportInImage(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl,
-                                                      uint32_t userImageIndex,
-                                                      ExportUseInImageHandler handler) const
-{
-    std::span<dyld_cache_image_export_v2>       cacheImageExports = this->imageExports();
-    std::span<dyld_cache_patchable_location_v4> cachePatchableLocations = this->patchableLocations();
-
-    // Get the exports used by this client in the given image
-    std::span<dyld_cache_patchable_export_v2> clientExports = this->clientsExportsForImageAndClient(imageIndex, userImageIndex);
-    for ( const dyld_cache_patchable_export_v2& clientExport : clientExports ) {
-        const dyld_cache_image_export_v2& imageExport = cacheImageExports[clientExport.imageExportIndex];
-
-        // Skip exports which aren't the one we are looking for
-        if ( imageExport.dylibOffsetOfImpl != dylibVMOffsetOfImpl )
-            continue;
-
-        // The client may have multiple locations to patch for the same symbol
-        auto patchableLocationsForExport = cachePatchableLocations.subspan(clientExport.patchLocationsStartIndex,
-                                                                           clientExport.patchLocationsCount);
-        for ( const dyld_cache_patchable_location_v4& loc : patchableLocationsForExport ) {
-            dyld3::MachOFile::PointerMetaData pmd;
-            loc.getPMD(pmd);
-            handler(loc.dylibOffsetOfUse, pmd, loc.getAddend(), loc.isWeakImport());
-        }
-
-        // We found the export, so we're done
-        break;
-    }
-}
-
-void PatchTableV4::forEachPatchableCacheUseOfExport(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl,
-                                                    uint64_t cacheUnslidAddress,
-                                                    GetDylibAddressHandler getDylibHandler,
-                                                    ExportCacheUseHandler handler) const
-{
-    std::span<dyld_cache_image_clients_v2>      imageClients = this->clientsForImage(imageIndex);
-    std::span<dyld_cache_image_export_v2>       cacheImageExports = this->imageExports();
-    std::span<dyld_cache_patchable_export_v2>   cacheClientExports = this->clientExports();
-    std::span<dyld_cache_patchable_location_v4> cachePatchableLocations = this->patchableLocations();
-
-    // Each image has a list of clients
-    for ( const dyld_cache_image_clients_v2& imageClient : imageClients ) {
-        // We need the address of the client to compute cache offsets later
-        uint64_t clientUnslidAddress = getDylibHandler(imageClient.clientDylibIndex);
-
-        // Each client has a list of exports from the image
-        auto exportsForClient = cacheClientExports.subspan(imageClient.patchExportsStartIndex,
-                                                           imageClient.patchExportsCount);
-
-        for ( const dyld_cache_patchable_export_v2& clientExport : exportsForClient ) {
-            const dyld_cache_image_export_v2& imageExport = cacheImageExports[clientExport.imageExportIndex];
-
-            // Skip exports which aren't the one we are looking for
-            if ( imageExport.dylibOffsetOfImpl != dylibVMOffsetOfImpl )
-                continue;
-
-            // The client may have multiple locations to patch for the same symbol
-            auto patchableLocationsForExport = cachePatchableLocations.subspan(clientExport.patchLocationsStartIndex,
-                                                                               clientExport.patchLocationsCount);
-            for ( const dyld_cache_patchable_location_v4& loc : patchableLocationsForExport ) {
-                uint64_t cacheOffset = (clientUnslidAddress + loc.dylibOffsetOfUse) - cacheUnslidAddress;
-                dyld3::MachOFile::PointerMetaData pmd;
-                loc.getPMD(pmd);
-                handler(cacheOffset, pmd, loc.getAddend(), loc.isWeakImport());
-            }
-        }
-    }
-}
-
-void PatchTableV4::forEachPatchableGOTUseOfExport(uint32_t imageIndex, uint32_t dylibVMOffsetOfImpl,
-                                                  GOTUseHandler handler) const
-{
-    auto gotClientExports = this->gotClientExportsForImage(imageIndex);
-    auto cacheImageExports = this->imageExports();
-    auto cachePatchableLocations = this->gotPatchableLocations();
-
-    if ( gotClientExports.empty() )
-        return;
-
-    // Binary search for the dylibOffset we want.  This works because they were sorted in the cache builder
-    const dyld_cache_patchable_export_v3* foundClientExport = nullptr;
-    int64_t start = 0;
-    int64_t end = (int64_t)gotClientExports.size() - 1;
-    while ( start <= end ) {
-        int64_t i = (start + end) / 2;
-
-        // Get element[i]
-        const dyld_cache_patchable_export_v3& clientExport = gotClientExports[(uint32_t)i];
-        const dyld_cache_image_export_v2& imageExport = cacheImageExports[clientExport.imageExportIndex];
-
-        if ( imageExport.dylibOffsetOfImpl == dylibVMOffsetOfImpl ) {
-            foundClientExport = &clientExport;
-            break;
-        }
-
-        if ( dylibVMOffsetOfImpl < imageExport.dylibOffsetOfImpl ) {
-            end = i-1;
-        } else {
-            start = i+1;
-        }
-    }
-
-    if ( foundClientExport == nullptr )
-        return;
-
-    // The client may have multiple locations to patch for the same symbol
-    auto patchableLocationsForExport = cachePatchableLocations.subspan(foundClientExport->patchLocationsStartIndex,
-                                                                       foundClientExport->patchLocationsCount);
-    for ( const dyld_cache_patchable_location_v4_got& loc : patchableLocationsForExport ) {
-        dyld3::MachOFile::PointerMetaData pmd;
-        loc.getPMD(pmd);
-        handler(loc.cacheOffsetOfUse, pmd, loc.getAddend(), loc.isWeakImport());
+        handler(loc.cacheOffsetOfUse, pmd, loc.getAddend());
     }
 }
 
@@ -745,9 +549,6 @@
                                         const std::span<PatchInfo>& patchInfos)
 {
     for ( const CacheDylib& cacheDylib : cacheDylibs ) {
-        if ( !cacheDylib.needsPatchTable )
-            continue;
-
         const PatchInfo& dylibPatchInfo = patchInfos[cacheDylib.cacheIndex];
         assert(cacheDylib.bindTargets.size() == dylibPatchInfo.bindUses.size());
         assert(cacheDylib.bindTargets.size() == dylibPatchInfo.bindTargetNames.size());
@@ -766,7 +567,6 @@
             assert(bindTarget.kind == CacheDylib::BindTarget::Kind::cacheImage);
             const CacheDylib::BindTarget::CacheImage& cacheImageTarget = bindTarget.cacheImage;
             CacheVMAddress                            bindTargetVMAddr = cacheImageTarget.targetDylib->cacheLoadAddress + cacheImageTarget.targetRuntimeOffset;
-            assert(cacheImageTarget.targetDylib->needsPatchTable && "target dylibs must be patchable");
 
             // Find the target dylib.  We need to add this dylib as a client of the target
             DylibClients& targetDylibClients = dylibClients[cacheImageTarget.targetDylib->cacheIndex];
@@ -790,20 +590,8 @@
         }
 
         // GOTs
-        for ( UniquedGOTKind sectionKind : { UniquedGOTKind::regular, UniquedGOTKind::authGot, UniquedGOTKind::authPtr } ) {
-            std::span<const std::vector<PatchInfo::GOTInfo>> bindGOTUses;
-            switch ( sectionKind ) {
-                case UniquedGOTKind::regular:
-                    bindGOTUses = dylibPatchInfo.bindGOTUses;
-                    break;
-                case UniquedGOTKind::authGot:
-                    bindGOTUses = dylibPatchInfo.bindAuthGOTUses;
-                    break;
-                case UniquedGOTKind::authPtr:
-                    bindGOTUses = dylibPatchInfo.bindAuthPtrUses;
-                    break;
-            }
-
+        for ( bool auth : { false, true } ) {
+            const auto& bindGOTUses = auth ? dylibPatchInfo.bindAuthGOTUses : dylibPatchInfo.bindGOTUses;
             assert(cacheDylib.bindTargets.size() == bindGOTUses.size());
             for ( uint32_t bindIndex = 0; bindIndex != cacheDylib.bindTargets.size(); ++bindIndex ) {
                 const CacheDylib::BindTarget& bindTarget = cacheDylib.bindTargets[bindIndex];
@@ -968,19 +756,6 @@
         patchImage.patchExportsStartIndex = (uint32_t)imageExports.size();
         patchImage.patchExportsCount      = (uint32_t)dylibClientData.getUsedExports().size();
 
-        if ( !cacheDylibs[dylibIndex].needsPatchTable ) {
-            assert(patchImage.patchExportsCount == 0);
-            assert(dylibClientData.clients.empty());
-            patchImages.push_back(patchImage);
-
-            // got clients entry needed even if unused
-            dyld_cache_image_got_clients_v3 gotClient;
-            gotClient.patchExportsStartIndex   = (uint32_t)gotClientExports.size();
-            gotClient.patchExportsCount        = 0;
-            gotClients.push_back(gotClient);
-            continue;
-        }
-
         // Add regular clients
         for ( const DylibClient& clientDylib : dylibClientData.clients ) {
             bool clientUsed = false;
@@ -1021,22 +796,14 @@
                 // Now add the list of locations.
                 // At this point we need to translate from the locations the cache recorded to what we encode
                 for ( const dyld_cache_patchable_location& use : uses ) {
-                    dyld_cache_patchable_location_v4 loc;
+                    dyld_cache_patchable_location_v2 loc;
                     loc.dylibOffsetOfUse     = (uint32_t)(use.cacheVMAddr - clientDylibVMAddr).rawValue();
-                    if ( use.authenticated ) {
-                        loc.auth.high7                = use.high7;
-                        loc.auth.isWeakImport         = use.isWeakImport;
-                        loc.auth.addend               = use.addend;
-                        loc.auth.authenticated        = use.authenticated;
-                        loc.auth.usesAddressDiversity = use.usesAddressDiversity;
-                        loc.auth.keyIsD               = (use.key == 2) ? 1 : 0;  // IA == 0, DA == 2
-                        loc.auth.discriminator        = use.discriminator;
-                    } else {
-                        loc.regular.high7                = use.high7;
-                        loc.regular.isWeakImport         = use.isWeakImport;
-                        loc.regular.addend               = use.addend;
-                        loc.regular.authenticated        = use.authenticated;
-                    }
+                    loc.high7                = use.high7;
+                    loc.addend               = use.addend;
+                    loc.authenticated        = use.authenticated;
+                    loc.usesAddressDiversity = use.usesAddressDiversity;
+                    loc.key                  = use.key;
+                    loc.discriminator        = use.discriminator;
                     patchLocations.push_back(loc);
                 }
             }
@@ -1078,23 +845,14 @@
                 // Now add the list of locations.
                 // At this point we need to translate from the locations the cache recorded to what we encode
                 for (const dyld_cache_patchable_location& use : uses) {
-                    dyld_cache_patchable_location_v4_got loc;
+                    dyld_cache_patchable_location_v3 loc;
                     loc.cacheOffsetOfUse            = (use.cacheVMAddr - cacheBaseAddress).rawValue();
-                    loc.unusedPadding               = 0;
-                    if ( use.authenticated ) {
-                        loc.auth.high7                = use.high7;
-                        loc.auth.isWeakImport         = use.isWeakImport;
-                        loc.auth.addend               = use.addend;
-                        loc.auth.authenticated        = use.authenticated;
-                        loc.auth.usesAddressDiversity = use.usesAddressDiversity;
-                        loc.auth.keyIsD               = (use.key == 2) ? 1 : 0; // IA == 0, DA == 2
-                        loc.auth.discriminator        = use.discriminator;
-                    } else {
-                        loc.regular.high7                = use.high7;
-                        loc.regular.isWeakImport         = use.isWeakImport;
-                        loc.regular.addend               = use.addend;
-                        loc.regular.authenticated        = use.authenticated;
-                    }
+                    loc.high7                       = use.high7;
+                    loc.addend                      = use.addend;
+                    loc.authenticated               = use.authenticated;
+                    loc.usesAddressDiversity        = use.usesAddressDiversity;
+                    loc.key                         = use.key;
+                    loc.discriminator               = use.discriminator;
                     gotPatchLocations.push_back(loc);
                 }
             }
@@ -1185,10 +943,10 @@
                      bufferSize / 1024 / 1024, patchInfoSize / 1024);
     }
     
-    dyld_cache_patch_info_v4 patchInfo;
-    patchInfo.patchTableVersion             = 4;
+    dyld_cache_patch_info_v3 patchInfo;
+    patchInfo.patchTableVersion             = 3;
     patchInfo.patchLocationVersion          = 0;
-    patchInfo.patchTableArrayAddr           = patchInfoAddr + sizeof(dyld_cache_patch_info_v4);
+    patchInfo.patchTableArrayAddr           = patchInfoAddr + sizeof(dyld_cache_patch_info_v3);
     patchInfo.patchTableArrayCount          = patchImages.size();
     patchInfo.patchImageExportsArrayAddr    = patchInfo.patchTableArrayAddr + (patchInfo.patchTableArrayCount * sizeof(dyld_cache_image_patches_v2));
     patchInfo.patchImageExportsArrayCount   = imageExports.size();
@@ -1198,39 +956,30 @@
     patchInfo.patchClientExportsArrayCount  = clientExports.size();
     patchInfo.patchLocationArrayAddr        = patchInfo.patchClientExportsArrayAddr + (patchInfo.patchClientExportsArrayCount * sizeof(dyld_cache_patchable_export_v2));
     patchInfo.patchLocationArrayCount       = patchLocations.size();
-    patchInfo.gotClientsArrayAddr           = patchInfo.patchLocationArrayAddr + (patchInfo.patchLocationArrayCount * sizeof(dyld_cache_patchable_location_v4));
+    patchInfo.gotClientsArrayAddr           = patchInfo.patchLocationArrayAddr + (patchInfo.patchLocationArrayCount * sizeof(dyld_cache_patchable_location_v2));
     patchInfo.gotClientsArrayCount          = gotClients.size();
     patchInfo.gotClientExportsArrayAddr     = patchInfo.gotClientsArrayAddr + (patchInfo.gotClientsArrayCount * sizeof(dyld_cache_image_got_clients_v3));
     patchInfo.gotClientExportsArrayCount    = gotClientExports.size();
     patchInfo.gotLocationArrayAddr          = patchInfo.gotClientExportsArrayAddr + (patchInfo.gotClientExportsArrayCount * sizeof(dyld_cache_patchable_export_v3));
     patchInfo.gotLocationArrayCount         = gotPatchLocations.size();
-    patchInfo.patchExportNamesAddr          = patchInfo.gotLocationArrayAddr + (patchInfo.gotLocationArrayCount * sizeof(dyld_cache_patchable_location_v4_got));
+    patchInfo.patchExportNamesAddr          = patchInfo.gotLocationArrayAddr + (patchInfo.gotLocationArrayCount * sizeof(dyld_cache_patchable_location_v3));
     patchInfo.patchExportNamesSize          = patchExportNames.size();
 
     // (dylib, client) patch table
     ::memcpy(buffer + patchInfoAddr - patchInfoAddr, &patchInfo, sizeof(dyld_cache_patch_info_v3));
-    if ( !patchImages.empty() )
-        ::memcpy(buffer + patchInfo.patchTableArrayAddr - patchInfoAddr, &patchImages[0], sizeof(patchImages[0]) * patchImages.size());
-    if ( !imageExports.empty() )
-        ::memcpy(buffer + patchInfo.patchImageExportsArrayAddr - patchInfoAddr, &imageExports[0], sizeof(imageExports[0]) * imageExports.size());
-    if ( !patchClients.empty() )
-        ::memcpy(buffer + patchInfo.patchClientsArrayAddr - patchInfoAddr, &patchClients[0], sizeof(patchClients[0]) * patchClients.size());
-    if ( !clientExports.empty() )
-        ::memcpy(buffer + patchInfo.patchClientExportsArrayAddr - patchInfoAddr, &clientExports[0], sizeof(clientExports[0]) * clientExports.size());
-    if ( !patchLocations.empty() )
-        ::memcpy(buffer + patchInfo.patchLocationArrayAddr - patchInfoAddr, &patchLocations[0], sizeof(patchLocations[0]) * patchLocations.size());
+    ::memcpy(buffer + patchInfo.patchTableArrayAddr - patchInfoAddr, &patchImages[0], sizeof(patchImages[0]) * patchImages.size());
+    ::memcpy(buffer + patchInfo.patchImageExportsArrayAddr - patchInfoAddr, &imageExports[0], sizeof(imageExports[0]) * imageExports.size());
+    ::memcpy(buffer + patchInfo.patchClientsArrayAddr - patchInfoAddr, &patchClients[0], sizeof(patchClients[0]) * patchClients.size());
+    ::memcpy(buffer + patchInfo.patchClientExportsArrayAddr - patchInfoAddr, &clientExports[0], sizeof(clientExports[0]) * clientExports.size());
+    ::memcpy(buffer + patchInfo.patchLocationArrayAddr - patchInfoAddr, &patchLocations[0], sizeof(patchLocations[0]) * patchLocations.size());
 
     // GOT patch table
-    if ( !gotClients.empty() )
-        ::memcpy(buffer + patchInfo.gotClientsArrayAddr - patchInfoAddr, &gotClients[0], sizeof(gotClients[0]) * gotClients.size());
-    if ( !gotClientExports.empty() )
-        ::memcpy(buffer + patchInfo.gotClientExportsArrayAddr - patchInfoAddr, &gotClientExports[0], sizeof(gotClientExports[0]) * gotClientExports.size());
-    if ( !gotPatchLocations.empty() )
-        ::memcpy(buffer + patchInfo.gotLocationArrayAddr - patchInfoAddr, &gotPatchLocations[0], sizeof(gotPatchLocations[0]) * gotPatchLocations.size());
+    ::memcpy(buffer + patchInfo.gotClientsArrayAddr - patchInfoAddr, &gotClients[0], sizeof(gotClients[0]) * gotClients.size());
+    ::memcpy(buffer + patchInfo.gotClientExportsArrayAddr - patchInfoAddr, &gotClientExports[0], sizeof(gotClientExports[0]) * gotClientExports.size());
+    ::memcpy(buffer + patchInfo.gotLocationArrayAddr - patchInfoAddr, &gotPatchLocations[0], sizeof(gotPatchLocations[0]) * gotPatchLocations.size());
 
     // Shared export names
-    if ( !patchExportNames.empty() )
-        ::memcpy(buffer + patchInfo.patchExportNamesAddr - patchInfoAddr, &patchExportNames[0], patchExportNames.size());
+    ::memcpy(buffer + patchInfo.patchExportNamesAddr - patchInfoAddr, &patchExportNames[0], patchExportNames.size());
     
     return Error();
 }
@@ -1265,17 +1014,15 @@
 
 dyld_cache_patchable_location::dyld_cache_patchable_location(CacheVMAddress cacheVMAddr,
                                                              dyld3::MachOFile::PointerMetaData pmd,
-                                                             uint64_t addend, bool isWeakImport)
+                                                             uint64_t addend)
 {
     this->cacheVMAddr          = cacheVMAddr;
     this->high7                = pmd.high8 >> 1;
-    this->isWeakImport         = isWeakImport ? 1 : 0;
-    this->unused               = 0;
+    this->addend               = addend;
     this->authenticated        = pmd.authenticated;
     this->usesAddressDiversity = pmd.usesAddrDiversity;
     this->key                  = pmd.key;
     this->discriminator        = pmd.diversity;
-    this->addend               = addend;
     // check for truncations
     assert(this->addend == addend);
     assert((this->high7 << 1) == pmd.high8);