dyld-635.2.tar.gz master macos-10141 v635.2
authorApple <opensource@apple.com>
Thu, 6 Dec 2018 05:24:58 +0000 (05:24 +0000)
committerApple <opensource@apple.com>
Thu, 6 Dec 2018 05:24:58 +0000 (05:24 +0000)
dyld3/AllImages.cpp
dyld3/AllImages.h
testing/test-cases/image_infos-uuids.dtest/foo.c [new file with mode: 0644]
testing/test-cases/image_infos-uuids.dtest/main.c [new file with mode: 0644]

index 5a696a7..38e7505 100644 (file)
@@ -200,6 +200,40 @@ void AllImages::mirrorToOldAllImageInfos()
         _oldAllImageInfos->infoArrayChangeTimestamp = mach_absolute_time();
         _oldAllImageInfos->infoArray                = _oldAllImageArray;
 
+        // <radr://problem/42668846> 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;
+        }
     });
 }
 
index 9880773..f542bec 100644 (file)
@@ -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 (file)
index 0000000..c8e9924
--- /dev/null
@@ -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 (file)
index 0000000..b96c698
--- /dev/null
@@ -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 <stdio.h>
+#include <dlfcn.h>
+#include <mach-o/loader.h>
+#include <mach-o/dyld_images.h>
+#include <uuid/uuid.h>
+
+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;
+}
+