Loading...
--- dyld/dyld-1284.13/framework/ProcessScavenger.cpp
+++ dyld/dyld-1330/framework/ProcessScavenger.cpp
@@ -24,6 +24,7 @@
#include <fcntl.h>
#include <libgen.h>
+#include <algorithm>
#include <libproc.h>
#include <sys/mman.h>
#include <mach/task.h>
@@ -41,6 +42,7 @@
#include "Header.h"
#include "DyldSharedCache.h"
#include "Vector.h"
+#include "SafeVMPrimitives.h"
#include <sys/fsgetpath.h>
#include <mach-o/dyld_priv.h>
@@ -145,8 +147,19 @@
(void)vm_deallocate(mach_task_self(), (vm_address_t)localAddress, _size);
return;
}
+ remote_memory_audit_start();
memcpy(_data, (void *)localAddress, _size);
+ remote_memory_audit_end();
(void)vm_deallocate(mach_task_self(), (vm_address_t)localAddress, _size);
+ }
+ RemoteMap(const RemoteMap&) = delete;
+ RemoteMap(RemoteMap&& other) {
+ swap(other);
+ }
+ MmappedBuffer& operator=(const MmappedBuffer&) = delete;
+ RemoteMap& operator=(RemoteMap&& other) {
+ swap(other);
+ return *this;
}
~RemoteMap() {
if (_data) {
@@ -163,6 +176,12 @@
return _size;
}
private:
+ void swap(RemoteMap& other) {
+ if (this == &other) { return; }
+ using std::swap;
+ swap(_data, other._data);
+ swap(_size, other._size);
+ }
void* _data = nullptr;
vm_size_t _size = 0;
};
@@ -248,6 +267,8 @@
snapshotFlags.setFlag(SnapshotFlagsPointerSize4Bytes, true);
#endif
mach_vm_size_t size;
+ bool dyldFound = false;
+ bool mainExecutableFound = false;
for (mach_vm_address_t address = 0; ; address += size) {
vm_region_basic_info_data_64_t info;
mach_port_t objectName;
@@ -259,37 +280,58 @@
if ( info.protection != (VM_PROT_READ|VM_PROT_EXECUTE) ) {
continue;
}
- RemoteMap map(task, address, (size_t)size);
+ RemoteMap map(task, address, std::min((size_t)size, (size_t)PAGE_SIZE));
if (!map) {
continue;
}
auto mf = Header::isMachO(map.span());
- if (mf) {
- auto& image = images.addObject<Dictionary>();
- uint64_t preferredLoadAddress = mf->preferredLoadAddress();
- if (preferredLoadAddress) {
- image.addObjectForKey<Integer>(kDyldAtlasImagePreferredLoadAddressKey, preferredLoadAddress);
- }
- image.addObjectForKey<Integer>(kDyldAtlasImageLoadAddressKey, address);
- const char* installname = mf->installName();
- if (installname) {
- image.addObjectForKey<String>(kDyldAtlasImageInstallnameKey, installname);
- }
- uuid_t uuid;
- if (mf->getUuid(uuid)) {
- image.addObjectForKey<UUID>(kDyldAtlasImageUUIDKey, uuid);
- }
- char executablePath[PATH_MAX+1];
- int len = proc_regionfilename(pid, address, executablePath, PATH_MAX);
- if ( len != 0 ) {
- executablePath[len] = '\0';
- image.addObjectForKey<String>(kDyldAtlasImageFilePathKey, executablePath);
- }
- addSegmentArray(image, mf);
- }
if (!mf) {
continue;
}
+ uint32_t headerSize = mf->headerAndLoadCommandsSize();
+ if (headerSize > PAGE_SIZE) {
+ size_t newSize = (size_t)lsl::roundToNextAligned(PAGE_SIZE, headerSize);
+ auto newMap = RemoteMap(task, address, newSize);
+ map = std::move(newMap);
+ if (!map) {
+ continue;
+ }
+ mf = Header::isMachO(map.span());
+ if (!mf) {
+ continue;
+ }
+ }
+ if (mf->isDylinker()) {
+ dyldFound = true;
+ }
+ if (mf->isMainExecutable()) {
+ mainExecutableFound = true;
+ }
+ // If this is not dyld or a main executable we don't need to scan the region
+ if (!mf->isDylinker() && !mf->isMainExecutable()) { continue; }
+ auto& image = images.addObject<Dictionary>();
+ uint64_t preferredLoadAddress = mf->preferredLoadAddress();
+ if (preferredLoadAddress) {
+ image.addObjectForKey<Integer>(kDyldAtlasImagePreferredLoadAddressKey, preferredLoadAddress);
+ }
+ image.addObjectForKey<Integer>(kDyldAtlasImageLoadAddressKey, address);
+ const char* installname = mf->installName();
+ if (installname) {
+ image.addObjectForKey<String>(kDyldAtlasImageInstallnameKey, installname);
+ }
+ uuid_t uuid;
+ if (mf->getUuid(uuid)) {
+ image.addObjectForKey<UUID>(kDyldAtlasImageUUIDKey, uuid);
+ }
+ char executablePath[PATH_MAX+1];
+ int len = proc_regionfilename(pid, address, executablePath, PATH_MAX);
+ if ( len != 0 ) {
+ executablePath[len] = '\0';
+ image.addObjectForKey<String>(kDyldAtlasImageFilePathKey, executablePath);
+ }
+ addSegmentArray(image, mf);
+ // If we have found dyld and the main executable we are done, exit early
+ if (dyldFound && mainExecutableFound) { break; }
}
rootDictionary.addObjectForKey<Integer>(kDyldAtlasSnapshotInitialImageCount, 1);
rootDictionary.addObjectForKey<Integer>(kDyldAtlasSnapshotState, dyld_process_state_not_started);