Loading...
--- dyld/dyld-1162/common/CachePatching.cpp
+++ dyld/dyld-1245.1/common/CachePatching.cpp
@@ -746,6 +746,9 @@
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());
@@ -764,6 +767,7 @@
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];
@@ -787,8 +791,20 @@
}
// GOTs
- for ( bool auth : { false, true } ) {
- const auto& bindGOTUses = auth ? dylibPatchInfo.bindAuthGOTUses : dylibPatchInfo.bindGOTUses;
+ 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;
+ }
+
assert(cacheDylib.bindTargets.size() == bindGOTUses.size());
for ( uint32_t bindIndex = 0; bindIndex != cacheDylib.bindTargets.size(); ++bindIndex ) {
const CacheDylib::BindTarget& bindTarget = cacheDylib.bindTargets[bindIndex];
@@ -952,6 +968,19 @@
patchImage.patchClientsCount = 0;
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 ) {
@@ -1181,19 +1210,28 @@
// (dylib, client) patch table
::memcpy(buffer + patchInfoAddr - patchInfoAddr, &patchInfo, sizeof(dyld_cache_patch_info_v3));
- ::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());
+ 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());
// GOT patch table
- ::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());
+ 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());
// Shared export names
- ::memcpy(buffer + patchInfo.patchExportNamesAddr - patchInfoAddr, &patchExportNames[0], patchExportNames.size());
+ if ( !patchExportNames.empty() )
+ ::memcpy(buffer + patchInfo.patchExportNamesAddr - patchInfoAddr, &patchExportNames[0], patchExportNames.size());
return Error();
}