From ba4c3badc27ea8c4637b4e91a49725742a02a53c Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 6 Dec 2018 05:24:58 +0000 Subject: [PATCH] dyld-635.2.tar.gz --- dyld3/AllImages.cpp | 34 +++++++ dyld3/AllImages.h | 2 + .../test-cases/image_infos-uuids.dtest/foo.c | 5 + .../test-cases/image_infos-uuids.dtest/main.c | 92 +++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 testing/test-cases/image_infos-uuids.dtest/foo.c create mode 100644 testing/test-cases/image_infos-uuids.dtest/main.c diff --git a/dyld3/AllImages.cpp b/dyld3/AllImages.cpp index 5a696a7..38e7505 100644 --- a/dyld3/AllImages.cpp +++ b/dyld3/AllImages.cpp @@ -200,6 +200,40 @@ void AllImages::mirrorToOldAllImageInfos() _oldAllImageInfos->infoArrayChangeTimestamp = mach_absolute_time(); _oldAllImageInfos->infoArray = _oldAllImageArray; + // update UUID array if needed + uint32_t nonCachedCount = 1; // always add dyld + for (const LoadedImage& li : _loadedImages) { + if ( !li.loadedAddress()->inDyldCache() ) + ++nonCachedCount; + } + if ( nonCachedCount != _oldAllImageInfos->uuidArrayCount ) { + // set infoArray to NULL to denote it is in-use + _oldAllImageInfos->uuidArray = nullptr; + // make sure allocation can hold all uuids + if ( _oldUUIDAllocCount < nonCachedCount ) { + uint32_t newAllocCount = (nonCachedCount + 3) & (-4); // round up to multiple of 4 + dyld_uuid_info* newArray = (dyld_uuid_info*)::malloc(sizeof(dyld_uuid_info)*newAllocCount); + if ( _oldUUIDArray != nullptr ) + ::free(_oldUUIDArray); + _oldUUIDArray = newArray; + _oldUUIDAllocCount = newAllocCount; + } + // add dyld then all images not in dyld cache + const MachOFile* dyldMF = (MachOFile*)_oldAllImageInfos->dyldImageLoadAddress; + _oldUUIDArray[0].imageLoadAddress = dyldMF; + dyldMF->getUuid(_oldUUIDArray[0].imageUUID); + index = 1; + for (const LoadedImage& li : _loadedImages) { + if ( !li.loadedAddress()->inDyldCache() ) { + _oldUUIDArray[index].imageLoadAddress = li.loadedAddress(); + li.loadedAddress()->getUuid(_oldUUIDArray[index].imageUUID); + ++index; + } + } + // set uuidArray back to base address of array (so kernel can now read) + _oldAllImageInfos->uuidArray = _oldUUIDArray; + _oldAllImageInfos->uuidArrayCount = nonCachedCount; + } }); } diff --git a/dyld3/AllImages.h b/dyld3/AllImages.h index 9880773..f542bec 100644 --- a/dyld3/AllImages.h +++ b/dyld3/AllImages.h @@ -178,8 +178,10 @@ private: ProgramVars* _programVars = nullptr; dyld_all_image_infos* _oldAllImageInfos = nullptr; dyld_image_info* _oldAllImageArray = nullptr; + dyld_uuid_info* _oldUUIDArray = nullptr; dyld_platform_t _platform = 0; uint32_t _oldArrayAllocCount = 0; + uint32_t _oldUUIDAllocCount = 0; closure::ImageNum _nextImageNum = 0; int32_t _gcCount = 0; bool _processDOFs = false; diff --git a/testing/test-cases/image_infos-uuids.dtest/foo.c b/testing/test-cases/image_infos-uuids.dtest/foo.c new file mode 100644 index 0000000..c8e9924 --- /dev/null +++ b/testing/test-cases/image_infos-uuids.dtest/foo.c @@ -0,0 +1,5 @@ +int foo() +{ + return 10; +} + diff --git a/testing/test-cases/image_infos-uuids.dtest/main.c b/testing/test-cases/image_infos-uuids.dtest/main.c new file mode 100644 index 0000000..b96c698 --- /dev/null +++ b/testing/test-cases/image_infos-uuids.dtest/main.c @@ -0,0 +1,92 @@ + +// BUILD: $CC foo.c -bundle -o $BUILD_DIR/test.bundle +// BUILD: $CC main.c -o $BUILD_DIR/image-list-uuid.exe -DRUN_DIR="$RUN_DIR" + +// RUN: ./image-list-uuid.exe + + +#include +#include +#include +#include +#include + +extern const struct mach_header __dso_handle; + +static void printUUIDs(const struct dyld_all_image_infos* infos) +{ + if ( infos->uuidArray != NULL ) { + for (int i=0; i < infos->uuidArrayCount; ++i) { + const struct dyld_uuid_info* nonCacheInfo = &infos->uuidArray[i]; + uuid_string_t uuidStr; + uuid_unparse_upper(nonCacheInfo->imageUUID, uuidStr); + printf("%p %s\n", nonCacheInfo->imageLoadAddress, uuidStr); + } + } +} + +int main() +{ + printf("[BEGIN] image_infos-uuids\n"); + + // NOTE: dyld_all_image_infos is private, but currently looked at by kernel during stackshots + // This test is to validate that the data available to the kernel is correct + + task_dyld_info_data_t task_dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + if ( task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count) ) { + printf("[FAIL] image_infos-uuids: task_info() failed\n"); + return 0; + } + const struct dyld_all_image_infos* infos = (struct dyld_all_image_infos*)(uintptr_t)task_dyld_info.all_image_info_addr; + + + if ( infos->uuidArray == NULL ) { + printf("[FAIL] infos->uuidArray == NULL\n"); + return 0; + } + if ( infos->uuidArrayCount < 2 ) { + // expect to contain main executable and dyld + printf("[FAIL] infos->uuidArrayCount != 2 (is %lu)\n", infos->uuidArrayCount); + return 0; + } + printUUIDs(infos); + uint32_t initialCount = infos->uuidArrayCount; + + bool foundMain = false; + bool foundDyld = false; + for (int i=0; i < infos->uuidArrayCount; ++i) { + const struct dyld_uuid_info* nonCacheInfo = &infos->uuidArray[i]; + if ( nonCacheInfo->imageLoadAddress == &__dso_handle ) + foundMain = true; + if ( nonCacheInfo->imageLoadAddress->filetype == MH_DYLINKER ) + foundDyld = true; + } + if ( !foundMain ) { + printf("[FAIL] image_infos-uuids uuid array does not contain main program\n"); + return 0; + } + if ( !foundDyld ) { + printf("[FAIL] image_infos-uuids uuid array does not contain dyld\n"); + return 0; + } + + void* handle = dlopen(RUN_DIR "/test.bundle", RTLD_LAZY); + if ( handle == NULL ) { + printf("[FAIL] image_infos-uuids %s\n", dlerror()); + return 0; + } + printf("loaded test.bundle\n"); + + // now expect UUID list to be three + if ( infos->uuidArrayCount != initialCount+1 ) { + // expect to contain main executable and dyld + printf("[FAIL] infos->uuidArrayCount was not incremented (is %lu)\n", infos->uuidArrayCount); + return 0; + } + printUUIDs(infos); + + printf("[PASS] image_infos-uuids\n"); + return 0; +} + -- 2.45.2