create_callback_file:
   59|  4.06k|void create_callback_file(const char *filename) {}

create_config_file:
   24|  25.1k|int create_config_file(const char* config_path, const char* config_filename, const uint8_t* data, size_t size) {
   25|  25.1k|  char filename[512];
   26|  25.1k|  char path[256];
   27|  25.1k|  char command[256];
   28|       |
   29|  25.1k|  sprintf(path, "%s/%s", getenv("HOME"), config_path);
   30|  25.1k|  sprintf(command, "mkdir -p %s", path);
   31|       |
   32|  25.1k|  system(command);
   33|       |
   34|  25.1k|  sprintf(filename, "%s/%s", path, config_filename);
   35|       |
   36|  25.1k|  FILE *fp = fopen(filename, "wb");
   37|  25.1k|  if (!fp) {
  ------------------
  |  Branch (37:7): [True: 0, False: 25.1k]
  ------------------
   38|      0|    return 1;
   39|      0|  }
   40|  25.1k|  fwrite(data, size, 1, fp);
   41|  25.1k|  fclose(fp);
   42|       |
   43|  25.1k|  return 0;
   44|  25.1k|}
remove_config_file:
   49|  25.1k|void remove_config_file(const char* config_path, const char* config_filename) {
   50|  25.1k|  char filename[512];
   51|  25.1k|  sprintf(filename, "%s/%s/%s", getenv("HOME"), config_path, config_filename);
   52|  25.1k|  unlink(filename);
   53|  25.1k|}
LLVMFuzzerTestOneInput:
   58|  8.37k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   59|  8.37k|  setenv("HOME", "/tmp", 1);
   60|       |
   61|       |  // Create implicit layer configuration file
   62|  8.37k|  int result = create_config_file(".local/share/vulkan/implicit_layer.d", "complex_layer.json", data, size);
   63|  8.37k|  if (result) {
  ------------------
  |  Branch (63:7): [True: 0, False: 8.37k]
  ------------------
   64|      0|    return 0;
   65|      0|  }
   66|       |  
   67|       |  // Create loader configuration file
   68|  8.37k|  result = create_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json", data, size);
   69|  8.37k|  if (result) {
  ------------------
  |  Branch (69:7): [True: 0, False: 8.37k]
  ------------------
   70|      0|    return 0;
   71|      0|  }
   72|       |
   73|       |  // Create icd configuration file
   74|  8.37k|  result = create_config_file(".local/share/vulkan/icd.d", "icd_test.json", data, size);
   75|  8.37k|  if (result) {
  ------------------
  |  Branch (75:7): [True: 0, False: 8.37k]
  ------------------
   76|      0|    return 0;
   77|      0|  }
   78|       |
   79|  8.37k|  setenv("VK_LOADER_LAYERS_ENABLE", "all", 1);
   80|       |
   81|       |
   82|  8.37k|  VkInstance inst = {0};
   83|  8.37k|  char *instance_layers[] = {
   84|  8.37k|    "VK_LAYER_KHRONOS_validation",
   85|  8.37k|    "VK_LAYER_test_layer_1",
   86|  8.37k|    "VK_LAYER_test_layer_2"
   87|  8.37k|  };
   88|  8.37k|  const VkApplicationInfo app = {
   89|  8.37k|      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
   90|  8.37k|      .pNext = NULL,
   91|  8.37k|      .pApplicationName = "TEST_APP",
   92|  8.37k|      .applicationVersion = 0,
   93|  8.37k|      .pEngineName = "TEST_ENGINE",
   94|  8.37k|      .engineVersion = 0,
   95|  8.37k|      .apiVersion = VK_API_VERSION_1_0,
  ------------------
  |  |   81|  8.37k|#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0
  |  |  ------------------
  |  |  |  |   60|  8.37k|    ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))
  |  |  ------------------
  ------------------
   96|  8.37k|  };
   97|  8.37k|  VkInstanceCreateInfo inst_info = {
   98|  8.37k|      .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
   99|  8.37k|      .pNext = NULL,
  100|  8.37k|      .pApplicationInfo = &app,
  101|  8.37k|      .enabledLayerCount = 1,
  102|  8.37k|      .ppEnabledLayerNames = (const char *const *)instance_layers,
  103|  8.37k|      .enabledExtensionCount = 0,
  104|  8.37k|      .ppEnabledExtensionNames = NULL,
  105|  8.37k|  };
  106|  8.37k|  VkResult err = vkCreateInstance(&inst_info, NULL, &inst);
  107|  8.37k|  if (err != VK_SUCCESS) {
  ------------------
  |  Branch (107:7): [True: 8.37k, False: 0]
  ------------------
  108|  8.37k|    goto out;
  109|  8.37k|  }
  110|       |
  111|      0|  vkDestroyInstance(inst, NULL);
  112|       |
  113|  8.37k|out:
  114|       |  // Clean up config files
  115|  8.37k|  remove_config_file(".local/share/vulkan/implicit_layer.d", "complex_layer.json");
  116|  8.37k|  remove_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json");
  117|  8.37k|  remove_config_file(".local/share/vulkan/icd.d", "icd_test.json");
  118|       |
  119|  8.37k|  return 0;
  120|      0|}

loader_alloc:
   34|    838|void *loader_alloc(const VkAllocationCallbacks *pAllocator, size_t size, VkSystemAllocationScope allocation_scope) {
   35|    838|    void *pMemory = NULL;
   36|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   37|       |    {
   38|       |#else
   39|    838|    if (pAllocator && pAllocator->pfnAllocation) {
  ------------------
  |  Branch (39:9): [True: 838, False: 0]
  |  Branch (39:23): [True: 0, False: 838]
  ------------------
   40|       |        // These are internal structures, so it's best to align everything to
   41|       |        // the largest unit size which is the size of a uint64_t.
   42|      0|        pMemory = pAllocator->pfnAllocation(pAllocator->pUserData, size, sizeof(uint64_t), allocation_scope);
   43|    838|    } else {
   44|    838|#endif
   45|    838|        pMemory = malloc(size);
   46|    838|    }
   47|       |
   48|    838|    return pMemory;
   49|    838|}
loader_calloc:
   51|   126M|void *loader_calloc(const VkAllocationCallbacks *pAllocator, size_t size, VkSystemAllocationScope allocation_scope) {
   52|   126M|    void *pMemory = NULL;
   53|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   54|       |    {
   55|       |#else
   56|   126M|    if (pAllocator && pAllocator->pfnAllocation) {
  ------------------
  |  Branch (56:9): [True: 126M, False: 8.37k]
  |  Branch (56:23): [True: 0, False: 126M]
  ------------------
   57|       |        // These are internal structures, so it's best to align everything to
   58|       |        // the largest unit size which is the size of a uint64_t.
   59|      0|        pMemory = pAllocator->pfnAllocation(pAllocator->pUserData, size, sizeof(uint64_t), allocation_scope);
   60|      0|        if (pMemory) {
  ------------------
  |  Branch (60:13): [True: 0, False: 0]
  ------------------
   61|      0|            memset(pMemory, 0, size);
   62|      0|        }
   63|   126M|    } else {
   64|   126M|#endif
   65|   126M|        pMemory = calloc(1, size);
   66|   126M|    }
   67|       |
   68|   126M|    return pMemory;
   69|   126M|}
loader_free:
   71|   194M|void loader_free(const VkAllocationCallbacks *pAllocator, void *pMemory) {
   72|   194M|    if (pMemory != NULL) {
  ------------------
  |  Branch (72:9): [True: 126M, False: 67.3M]
  ------------------
   73|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   74|       |        {
   75|       |#else
   76|   126M|        if (pAllocator && pAllocator->pfnFree) {
  ------------------
  |  Branch (76:13): [True: 126M, False: 0]
  |  Branch (76:27): [True: 0, False: 126M]
  ------------------
   77|      0|            pAllocator->pfnFree(pAllocator->pUserData, pMemory);
   78|   126M|        } else {
   79|   126M|#endif
   80|   126M|            free(pMemory);
   81|   126M|        }
   82|   126M|    }
   83|   194M|}
loader_realloc:
   86|  3.15M|                     VkSystemAllocationScope allocation_scope) {
   87|  3.15M|    void *pNewMem = NULL;
   88|  3.15M|    if (pMemory == NULL || orig_size == 0) {
  ------------------
  |  Branch (88:9): [True: 0, False: 3.15M]
  |  Branch (88:28): [True: 0, False: 3.15M]
  ------------------
   89|      0|        pNewMem = loader_alloc(pAllocator, size, allocation_scope);
   90|  3.15M|    } else if (size == 0) {
  ------------------
  |  Branch (90:16): [True: 0, False: 3.15M]
  ------------------
   91|      0|        loader_free(pAllocator, pMemory);
   92|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   93|       |#else
   94|  3.15M|    } else if (pAllocator && pAllocator->pfnReallocation) {
  ------------------
  |  Branch (94:16): [True: 3.15M, False: 0]
  |  Branch (94:30): [True: 0, False: 3.15M]
  ------------------
   95|       |        // These are internal structures, so it's best to align everything to
   96|       |        // the largest unit size which is the size of a uint64_t.
   97|      0|        pNewMem = pAllocator->pfnReallocation(pAllocator->pUserData, pMemory, size, sizeof(uint64_t), allocation_scope);
   98|      0|#endif
   99|  3.15M|    } else {
  100|  3.15M|        pNewMem = realloc(pMemory, size);
  101|       |        // Clear out the newly allocated memory. On failure realloc returns NULL and leaves the original block valid, so
  102|       |        // only write through pNewMem once we know it points at the resized allocation.
  103|  3.15M|        if (NULL != pNewMem && size > orig_size) {
  ------------------
  |  Branch (103:13): [True: 3.15M, False: 0]
  |  Branch (103:32): [True: 21.5k, False: 3.12M]
  ------------------
  104|  21.5k|            memset((uint8_t *)pNewMem + orig_size, 0, size - orig_size);
  105|  21.5k|        }
  106|  3.15M|    }
  107|  3.15M|    return pNewMem;
  108|  3.15M|}
loader_instance_heap_alloc:
  110|    838|void *loader_instance_heap_alloc(const struct loader_instance *inst, size_t size, VkSystemAllocationScope allocation_scope) {
  111|    838|    return loader_alloc(inst ? &inst->alloc_callbacks : NULL, size, allocation_scope);
  ------------------
  |  Branch (111:25): [True: 838, False: 0]
  ------------------
  112|    838|}
loader_instance_heap_calloc:
  114|  6.04M|void *loader_instance_heap_calloc(const struct loader_instance *inst, size_t size, VkSystemAllocationScope allocation_scope) {
  115|  6.04M|    return loader_calloc(inst ? &inst->alloc_callbacks : NULL, size, allocation_scope);
  ------------------
  |  Branch (115:26): [True: 6.04M, False: 0]
  ------------------
  116|  6.04M|}
loader_instance_heap_free:
  118|  76.5M|void loader_instance_heap_free(const struct loader_instance *inst, void *pMemory) {
  119|  76.5M|    loader_free(inst ? &inst->alloc_callbacks : NULL, pMemory);
  ------------------
  |  Branch (119:17): [True: 76.5M, False: 2]
  ------------------
  120|  76.5M|}
loader_instance_heap_realloc:
  122|  10.7k|                                   VkSystemAllocationScope allocation_scope) {
  123|  10.7k|    return loader_realloc(inst ? &inst->alloc_callbacks : NULL, pMemory, orig_size, size, allocation_scope);
  ------------------
  |  Branch (123:27): [True: 10.7k, False: 0]
  ------------------
  124|  10.7k|}

loader_cJSON_GetStringValue:
   98|  13.2M|CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
   99|  13.2M|    if (!loader_cJSON_IsString(item)) {
  ------------------
  |  Branch (99:9): [True: 4.05M, False: 9.17M]
  ------------------
  100|  4.05M|        return NULL;
  101|  4.05M|    }
  102|       |
  103|  9.17M|    return item->valuestring;
  104|  13.2M|}
loader_cJSON_Delete:
  151|  11.0M|TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
  152|  11.0M|    cJSON *next = NULL;
  153|  59.0M|    while (item != NULL) {
  ------------------
  |  Branch (153:12): [True: 47.9M, False: 11.0M]
  ------------------
  154|  47.9M|        next = item->next;
  155|  47.9M|        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
  ------------------
  |  |  106|  47.9M|#define cJSON_IsReference 256
  ------------------
  |  Branch (155:13): [True: 47.9M, False: 0]
  |  Branch (155:50): [True: 10.4M, False: 37.4M]
  ------------------
  156|  10.4M|            loader_cJSON_Delete(item->child);
  157|  10.4M|        }
  158|  47.9M|        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
  ------------------
  |  |  106|  47.9M|#define cJSON_IsReference 256
  ------------------
  |  Branch (158:13): [True: 47.9M, False: 0]
  |  Branch (158:50): [True: 32.6M, False: 15.3M]
  ------------------
  159|  32.6M|            loader_free(item->pAllocator, item->valuestring);
  160|  32.6M|            item->valuestring = NULL;
  161|  32.6M|        }
  162|  47.9M|        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
  ------------------
  |  |  107|  47.9M|#define cJSON_StringIsConst 512
  ------------------
  |  Branch (162:13): [True: 47.9M, False: 0]
  |  Branch (162:52): [True: 34.1M, False: 13.7M]
  ------------------
  163|  34.1M|            loader_free(item->pAllocator, item->string);
  164|       |            item->string = NULL;
  165|  34.1M|        }
  166|  47.9M|        loader_free(item->pAllocator, item);
  167|  47.9M|        item = next;
  168|  47.9M|    }
  169|  11.0M|}
loader_cJSON_ParseWithLengthOpts:
  848|   111k|                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
  849|   111k|    parse_buffer buffer = {0, 0, 0, 0, 0};
  850|   111k|    cJSON *item = NULL;
  851|       |
  852|       |    /* reset error position */
  853|       |    // global_error.json = NULL;
  854|       |    // global_error.position = 0;
  855|       |
  856|   111k|    if (value == NULL || 0 == buffer_length) {
  ------------------
  |  Branch (856:9): [True: 0, False: 111k]
  |  Branch (856:26): [True: 0, False: 111k]
  ------------------
  857|      0|        goto fail;
  858|      0|    }
  859|       |
  860|   111k|    buffer.content = (const unsigned char *)value;
  861|   111k|    buffer.length = buffer_length;
  862|   111k|    buffer.offset = 0;
  863|   111k|    buffer.pAllocator = pAllocator;
  864|       |
  865|   111k|    item = cJSON_New_Item(pAllocator);
  866|   111k|    if (item == NULL) /* memory fail */
  ------------------
  |  Branch (866:9): [True: 0, False: 111k]
  ------------------
  867|      0|    {
  868|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  869|      0|        goto fail;
  870|      0|    }
  871|       |
  872|   111k|    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
  ------------------
  |  Branch (872:9): [True: 29.4k, False: 82.0k]
  ------------------
  873|       |        /* parse failure. ep is set. */
  874|  29.4k|        goto fail;
  875|  29.4k|    }
  876|       |
  877|       |    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
  878|  82.0k|    if (require_null_terminated) {
  ------------------
  |  Branch (878:9): [True: 0, False: 82.0k]
  ------------------
  879|      0|        buffer_skip_whitespace(&buffer);
  880|      0|        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (880:13): [True: 0, False: 0]
  |  Branch (880:49): [True: 0, False: 0]
  ------------------
  881|      0|            goto fail;
  882|      0|        }
  883|      0|    }
  884|  82.0k|    if (return_parse_end) {
  ------------------
  |  Branch (884:9): [True: 0, False: 82.0k]
  ------------------
  885|      0|        *return_parse_end = (const char *)buffer_at_offset(&buffer);
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  886|      0|    }
  887|       |
  888|  82.0k|    return item;
  889|       |
  890|  29.4k|fail:
  891|  29.4k|    if (item != NULL) {
  ------------------
  |  Branch (891:9): [True: 29.4k, False: 0]
  ------------------
  892|  29.4k|        loader_cJSON_Delete(item);
  893|  29.4k|    }
  894|       |
  895|  29.4k|    if (value != NULL) {
  ------------------
  |  Branch (895:9): [True: 29.4k, False: 0]
  ------------------
  896|  29.4k|        error local_error;
  897|  29.4k|        local_error.json = (const unsigned char *)value;
  898|  29.4k|        local_error.position = 0;
  899|       |
  900|  29.4k|        if (buffer.offset < buffer.length) {
  ------------------
  |  Branch (900:13): [True: 28.3k, False: 1.07k]
  ------------------
  901|  28.3k|            local_error.position = buffer.offset;
  902|  28.3k|        } else if (buffer.length > 0) {
  ------------------
  |  Branch (902:20): [True: 1.07k, False: 0]
  ------------------
  903|  1.07k|            local_error.position = buffer.length - 1;
  904|  1.07k|        }
  905|       |
  906|  29.4k|        if (return_parse_end != NULL) {
  ------------------
  |  Branch (906:13): [True: 0, False: 29.4k]
  ------------------
  907|      0|            *return_parse_end = (const char *)local_error.json + local_error.position;
  908|      0|        }
  909|       |
  910|       |        // global_error = local_error;
  911|  29.4k|    }
  912|       |
  913|       |    return NULL;
  914|  82.0k|}
loader_cJSON_ParseWithLength:
  923|   111k|                             bool *out_of_memory) {
  924|   111k|    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
  925|   111k|}
loader_cJSON_Print:
  977|  3.12M|TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
  978|  3.12M|    return (char *)print(item, true, out_of_memory);
  ------------------
  |  |   67|  3.12M|#define true ((cJSON_bool)1)
  ------------------
  979|  3.12M|}
loader_cJSON_PrintPreallocated:
 1014|  7.33M|    loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
 1015|  7.33M|    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
 1016|       |
 1017|  7.33M|    if ((length < 0) || (buffer == NULL)) {
  ------------------
  |  Branch (1017:9): [True: 0, False: 7.33M]
  |  Branch (1017:25): [True: 0, False: 7.33M]
  ------------------
 1018|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1019|      0|    }
 1020|       |
 1021|  7.33M|    p.buffer = (unsigned char *)buffer;
 1022|  7.33M|    p.length = (size_t)length;
 1023|  7.33M|    p.offset = 0;
 1024|  7.33M|    p.noalloc = true;
  ------------------
  |  |   67|  7.33M|#define true ((cJSON_bool)1)
  ------------------
 1025|  7.33M|    p.format = format;
 1026|  7.33M|    p.pAllocator = item->pAllocator;
 1027|  7.33M|    bool out_of_memory = false;
  ------------------
  |  |   72|  7.33M|#define false ((cJSON_bool)0)
  ------------------
 1028|  7.33M|    return print_value(item, &p, &out_of_memory);
 1029|  7.33M|}
loader_cJSON_GetArraySize:
 1489|   438k|CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
 1490|   438k|    cJSON *child = NULL;
 1491|   438k|    size_t size = 0;
 1492|       |
 1493|   438k|    if (array == NULL) {
  ------------------
  |  Branch (1493:9): [True: 0, False: 438k]
  ------------------
 1494|      0|        return 0;
 1495|      0|    }
 1496|       |
 1497|   438k|    child = array->child;
 1498|       |
 1499|  1.87M|    while (child != NULL) {
  ------------------
  |  Branch (1499:12): [True: 1.43M, False: 438k]
  ------------------
 1500|  1.43M|        size++;
 1501|  1.43M|        child = child->next;
 1502|  1.43M|    }
 1503|       |
 1504|       |    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
 1505|       |
 1506|   438k|    return (int)size;
 1507|   438k|}
loader_cJSON_GetObjectItem:
 1559|  41.4M|CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
 1560|  41.4M|    return get_object_item(object, string, false);
  ------------------
  |  |   72|  41.4M|#define false ((cJSON_bool)0)
  ------------------
 1561|  41.4M|}
loader_cJSON_IsTrue:
 1671|     31|CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsTrue(const cJSON *const item) {
 1672|     31|    if (item == NULL) {
  ------------------
  |  Branch (1672:9): [True: 31, False: 0]
  ------------------
 1673|     31|        return false;
  ------------------
  |  |   72|     31|#define false ((cJSON_bool)0)
  ------------------
 1674|     31|    }
 1675|       |
 1676|      0|    return (item->type & 0xff) == cJSON_True;
  ------------------
  |  |   98|      0|#define cJSON_True (1 << 1)
  ------------------
 1677|     31|}
loader_cJSON_IsString:
 1702|  13.2M|CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
 1703|  13.2M|    if (item == NULL) {
  ------------------
  |  Branch (1703:9): [True: 4.05M, False: 9.17M]
  ------------------
 1704|  4.05M|        return false;
  ------------------
  |  |   72|  4.05M|#define false ((cJSON_bool)0)
  ------------------
 1705|  4.05M|    }
 1706|       |
 1707|  9.17M|    return (item->type & 0xFF) == cJSON_String;
  ------------------
  |  |  101|  9.17M|#define cJSON_String (1 << 4)
  ------------------
 1708|  13.2M|}
cJSON.c:cJSON_New_Item:
  142|  47.9M|static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
  143|  47.9M|    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  144|  47.9M|    if (NULL != node) {
  ------------------
  |  Branch (144:9): [True: 47.9M, False: 0]
  ------------------
  145|  47.9M|        node->pAllocator = pAllocator;
  146|  47.9M|    }
  147|  47.9M|    return node;
  148|  47.9M|}
cJSON.c:buffer_skip_whitespace:
  796|   175M|static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
  797|   175M|    if ((buffer == NULL) || (buffer->content == NULL)) {
  ------------------
  |  Branch (797:9): [True: 0, False: 175M]
  |  Branch (797:29): [True: 0, False: 175M]
  ------------------
  798|      0|        return NULL;
  799|      0|    }
  800|       |
  801|   175M|    if (cannot_access_at_index(buffer, 0)) {
  ------------------
  |  |  193|   175M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   175M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 175M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 175M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  802|      0|        return buffer;
  803|      0|    }
  804|       |
  805|   371M|    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  192|   742M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 371M, False: 0]
  |  |  |  Branch (192:65): [True: 371M, False: 9.90k]
  |  |  ------------------
  ------------------
                  while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  195|   371M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (805:46): [True: 195M, False: 175M]
  ------------------
  806|   195M|        buffer->offset++;
  807|   195M|    }
  808|       |
  809|   175M|    if (buffer->offset == buffer->length) {
  ------------------
  |  Branch (809:9): [True: 9.90k, False: 175M]
  ------------------
  810|  9.90k|        buffer->offset--;
  811|  9.90k|    }
  812|       |
  813|   175M|    return buffer;
  814|   175M|}
cJSON.c:skip_utf8_bom:
  817|   111k|static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
  818|   111k|    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
  ------------------
  |  Branch (818:9): [True: 0, False: 111k]
  |  Branch (818:29): [True: 0, False: 111k]
  |  Branch (818:58): [True: 0, False: 111k]
  ------------------
  819|      0|        return NULL;
  820|      0|    }
  821|       |
  822|   111k|    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  192|   222k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 111k, False: 0]
  |  |  |  Branch (192:65): [True: 91.6k, False: 19.7k]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  195|  91.6k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (822:43): [True: 315, False: 91.3k]
  ------------------
  823|    315|        buffer->offset += 3;
  824|    315|    }
  825|       |
  826|   111k|    return buffer;
  827|   111k|}
cJSON.c:print:
  929|  3.12M|static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
  930|  3.12M|    static const size_t default_buffer_size = 256;
  931|  3.12M|    printbuffer buffer[1];
  932|  3.12M|    unsigned char *printed = NULL;
  933|       |
  934|  3.12M|    memset(buffer, 0, sizeof(buffer));
  935|       |
  936|       |    /* create buffer */
  937|  3.12M|    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  938|  3.12M|    buffer->length = default_buffer_size;
  939|  3.12M|    buffer->format = format;
  940|  3.12M|    buffer->pAllocator = item->pAllocator;
  941|  3.12M|    if (buffer->buffer == NULL) {
  ------------------
  |  Branch (941:9): [True: 0, False: 3.12M]
  ------------------
  942|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  943|      0|        goto fail;
  944|      0|    }
  945|       |
  946|       |    /* print the value */
  947|  3.12M|    if (!print_value(item, buffer, out_of_memory)) {
  ------------------
  |  Branch (947:9): [True: 0, False: 3.12M]
  ------------------
  948|      0|        goto fail;
  949|      0|    }
  950|  3.12M|    update_offset(buffer);
  951|       |
  952|  3.12M|    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
  953|  3.12M|                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  954|  3.12M|    if (printed == NULL) {
  ------------------
  |  Branch (954:9): [True: 0, False: 3.12M]
  ------------------
  955|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  956|      0|        goto fail;
  957|      0|    }
  958|  3.12M|    buffer->buffer = NULL;
  959|       |
  960|  3.12M|    return printed;
  961|       |
  962|      0|fail:
  963|      0|    if (buffer->buffer != NULL) {
  ------------------
  |  Branch (963:9): [True: 0, False: 0]
  ------------------
  964|      0|        loader_free(item->pAllocator, buffer->buffer);
  965|      0|        buffer->buffer = NULL;
  966|      0|    }
  967|       |
  968|      0|    if (printed != NULL) {
  ------------------
  |  Branch (968:9): [True: 0, False: 0]
  ------------------
  969|      0|        loader_free(item->pAllocator, printed);
  970|      0|        printed = NULL;
  971|      0|    }
  972|       |
  973|       |    return NULL;
  974|  3.12M|}
cJSON.c:update_offset:
  355|  5.21M|static void update_offset(printbuffer *const buffer) {
  356|  5.21M|    const unsigned char *buffer_pointer = NULL;
  357|  5.21M|    if ((buffer == NULL) || (buffer->buffer == NULL)) {
  ------------------
  |  Branch (357:9): [True: 0, False: 5.21M]
  |  Branch (357:29): [True: 0, False: 5.21M]
  ------------------
  358|      0|        return;
  359|      0|    }
  360|  5.21M|    buffer_pointer = buffer->buffer + buffer->offset;
  361|       |
  362|  5.21M|    buffer->offset += strlen((const char *)buffer_pointer);
  363|  5.21M|}
cJSON.c:parse_value:
 1032|  47.9M|static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1033|  47.9M|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (1033:9): [True: 0, False: 47.9M]
  |  Branch (1033:35): [True: 0, False: 47.9M]
  ------------------
 1034|      0|        return false; /* no input */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1035|      0|    }
 1036|       |
 1037|       |    /* parse the different types of values */
 1038|       |    /* null */
 1039|  47.9M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  190|  95.8M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 47.9M, False: 0]
  |  |  |  Branch (190:53): [True: 47.8M, False: 24.9k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  195|  47.8M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1039:38): [True: 3.34k, False: 47.8M]
  ------------------
 1040|  3.34k|        item->type = cJSON_NULL;
  ------------------
  |  |   99|  3.34k|#define cJSON_NULL (1 << 2)
  ------------------
 1041|  3.34k|        input_buffer->offset += 4;
 1042|  3.34k|        return true;
  ------------------
  |  |   67|  3.34k|#define true ((cJSON_bool)1)
  ------------------
 1043|  3.34k|    }
 1044|       |    /* false */
 1045|  47.9M|    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  190|  95.8M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 47.9M, False: 0]
  |  |  |  Branch (190:53): [True: 47.8M, False: 28.0k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  195|  47.8M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1045:38): [True: 10.8k, False: 47.8M]
  ------------------
 1046|  10.8k|        item->type = cJSON_False;
  ------------------
  |  |   97|  10.8k|#define cJSON_False (1 << 0)
  ------------------
 1047|  10.8k|        input_buffer->offset += 5;
 1048|  10.8k|        return true;
  ------------------
  |  |   67|  10.8k|#define true ((cJSON_bool)1)
  ------------------
 1049|  10.8k|    }
 1050|       |    /* true */
 1051|  47.9M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  190|  95.8M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 47.9M, False: 0]
  |  |  |  Branch (190:53): [True: 47.8M, False: 24.9k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  195|  47.8M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1051:38): [True: 339k, False: 47.5M]
  ------------------
 1052|   339k|        item->type = cJSON_True;
  ------------------
  |  |   98|   339k|#define cJSON_True (1 << 1)
  ------------------
 1053|   339k|        item->valueint = 1;
 1054|   339k|        input_buffer->offset += 4;
 1055|   339k|        return true;
  ------------------
  |  |   67|   339k|#define true ((cJSON_bool)1)
  ------------------
 1056|   339k|    }
 1057|       |    /* string */
 1058|  47.5M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  192|  95.1M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 47.5M, False: 0]
  |  |  |  Branch (192:65): [True: 47.5M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  195|  47.5M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1058:49): [True: 32.6M, False: 14.9M]
  ------------------
 1059|  32.6M|        return parse_string(item, input_buffer, out_of_memory);
 1060|  32.6M|    }
 1061|       |    /* number */
 1062|  14.9M|    if (can_access_at_index(input_buffer, 0) &&
  ------------------
  |  |  192|  29.8M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 14.9M, False: 0]
  |  |  |  Branch (192:65): [True: 14.9M, False: 0]
  |  |  ------------------
  ------------------
 1063|  14.9M|        ((buffer_at_offset(input_buffer)[0] == '-') ||
  ------------------
  |  |  195|  14.9M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1063:10): [True: 17.0k, False: 14.9M]
  ------------------
 1064|  14.9M|         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|  14.9M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
                       ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|  14.9M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1064:11): [True: 14.9M, False: 9.93k]
  |  Branch (1064:57): [True: 2.86M, False: 12.0M]
  ------------------
 1065|  2.87M|        return parse_number(item, input_buffer);
 1066|  2.87M|    }
 1067|       |    /* array */
 1068|  12.0M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  192|  24.1M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 12.0M, False: 0]
  |  |  |  Branch (192:65): [True: 12.0M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  195|  12.0M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1068:49): [True: 2.56M, False: 9.49M]
  ------------------
 1069|  2.56M|        return parse_array(item, input_buffer, out_of_memory);
 1070|  2.56M|    }
 1071|       |    /* object */
 1072|  9.49M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  192|  18.9M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 9.49M, False: 0]
  |  |  |  Branch (192:65): [True: 9.49M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  195|  9.49M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1072:49): [True: 9.48M, False: 19.0k]
  ------------------
 1073|  9.48M|        return parse_object(item, input_buffer, out_of_memory);
 1074|  9.48M|    }
 1075|       |
 1076|  19.0k|    return false;
  ------------------
  |  |   72|  19.0k|#define false ((cJSON_bool)0)
  ------------------
 1077|  9.49M|}
cJSON.c:parse_string:
  557|  66.7M|static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
  558|  66.7M|    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  66.7M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  559|  66.7M|    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  66.7M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  560|  66.7M|    unsigned char *output_pointer = NULL;
  561|  66.7M|    unsigned char *output = NULL;
  562|       |
  563|       |    /* not a string */
  564|  66.7M|    if (buffer_at_offset(input_buffer)[0] != '\"') {
  ------------------
  |  |  195|  66.7M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (564:9): [True: 1.07k, False: 66.7M]
  ------------------
  565|  1.07k|        goto fail;
  566|  1.07k|    }
  567|       |
  568|  66.7M|    {
  569|       |        /* calculate approximate size of the output (overestimate) */
  570|  66.7M|        size_t allocation_length = 0;
  571|  66.7M|        size_t skipped_bytes = 0;
  572|   921M|        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
  ------------------
  |  Branch (572:16): [True: 921M, False: 3.66k]
  |  Branch (572:88): [True: 854M, False: 66.7M]
  ------------------
  573|       |            /* is escape sequence */
  574|   854M|            if (input_end[0] == '\\') {
  ------------------
  |  Branch (574:17): [True: 1.97M, False: 853M]
  ------------------
  575|  1.97M|                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
  ------------------
  |  Branch (575:21): [True: 0, False: 1.97M]
  ------------------
  576|       |                    /* prevent buffer overflow when last input character is a backslash */
  577|      0|                    goto fail;
  578|      0|                }
  579|  1.97M|                skipped_bytes++;
  580|  1.97M|                input_end++;
  581|  1.97M|            }
  582|   854M|            input_end++;
  583|   854M|        }
  584|  66.7M|        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
  ------------------
  |  Branch (584:13): [True: 3.66k, False: 66.7M]
  |  Branch (584:86): [True: 0, False: 66.7M]
  ------------------
  585|  3.66k|            goto fail; /* string ended unexpectedly */
  586|  3.66k|        }
  587|       |
  588|       |        /* This is at most how much we need for the output */
  589|  66.7M|        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
  ------------------
  |  |  195|  66.7M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  590|  66.7M|        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
  591|  66.7M|                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  592|  66.7M|        if (output == NULL) {
  ------------------
  |  Branch (592:13): [True: 0, False: 66.7M]
  ------------------
  593|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  594|      0|            goto fail; /* allocation failure */
  595|      0|        }
  596|  66.7M|    }
  597|       |
  598|  66.7M|    output_pointer = output;
  599|       |    /* loop through the string literal */
  600|   901M|    while (input_pointer < input_end) {
  ------------------
  |  Branch (600:12): [True: 834M, False: 66.7M]
  ------------------
  601|   834M|        if (*input_pointer != '\\') {
  ------------------
  |  Branch (601:13): [True: 832M, False: 1.76M]
  ------------------
  602|   832M|            *output_pointer++ = *input_pointer++;
  603|   832M|        }
  604|       |        /* escape sequence */
  605|  1.76M|        else {
  606|  1.76M|            unsigned char sequence_length = 2;
  607|  1.76M|            if ((input_end - input_pointer) < 1) {
  ------------------
  |  Branch (607:17): [True: 0, False: 1.76M]
  ------------------
  608|      0|                goto fail;
  609|      0|            }
  610|       |
  611|  1.76M|            switch (input_pointer[1]) {
  612|  59.9k|                case 'b':
  ------------------
  |  Branch (612:17): [True: 59.9k, False: 1.70M]
  ------------------
  613|  59.9k|                    *output_pointer++ = '\b';
  614|  59.9k|                    break;
  615|  12.7k|                case 'f':
  ------------------
  |  Branch (615:17): [True: 12.7k, False: 1.75M]
  ------------------
  616|  12.7k|                    *output_pointer++ = '\f';
  617|  12.7k|                    break;
  618|    784|                case 'n':
  ------------------
  |  Branch (618:17): [True: 784, False: 1.76M]
  ------------------
  619|    784|                    *output_pointer++ = '\n';
  620|    784|                    break;
  621|   191k|                case 'r':
  ------------------
  |  Branch (621:17): [True: 191k, False: 1.57M]
  ------------------
  622|   191k|                    *output_pointer++ = '\r';
  623|   191k|                    break;
  624|  21.5k|                case 't':
  ------------------
  |  Branch (624:17): [True: 21.5k, False: 1.74M]
  ------------------
  625|  21.5k|                    *output_pointer++ = '\t';
  626|  21.5k|                    break;
  627|    875|                case '\"':
  ------------------
  |  Branch (627:17): [True: 875, False: 1.76M]
  ------------------
  628|  5.80k|                case '\\':
  ------------------
  |  Branch (628:17): [True: 4.92k, False: 1.75M]
  ------------------
  629|  6.98k|                case '/':
  ------------------
  |  Branch (629:17): [True: 1.18k, False: 1.76M]
  ------------------
  630|  6.98k|                    *output_pointer++ = input_pointer[1];
  631|  6.98k|                    break;
  632|       |
  633|       |                /* UTF-16 literal */
  634|  1.46M|                case 'u':
  ------------------
  |  Branch (634:17): [True: 1.46M, False: 293k]
  ------------------
  635|  1.46M|                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
  636|  1.46M|                    if (sequence_length == 0) {
  ------------------
  |  Branch (636:25): [True: 3.44k, False: 1.46M]
  ------------------
  637|       |                        /* failed to convert UTF16-literal to UTF-8 */
  638|  3.44k|                        goto fail;
  639|  3.44k|                    }
  640|  1.46M|                    break;
  641|       |
  642|  1.46M|                default:
  ------------------
  |  Branch (642:17): [True: 24, False: 1.76M]
  ------------------
  643|     24|                    goto fail;
  644|  1.76M|            }
  645|  1.76M|            input_pointer += sequence_length;
  646|  1.76M|        }
  647|   834M|    }
  648|       |
  649|       |    /* zero terminate the output */
  650|  66.7M|    *output_pointer = '\0';
  651|       |
  652|  66.7M|    item->type = cJSON_String;
  ------------------
  |  |  101|  66.7M|#define cJSON_String (1 << 4)
  ------------------
  653|  66.7M|    item->valuestring = (char *)output;
  654|       |
  655|  66.7M|    input_buffer->offset = (size_t)(input_end - input_buffer->content);
  656|  66.7M|    input_buffer->offset++;
  657|       |
  658|  66.7M|    return true;
  ------------------
  |  |   67|  66.7M|#define true ((cJSON_bool)1)
  ------------------
  659|       |
  660|  8.20k|fail:
  661|  8.20k|    if (output != NULL) {
  ------------------
  |  Branch (661:9): [True: 3.46k, False: 4.74k]
  ------------------
  662|  3.46k|        loader_free(input_buffer->pAllocator, output);
  663|  3.46k|        output = NULL;
  664|  3.46k|    }
  665|       |
  666|  8.20k|    if (input_pointer != NULL) {
  ------------------
  |  Branch (666:9): [True: 8.20k, False: 0]
  ------------------
  667|  8.20k|        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
  668|  8.20k|    }
  669|       |
  670|  8.20k|    return false;
  ------------------
  |  |   72|  8.20k|#define false ((cJSON_bool)0)
  ------------------
  671|  66.7M|}
cJSON.c:utf16_literal_to_utf8:
  459|  1.46M|                                           unsigned char **output_pointer) {
  460|  1.46M|    long unsigned int codepoint = 0;
  461|  1.46M|    unsigned int first_code = 0;
  462|  1.46M|    const unsigned char *first_sequence = input_pointer;
  463|  1.46M|    unsigned char utf8_length = 0;
  464|  1.46M|    unsigned char utf8_position = 0;
  465|  1.46M|    unsigned char sequence_length = 0;
  466|  1.46M|    unsigned char first_byte_mark = 0;
  467|       |
  468|  1.46M|    if ((input_end - first_sequence) < 6) {
  ------------------
  |  Branch (468:9): [True: 14, False: 1.46M]
  ------------------
  469|       |        /* input ends unexpectedly */
  470|     14|        goto fail;
  471|     14|    }
  472|       |
  473|       |    /* get the first utf16 sequence */
  474|  1.46M|    first_code = parse_hex4(first_sequence + 2);
  475|       |
  476|       |    /* check that the code is valid */
  477|  1.46M|    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
  ------------------
  |  Branch (477:10): [True: 87.2k, False: 1.38M]
  |  Branch (477:36): [True: 1.14k, False: 86.0k]
  ------------------
  478|  1.14k|        goto fail;
  479|  1.14k|    }
  480|       |
  481|       |    /* UTF16 surrogate pair */
  482|  1.46M|    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
  ------------------
  |  Branch (482:9): [True: 92.6k, False: 1.37M]
  |  Branch (482:35): [True: 6.55k, False: 86.0k]
  ------------------
  483|  6.55k|        const unsigned char *second_sequence = first_sequence + 6;
  484|  6.55k|        unsigned int second_code = 0;
  485|  6.55k|        sequence_length = 12; /* \uXXXX\uXXXX */
  486|       |
  487|  6.55k|        if ((input_end - second_sequence) < 6) {
  ------------------
  |  Branch (487:13): [True: 669, False: 5.88k]
  ------------------
  488|       |            /* input ends unexpectedly */
  489|    669|            goto fail;
  490|    669|        }
  491|       |
  492|  5.88k|        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
  ------------------
  |  Branch (492:13): [True: 465, False: 5.42k]
  |  Branch (492:45): [True: 456, False: 4.96k]
  ------------------
  493|       |            /* missing second half of the surrogate pair */
  494|    921|            goto fail;
  495|    921|        }
  496|       |
  497|       |        /* get the second utf16 sequence */
  498|  4.96k|        second_code = parse_hex4(second_sequence + 2);
  499|       |        /* check that the code is valid */
  500|  4.96k|        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
  ------------------
  |  Branch (500:13): [True: 687, False: 4.28k]
  |  Branch (500:39): [True: 5, False: 4.27k]
  ------------------
  501|       |            /* invalid second half of the surrogate pair */
  502|    692|            goto fail;
  503|    692|        }
  504|       |
  505|       |        /* calculate the unicode codepoint from the surrogate pair */
  506|  4.27k|        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
  507|  1.46M|    } else {
  508|  1.46M|        sequence_length = 6; /* \uXXXX */
  509|  1.46M|        codepoint = first_code;
  510|  1.46M|    }
  511|       |
  512|       |    /* encode as UTF-8
  513|       |     * takes at maximum 4 bytes to encode:
  514|       |     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  515|  1.46M|    if (codepoint < 0x80) {
  ------------------
  |  Branch (515:9): [True: 1.32M, False: 144k]
  ------------------
  516|       |        /* normal ascii, encoding 0xxxxxxx */
  517|  1.32M|        utf8_length = 1;
  518|  1.32M|    } else if (codepoint < 0x800) {
  ------------------
  |  Branch (518:16): [True: 20.9k, False: 123k]
  ------------------
  519|       |        /* two bytes, encoding 110xxxxx 10xxxxxx */
  520|  20.9k|        utf8_length = 2;
  521|  20.9k|        first_byte_mark = 0xC0; /* 11000000 */
  522|   123k|    } else if (codepoint < 0x10000) {
  ------------------
  |  Branch (522:16): [True: 119k, False: 4.27k]
  ------------------
  523|       |        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
  524|   119k|        utf8_length = 3;
  525|   119k|        first_byte_mark = 0xE0; /* 11100000 */
  526|   119k|    } else if (codepoint <= 0x10FFFF) {
  ------------------
  |  Branch (526:16): [True: 4.27k, False: 0]
  ------------------
  527|       |        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
  528|  4.27k|        utf8_length = 4;
  529|  4.27k|        first_byte_mark = 0xF0; /* 11110000 */
  530|  4.27k|    } else {
  531|       |        /* invalid unicode codepoint */
  532|      0|        goto fail;
  533|      0|    }
  534|       |
  535|       |    /* encode as utf8 */
  536|  1.73M|    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
  ------------------
  |  Branch (536:60): [True: 272k, False: 1.46M]
  ------------------
  537|       |        /* 10xxxxxx */
  538|   272k|        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
  539|   272k|        codepoint >>= 6;
  540|   272k|    }
  541|       |    /* encode first byte */
  542|  1.46M|    if (utf8_length > 1) {
  ------------------
  |  Branch (542:9): [True: 144k, False: 1.32M]
  ------------------
  543|   144k|        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
  544|  1.32M|    } else {
  545|  1.32M|        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
  546|  1.32M|    }
  547|       |
  548|  1.46M|    *output_pointer += utf8_length;
  549|       |
  550|  1.46M|    return sequence_length;
  551|       |
  552|  3.44k|fail:
  553|  3.44k|    return 0;
  554|  1.46M|}
cJSON.c:parse_hex4:
  430|  1.47M|static unsigned parse_hex4(const unsigned char *const input) {
  431|  1.47M|    unsigned int h = 0;
  432|  1.47M|    size_t i = 0;
  433|       |
  434|  4.61M|    for (i = 0; i < 4; i++) {
  ------------------
  |  Branch (434:17): [True: 4.46M, False: 154k]
  ------------------
  435|       |        /* parse digit */
  436|  4.46M|        if ((input[i] >= '0') && (input[i] <= '9')) {
  ------------------
  |  Branch (436:13): [True: 4.21M, False: 243k]
  |  Branch (436:34): [True: 1.10M, False: 3.11M]
  ------------------
  437|  1.10M|            h += (unsigned int)input[i] - '0';
  438|  3.36M|        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
  ------------------
  |  Branch (438:20): [True: 2.90M, False: 457k]
  |  Branch (438:41): [True: 693k, False: 2.21M]
  ------------------
  439|   693k|            h += (unsigned int)10 + input[i] - 'A';
  440|  2.66M|        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
  ------------------
  |  Branch (440:20): [True: 1.94M, False: 725k]
  |  Branch (440:41): [True: 1.34M, False: 595k]
  ------------------
  441|  1.34M|            h += (unsigned int)10 + input[i] - 'a';
  442|  1.34M|        } else /* invalid */
  443|  1.32M|        {
  444|  1.32M|            return 0;
  445|  1.32M|        }
  446|       |
  447|  3.14M|        if (i < 3) {
  ------------------
  |  Branch (447:13): [True: 2.98M, False: 154k]
  ------------------
  448|       |            /* shift left to make place for the next nibble */
  449|  2.98M|            h = h << 4;
  450|  2.98M|        }
  451|  3.14M|    }
  452|       |
  453|   154k|    return h;
  454|  1.47M|}
cJSON.c:parse_number:
  198|  2.87M|static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
  199|  2.87M|    double number = 0;
  200|  2.87M|    unsigned char *after_end = NULL;
  201|  2.87M|    unsigned char *number_c_string;
  202|  2.87M|    unsigned char decimal_point = get_decimal_point();
  203|  2.87M|    size_t i = 0;
  204|  2.87M|    size_t number_string_length = 0;
  205|  2.87M|    cJSON_bool has_decimal_point = false;
  ------------------
  |  |   72|  2.87M|#define false ((cJSON_bool)0)
  ------------------
  206|       |
  207|  2.87M|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (207:9): [True: 0, False: 2.87M]
  |  Branch (207:35): [True: 0, False: 2.87M]
  ------------------
  208|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  209|      0|    }
  210|       |
  211|       |    /* copy the number into a temporary buffer and replace '.' with the decimal point
  212|       |     * of the current locale (for strtod)
  213|       |     * This also takes care of '\0' not necessarily being available for marking the end of the input */
  214|  8.68M|    for (i = 0; can_access_at_index(input_buffer, i); i++) {
  ------------------
  |  |  192|  8.68M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 8.68M, False: 0]
  |  |  |  Branch (192:65): [True: 8.68M, False: 0]
  |  |  ------------------
  ------------------
  215|  8.68M|        switch (buffer_at_offset(input_buffer)[i]) {
  ------------------
  |  |  195|  8.68M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  216|   623k|            case '0':
  ------------------
  |  Branch (216:13): [True: 623k, False: 8.05M]
  ------------------
  217|  2.75M|            case '1':
  ------------------
  |  Branch (217:13): [True: 2.13M, False: 6.54M]
  ------------------
  218|  3.07M|            case '2':
  ------------------
  |  Branch (218:13): [True: 314k, False: 8.36M]
  ------------------
  219|  3.23M|            case '3':
  ------------------
  |  Branch (219:13): [True: 162k, False: 8.51M]
  ------------------
  220|  3.38M|            case '4':
  ------------------
  |  Branch (220:13): [True: 148k, False: 8.53M]
  ------------------
  221|  3.55M|            case '5':
  ------------------
  |  Branch (221:13): [True: 166k, False: 8.51M]
  ------------------
  222|  4.13M|            case '6':
  ------------------
  |  Branch (222:13): [True: 589k, False: 8.09M]
  ------------------
  223|  4.38M|            case '7':
  ------------------
  |  Branch (223:13): [True: 248k, False: 8.43M]
  ------------------
  224|  4.63M|            case '8':
  ------------------
  |  Branch (224:13): [True: 248k, False: 8.43M]
  ------------------
  225|  5.25M|            case '9':
  ------------------
  |  Branch (225:13): [True: 615k, False: 8.06M]
  ------------------
  226|  5.25M|            case '+':
  ------------------
  |  Branch (226:13): [True: 2.43k, False: 8.67M]
  ------------------
  227|  5.27M|            case '-':
  ------------------
  |  Branch (227:13): [True: 18.7k, False: 8.66M]
  ------------------
  228|  5.75M|            case 'e':
  ------------------
  |  Branch (228:13): [True: 481k, False: 8.19M]
  ------------------
  229|  5.75M|            case 'E':
  ------------------
  |  Branch (229:13): [True: 3.12k, False: 8.67M]
  ------------------
  230|  5.75M|                number_string_length++;
  231|  5.75M|                break;
  232|       |
  233|  42.5k|            case '.':
  ------------------
  |  Branch (233:13): [True: 42.5k, False: 8.63M]
  ------------------
  234|  42.5k|                number_string_length++;
  235|  42.5k|                has_decimal_point = true;
  ------------------
  |  |   67|  42.5k|#define true ((cJSON_bool)1)
  ------------------
  236|  42.5k|                break;
  237|       |
  238|  2.87M|            default:
  ------------------
  |  Branch (238:13): [True: 2.87M, False: 5.80M]
  ------------------
  239|  2.87M|                goto loop_end;
  240|  8.68M|        }
  241|  8.68M|    }
  242|  2.87M|loop_end:
  243|       |    /* malloc for temporary buffer, add 1 for '\0' */
  244|  2.87M|    number_c_string =
  245|  2.87M|        (unsigned char *)loader_calloc(input_buffer->pAllocator, number_string_length + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  246|  2.87M|    if (number_c_string == NULL) {
  ------------------
  |  Branch (246:9): [True: 0, False: 2.87M]
  ------------------
  247|      0|        return false; /* allocation failure */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  248|      0|    }
  249|       |
  250|  2.87M|    memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
  ------------------
  |  |  195|  2.87M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  251|  2.87M|    number_c_string[number_string_length] = '\0';
  252|       |
  253|  2.87M|    if (has_decimal_point) {
  ------------------
  |  Branch (253:9): [True: 42.4k, False: 2.83M]
  ------------------
  254|   228k|        for (i = 0; i < number_string_length; i++) {
  ------------------
  |  Branch (254:21): [True: 185k, False: 42.4k]
  ------------------
  255|   185k|            if (number_c_string[i] == '.') {
  ------------------
  |  Branch (255:17): [True: 42.5k, False: 142k]
  ------------------
  256|       |                /* replace '.' with the decimal point of the current locale (for strtod) */
  257|  42.5k|                number_c_string[i] = decimal_point;
  258|  42.5k|            }
  259|   185k|        }
  260|  42.4k|    }
  261|       |
  262|  2.87M|    number = strtod((const char *)number_c_string, (char **)&after_end);
  263|  2.87M|    if (number_c_string == after_end) {
  ------------------
  |  Branch (263:9): [True: 1.12k, False: 2.87M]
  ------------------
  264|       |        /* free the temporary buffer */
  265|  1.12k|        loader_free(input_buffer->pAllocator, number_c_string);
  266|  1.12k|        return false; /* parse_error */
  ------------------
  |  |   72|  1.12k|#define false ((cJSON_bool)0)
  ------------------
  267|  1.12k|    }
  268|       |
  269|  2.87M|    item->valuedouble = number;
  270|       |
  271|       |    /* use saturation in case of overflow */
  272|  2.87M|    if (number >= INT_MAX) {
  ------------------
  |  Branch (272:9): [True: 202k, False: 2.67M]
  ------------------
  273|   202k|        item->valueint = INT_MAX;
  274|  2.67M|    } else if (number <= (double)INT_MIN) {
  ------------------
  |  Branch (274:16): [True: 9.01k, False: 2.66M]
  ------------------
  275|  9.01k|        item->valueint = INT_MIN;
  276|  2.66M|    } else {
  277|  2.66M|        item->valueint = (int)number;
  278|  2.66M|    }
  279|       |
  280|  2.87M|    item->type = cJSON_Number;
  ------------------
  |  |  100|  2.87M|#define cJSON_Number (1 << 3)
  ------------------
  281|       |
  282|  2.87M|    input_buffer->offset += (size_t)(after_end - number_c_string);
  283|       |    /* free the temporary buffer */
  284|  2.87M|    loader_free(input_buffer->pAllocator, number_c_string);
  285|  2.87M|    return true;
  ------------------
  |  |   67|  2.87M|#define true ((cJSON_bool)1)
  ------------------
  286|  2.87M|}
cJSON.c:get_decimal_point:
  172|  3.31M|static unsigned char get_decimal_point(void) {
  173|       |#ifdef ENABLE_LOCALES
  174|       |    struct lconv *lconv = localeconv();
  175|       |    return (unsigned char)lconv->decimal_point[0];
  176|       |#else
  177|  3.31M|    return '.';
  178|  3.31M|#endif
  179|  3.31M|}
cJSON.c:parse_array:
 1145|  2.56M|static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1146|  2.56M|    cJSON *head = NULL; /* head of the linked list */
 1147|  2.56M|    cJSON *current_item = NULL;
 1148|       |
 1149|  2.56M|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|  2.56M|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1149:9): [True: 441, False: 2.56M]
  ------------------
 1150|    441|        return false; /* to deeply nested */
  ------------------
  |  |   72|    441|#define false ((cJSON_bool)0)
  ------------------
 1151|    441|    }
 1152|  2.56M|    input_buffer->depth++;
 1153|       |
 1154|  2.56M|    if (buffer_at_offset(input_buffer)[0] != '[') {
  ------------------
  |  |  195|  2.56M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1154:9): [True: 0, False: 2.56M]
  ------------------
 1155|       |        /* not an array */
 1156|      0|        goto fail;
 1157|      0|    }
 1158|       |
 1159|  2.56M|    input_buffer->offset++;
 1160|  2.56M|    buffer_skip_whitespace(input_buffer);
 1161|  2.56M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  192|  5.13M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 2.56M, False: 0]
  |  |  |  Branch (192:65): [True: 2.56M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  195|  2.56M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1161:49): [True: 643k, False: 1.92M]
  ------------------
 1162|       |        /* empty array */
 1163|   643k|        goto success;
 1164|   643k|    }
 1165|       |
 1166|       |    /* check if we skipped to the end of the buffer */
 1167|  1.92M|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|  1.92M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  1.92M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 1.92M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 1.92M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1168|      0|        input_buffer->offset--;
 1169|      0|        goto fail;
 1170|      0|    }
 1171|       |
 1172|       |    /* step back to character in front of the first element */
 1173|  1.92M|    input_buffer->offset--;
 1174|       |    /* loop through the comma separated array elements */
 1175|  13.6M|    do {
 1176|       |        /* allocate next item */
 1177|  13.6M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1178|  13.6M|        if (new_item == NULL) {
  ------------------
  |  Branch (1178:13): [True: 0, False: 13.6M]
  ------------------
 1179|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1180|      0|            goto fail; /* allocation failure */
 1181|      0|        }
 1182|       |
 1183|       |        /* attach next item to list */
 1184|  13.6M|        if (head == NULL) {
  ------------------
  |  Branch (1184:13): [True: 1.92M, False: 11.7M]
  ------------------
 1185|       |            /* start the linked list */
 1186|  1.92M|            current_item = head = new_item;
 1187|  11.7M|        } else {
 1188|       |            /* add to the end and advance */
 1189|  11.7M|            current_item->next = new_item;
 1190|  11.7M|            new_item->prev = current_item;
 1191|  11.7M|            current_item = new_item;
 1192|  11.7M|        }
 1193|       |
 1194|       |        /* parse next value */
 1195|  13.6M|        input_buffer->offset++;
 1196|  13.6M|        buffer_skip_whitespace(input_buffer);
 1197|  13.6M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1197:13): [True: 512k, False: 13.1M]
  ------------------
 1198|   512k|            goto fail; /* failed to parse value */
 1199|   512k|        }
 1200|  13.1M|        buffer_skip_whitespace(input_buffer);
 1201|  13.1M|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  26.3M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 13.1M, False: 0]
  |  |  |  Branch (192:65): [True: 13.1M, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|  13.1M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1201:54): [True: 11.7M, False: 1.41M]
  ------------------
 1202|       |
 1203|  1.41M|    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  193|  2.82M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  1.41M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 1.41M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 1.41M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  195|  1.41M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1203:52): [True: 119, False: 1.41M]
  ------------------
 1204|    119|        goto fail; /* expected end of array */
 1205|    119|    }
 1206|       |
 1207|  2.05M|success:
 1208|  2.05M|    input_buffer->depth--;
 1209|       |
 1210|  2.05M|    if (head != NULL) {
  ------------------
  |  Branch (1210:9): [True: 1.41M, False: 643k]
  ------------------
 1211|  1.41M|        head->prev = current_item;
 1212|  1.41M|    }
 1213|       |
 1214|  2.05M|    item->type = cJSON_Array;
  ------------------
  |  |  102|  2.05M|#define cJSON_Array (1 << 5)
  ------------------
 1215|  2.05M|    item->child = head;
 1216|       |
 1217|  2.05M|    input_buffer->offset++;
 1218|       |
 1219|  2.05M|    return true;
  ------------------
  |  |   67|  2.05M|#define true ((cJSON_bool)1)
  ------------------
 1220|       |
 1221|   512k|fail:
 1222|   512k|    if (head != NULL) {
  ------------------
  |  Branch (1222:9): [True: 512k, False: 0]
  ------------------
 1223|   512k|        loader_cJSON_Delete(head);
 1224|   512k|    }
 1225|       |
 1226|   512k|    return false;
  ------------------
  |  |   72|   512k|#define false ((cJSON_bool)0)
  ------------------
 1227|  1.41M|}
cJSON.c:parse_object:
 1287|  9.48M|static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1288|  9.48M|    cJSON *head = NULL; /* linked list head */
 1289|  9.48M|    cJSON *current_item = NULL;
 1290|       |
 1291|  9.48M|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|  9.48M|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1291:9): [True: 3, False: 9.48M]
  ------------------
 1292|      3|        return false; /* to deeply nested */
  ------------------
  |  |   72|      3|#define false ((cJSON_bool)0)
  ------------------
 1293|      3|    }
 1294|  9.48M|    input_buffer->depth++;
 1295|       |
 1296|  9.48M|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  193|  18.9M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  9.48M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 9.48M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 9.48M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  195|  9.48M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1296:52): [True: 0, False: 9.48M]
  ------------------
 1297|      0|        goto fail; /* not an object */
 1298|      0|    }
 1299|       |
 1300|  9.48M|    input_buffer->offset++;
 1301|  9.48M|    buffer_skip_whitespace(input_buffer);
 1302|  9.48M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  192|  18.9M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 9.48M, False: 0]
  |  |  |  Branch (192:65): [True: 9.48M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  195|  9.48M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1302:49): [True: 424k, False: 9.05M]
  ------------------
 1303|   424k|        goto success; /* empty object */
 1304|   424k|    }
 1305|       |
 1306|       |    /* check if we skipped to the end of the buffer */
 1307|  9.05M|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|  9.05M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  9.05M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 9.05M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 9.05M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1308|      0|        input_buffer->offset--;
 1309|      0|        goto fail;
 1310|      0|    }
 1311|       |
 1312|       |    /* step back to character in front of the first element */
 1313|  9.05M|    input_buffer->offset--;
 1314|       |    /* loop through the comma separated array elements */
 1315|  34.1M|    do {
 1316|       |        /* allocate next item */
 1317|  34.1M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1318|  34.1M|        if (new_item == NULL) {
  ------------------
  |  Branch (1318:13): [True: 0, False: 34.1M]
  ------------------
 1319|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1320|      0|            goto fail; /* allocation failure */
 1321|      0|        }
 1322|       |
 1323|       |        /* attach next item to list */
 1324|  34.1M|        if (head == NULL) {
  ------------------
  |  Branch (1324:13): [True: 9.05M, False: 25.0M]
  ------------------
 1325|       |            /* start the linked list */
 1326|  9.05M|            current_item = head = new_item;
 1327|  25.0M|        } else {
 1328|       |            /* add to the end and advance */
 1329|  25.0M|            current_item->next = new_item;
 1330|  25.0M|            new_item->prev = current_item;
 1331|  25.0M|            current_item = new_item;
 1332|  25.0M|        }
 1333|       |
 1334|  34.1M|        if (cannot_access_at_index(input_buffer, 1)) {
  ------------------
  |  |  193|  34.1M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  34.1M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 34.1M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 34.1M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1335|      0|            goto fail; /* nothing comes after the comma */
 1336|      0|        }
 1337|       |
 1338|       |        /* parse the name of the child */
 1339|  34.1M|        input_buffer->offset++;
 1340|  34.1M|        buffer_skip_whitespace(input_buffer);
 1341|  34.1M|        if (!parse_string(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1341:13): [True: 2.03k, False: 34.1M]
  ------------------
 1342|  2.03k|            goto fail; /* failed to parse name */
 1343|  2.03k|        }
 1344|  34.1M|        buffer_skip_whitespace(input_buffer);
 1345|       |
 1346|       |        /* swap valuestring and string, because we parsed the name */
 1347|  34.1M|        current_item->string = current_item->valuestring;
 1348|  34.1M|        current_item->valuestring = NULL;
 1349|       |
 1350|  34.1M|        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  193|  68.2M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  34.1M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 34.1M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 34.1M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                      if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  195|  34.1M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1350:56): [True: 475, False: 34.1M]
  ------------------
 1351|    475|            goto fail; /* invalid object */
 1352|    475|        }
 1353|       |
 1354|       |        /* parse the value */
 1355|  34.1M|        input_buffer->offset++;
 1356|  34.1M|        buffer_skip_whitespace(input_buffer);
 1357|  34.1M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1357:13): [True: 17.7k, False: 34.1M]
  ------------------
 1358|  17.7k|            goto fail; /* failed to parse value */
 1359|  17.7k|        }
 1360|  34.1M|        buffer_skip_whitespace(input_buffer);
 1361|  34.1M|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  68.2M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 34.1M, False: 0]
  |  |  |  Branch (192:65): [True: 34.1M, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|  34.1M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1361:54): [True: 25.0M, False: 9.03M]
  ------------------
 1362|       |
 1363|  9.03M|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  193|  18.0M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  9.03M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 9.03M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 9.03M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  195|  9.03M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1363:52): [True: 22, False: 9.03M]
  ------------------
 1364|     22|        goto fail; /* expected end of object */
 1365|     22|    }
 1366|       |
 1367|  9.46M|success:
 1368|  9.46M|    input_buffer->depth--;
 1369|       |
 1370|  9.46M|    if (head != NULL) {
  ------------------
  |  Branch (1370:9): [True: 9.03M, False: 424k]
  ------------------
 1371|  9.03M|        head->prev = current_item;
 1372|  9.03M|    }
 1373|       |
 1374|  9.46M|    item->type = cJSON_Object;
  ------------------
  |  |  103|  9.46M|#define cJSON_Object (1 << 6)
  ------------------
 1375|  9.46M|    item->child = head;
 1376|       |
 1377|  9.46M|    input_buffer->offset++;
 1378|  9.46M|    return true;
  ------------------
  |  |   67|  9.46M|#define true ((cJSON_bool)1)
  ------------------
 1379|       |
 1380|  20.2k|fail:
 1381|  20.2k|    if (head != NULL) {
  ------------------
  |  Branch (1381:9): [True: 20.2k, False: 0]
  ------------------
 1382|  20.2k|        loader_cJSON_Delete(head);
 1383|  20.2k|    }
 1384|       |
 1385|  20.2k|    return false;
  ------------------
  |  |   72|  20.2k|#define false ((cJSON_bool)0)
  ------------------
 1386|  9.03M|}
cJSON.c:print_value:
 1080|  11.7M|static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
 1081|  11.7M|    unsigned char *output = NULL;
 1082|       |
 1083|  11.7M|    if ((item == NULL) || (output_buffer == NULL)) {
  ------------------
  |  Branch (1083:9): [True: 0, False: 11.7M]
  |  Branch (1083:27): [True: 0, False: 11.7M]
  ------------------
 1084|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1085|      0|    }
 1086|       |
 1087|  11.7M|    switch ((item->type) & 0xFF) {
 1088|    480|        case cJSON_NULL:
  ------------------
  |  |   99|    480|#define cJSON_NULL (1 << 2)
  ------------------
  |  Branch (1088:9): [True: 480, False: 11.7M]
  ------------------
 1089|    480|            output = ensure(output_buffer, 5, out_of_memory);
 1090|    480|            if (output == NULL) {
  ------------------
  |  Branch (1090:17): [True: 0, False: 480]
  ------------------
 1091|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1092|      0|            }
 1093|    480|            strcpy((char *)output, "null");
 1094|    480|            return true;
  ------------------
  |  |   67|    480|#define true ((cJSON_bool)1)
  ------------------
 1095|       |
 1096|  3.17k|        case cJSON_False:
  ------------------
  |  |   97|  3.17k|#define cJSON_False (1 << 0)
  ------------------
  |  Branch (1096:9): [True: 3.17k, False: 11.7M]
  ------------------
 1097|  3.17k|            output = ensure(output_buffer, 6, out_of_memory);
 1098|  3.17k|            if (output == NULL) {
  ------------------
  |  Branch (1098:17): [True: 0, False: 3.17k]
  ------------------
 1099|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1100|      0|            }
 1101|  3.17k|            strcpy((char *)output, "false");
 1102|  3.17k|            return true;
  ------------------
  |  |   67|  3.17k|#define true ((cJSON_bool)1)
  ------------------
 1103|       |
 1104|  50.8k|        case cJSON_True:
  ------------------
  |  |   98|  50.8k|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (1104:9): [True: 50.8k, False: 11.7M]
  ------------------
 1105|  50.8k|            output = ensure(output_buffer, 5, out_of_memory);
 1106|  50.8k|            if (output == NULL) {
  ------------------
  |  Branch (1106:17): [True: 0, False: 50.8k]
  ------------------
 1107|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1108|      0|            }
 1109|  50.8k|            strcpy((char *)output, "true");
 1110|  50.8k|            return true;
  ------------------
  |  |   67|  50.8k|#define true ((cJSON_bool)1)
  ------------------
 1111|       |
 1112|   430k|        case cJSON_Number:
  ------------------
  |  |  100|   430k|#define cJSON_Number (1 << 3)
  ------------------
  |  Branch (1112:9): [True: 430k, False: 11.3M]
  ------------------
 1113|   430k|            return print_number(item, output_buffer, out_of_memory);
 1114|       |
 1115|      0|        case cJSON_Raw: {
  ------------------
  |  |  104|      0|#define cJSON_Raw (1 << 7) /* raw json */
  ------------------
  |  Branch (1115:9): [True: 0, False: 11.7M]
  ------------------
 1116|      0|            size_t raw_length = 0;
 1117|      0|            if (item->valuestring == NULL) {
  ------------------
  |  Branch (1117:17): [True: 0, False: 0]
  ------------------
 1118|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1119|      0|            }
 1120|       |
 1121|      0|            raw_length = strlen(item->valuestring) + sizeof("");
 1122|      0|            output = ensure(output_buffer, raw_length, out_of_memory);
 1123|      0|            if (output == NULL) {
  ------------------
  |  Branch (1123:17): [True: 0, False: 0]
  ------------------
 1124|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1125|      0|            }
 1126|      0|            memcpy(output, item->valuestring, raw_length);
 1127|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1128|      0|        }
 1129|       |
 1130|  10.5M|        case cJSON_String:
  ------------------
  |  |  101|  10.5M|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (1130:9): [True: 10.5M, False: 1.22M]
  ------------------
 1131|  10.5M|            return print_string(item, output_buffer, out_of_memory);
 1132|       |
 1133|   217k|        case cJSON_Array:
  ------------------
  |  |  102|   217k|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (1133:9): [True: 217k, False: 11.5M]
  ------------------
 1134|   217k|            return print_array(item, output_buffer, out_of_memory);
 1135|       |
 1136|   519k|        case cJSON_Object:
  ------------------
  |  |  103|   519k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (1136:9): [True: 519k, False: 11.2M]
  ------------------
 1137|   519k|            return print_object(item, output_buffer, out_of_memory);
 1138|       |
 1139|      0|        default:
  ------------------
  |  Branch (1139:9): [True: 0, False: 11.7M]
  ------------------
 1140|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1141|  11.7M|    }
 1142|  11.7M|}
cJSON.c:ensure:
  299|  15.9M|static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
  300|  15.9M|    unsigned char *newbuffer = NULL;
  301|  15.9M|    size_t newsize = 0;
  302|       |
  303|  15.9M|    if ((p == NULL) || (p->buffer == NULL)) {
  ------------------
  |  Branch (303:9): [True: 0, False: 15.9M]
  |  Branch (303:24): [True: 0, False: 15.9M]
  ------------------
  304|      0|        return NULL;
  305|      0|    }
  306|       |
  307|  15.9M|    if ((p->length > 0) && (p->offset >= p->length)) {
  ------------------
  |  Branch (307:9): [True: 15.9M, False: 0]
  |  Branch (307:28): [True: 0, False: 15.9M]
  ------------------
  308|       |        /* make sure that offset is valid */
  309|      0|        return NULL;
  310|      0|    }
  311|       |
  312|  15.9M|    if (needed > INT_MAX) {
  ------------------
  |  Branch (312:9): [True: 0, False: 15.9M]
  ------------------
  313|       |        /* sizes bigger than INT_MAX are currently not supported */
  314|      0|        return NULL;
  315|      0|    }
  316|       |
  317|  15.9M|    needed += p->offset + 1;
  318|  15.9M|    if (needed <= p->length) {
  ------------------
  |  Branch (318:9): [True: 15.9M, False: 16.4k]
  ------------------
  319|  15.9M|        return p->buffer + p->offset;
  320|  15.9M|    }
  321|       |
  322|  16.4k|    if (p->noalloc) {
  ------------------
  |  Branch (322:9): [True: 5.60k, False: 10.8k]
  ------------------
  323|  5.60k|        return NULL;
  324|  5.60k|    }
  325|       |
  326|       |    /* calculate new buffer size */
  327|  10.8k|    if (needed > (INT_MAX / 2)) {
  ------------------
  |  Branch (327:9): [True: 0, False: 10.8k]
  ------------------
  328|       |        /* overflow of int, use INT_MAX if possible */
  329|      0|        if (needed <= INT_MAX) {
  ------------------
  |  Branch (329:13): [True: 0, False: 0]
  ------------------
  330|      0|            newsize = INT_MAX;
  331|      0|        } else {
  332|      0|            return NULL;
  333|      0|        }
  334|  10.8k|    } else {
  335|  10.8k|        newsize = needed * 2;
  336|  10.8k|    }
  337|       |
  338|  10.8k|    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  339|  10.8k|    if (newbuffer == NULL) {
  ------------------
  |  Branch (339:9): [True: 0, False: 10.8k]
  ------------------
  340|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  341|      0|        loader_free(p->pAllocator, p->buffer);
  342|      0|        p->length = 0;
  343|      0|        p->buffer = NULL;
  344|       |
  345|      0|        return NULL;
  346|      0|    }
  347|       |
  348|  10.8k|    p->length = newsize;
  349|  10.8k|    p->buffer = newbuffer;
  350|       |
  351|  10.8k|    return newbuffer + p->offset;
  352|  10.8k|}
cJSON.c:print_number:
  372|   430k|static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
  373|   430k|    unsigned char *output_pointer = NULL;
  374|   430k|    double d = item->valuedouble;
  375|   430k|    int length = 0;
  376|   430k|    size_t i = 0;
  377|   430k|    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
  378|   430k|    unsigned char decimal_point = get_decimal_point();
  379|   430k|    double test = 0.0;
  380|       |
  381|   430k|    if (output_buffer == NULL) {
  ------------------
  |  Branch (381:9): [True: 0, False: 430k]
  ------------------
  382|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  383|      0|    }
  384|       |
  385|       |    /* This checks for NaN and Infinity */
  386|   430k|    if (isnan(d) || isinf(d)) {
  ------------------
  |  Branch (386:9): [True: 0, False: 430k]
  |  Branch (386:21): [True: 1.16k, False: 429k]
  ------------------
  387|  1.16k|        length = snprintf((char *)number_buffer, 26, "null");
  388|   429k|    } else if (d == (double)item->valueint) {
  ------------------
  |  Branch (388:16): [True: 374k, False: 55.2k]
  ------------------
  389|   374k|        length = snprintf((char *)number_buffer, 26, "%d", item->valueint);
  390|   374k|    } else {
  391|       |        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
  392|  55.2k|        length = snprintf((char *)number_buffer, 26, "%1.15g", d);
  393|       |
  394|       |        /* Check whether the original double can be recovered */
  395|  55.2k|        if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) {
  ------------------
  |  Branch (395:13): [True: 0, False: 55.2k]
  |  Branch (395:67): [True: 2.51k, False: 52.7k]
  ------------------
  396|       |            /* If not, print with 17 decimal places of precision */
  397|  2.51k|            length = snprintf((char *)number_buffer, 26, "%1.17g", d);
  398|  2.51k|        }
  399|  55.2k|    }
  400|       |
  401|       |    /* snprintf failed or buffer overrun occurred */
  402|   430k|    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
  ------------------
  |  Branch (402:9): [True: 0, False: 430k]
  |  Branch (402:25): [True: 0, False: 430k]
  ------------------
  403|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  404|      0|    }
  405|       |
  406|       |    /* reserve appropriate space in the output */
  407|   430k|    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""), out_of_memory);
  408|   430k|    if (output_pointer == NULL) {
  ------------------
  |  Branch (408:9): [True: 0, False: 430k]
  ------------------
  409|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  410|      0|    }
  411|       |
  412|       |    /* copy the printed number to the output and replace locale
  413|       |     * dependent decimal point with '.' */
  414|  1.14M|    for (i = 0; i < ((size_t)length); i++) {
  ------------------
  |  Branch (414:17): [True: 711k, False: 430k]
  ------------------
  415|   711k|        if (number_buffer[i] == decimal_point) {
  ------------------
  |  Branch (415:13): [True: 3.13k, False: 708k]
  ------------------
  416|  3.13k|            output_pointer[i] = '.';
  417|  3.13k|            continue;
  418|  3.13k|        }
  419|       |
  420|   708k|        output_pointer[i] = number_buffer[i];
  421|   708k|    }
  422|   430k|    output_pointer[i] = '\0';
  423|       |
  424|   430k|    output_buffer->offset += (size_t)length;
  425|       |
  426|   430k|    return true;
  ------------------
  |  |   67|   430k|#define true ((cJSON_bool)1)
  ------------------
  427|   430k|}
cJSON.c:print_string:
  783|  10.5M|static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
  784|  10.5M|    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
  785|  10.5M|}
cJSON.c:print_string_ptr:
  674|  11.3M|static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
  675|  11.3M|    const unsigned char *input_pointer = NULL;
  676|  11.3M|    unsigned char *output = NULL;
  677|  11.3M|    unsigned char *output_pointer = NULL;
  678|  11.3M|    size_t output_length = 0;
  679|       |    /* numbers of additional characters needed for escaping */
  680|  11.3M|    size_t escape_characters = 0;
  681|       |
  682|  11.3M|    if (output_buffer == NULL) {
  ------------------
  |  Branch (682:9): [True: 0, False: 11.3M]
  ------------------
  683|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  684|      0|    }
  685|       |
  686|       |    /* empty string */
  687|  11.3M|    if (input == NULL) {
  ------------------
  |  Branch (687:9): [True: 0, False: 11.3M]
  ------------------
  688|      0|        output = ensure(output_buffer, sizeof(""), out_of_memory);
  689|      0|        if (output == NULL) {
  ------------------
  |  Branch (689:13): [True: 0, False: 0]
  ------------------
  690|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  691|      0|        }
  692|       |
  693|      0|        return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  694|      0|    }
  695|       |
  696|       |    /* set "flag" to 1 if something needs to be escaped */
  697|   116M|    for (input_pointer = input; *input_pointer; input_pointer++) {
  ------------------
  |  Branch (697:33): [True: 104M, False: 11.3M]
  ------------------
  698|   104M|        switch (*input_pointer) {
  699|    226|            case '\"':
  ------------------
  |  Branch (699:13): [True: 226, False: 104M]
  ------------------
  700|    878|            case '\\':
  ------------------
  |  Branch (700:13): [True: 652, False: 104M]
  ------------------
  701|  8.60k|            case '\b':
  ------------------
  |  Branch (701:13): [True: 7.72k, False: 104M]
  ------------------
  702|  11.1k|            case '\f':
  ------------------
  |  Branch (702:13): [True: 2.55k, False: 104M]
  ------------------
  703|  94.9k|            case '\n':
  ------------------
  |  Branch (703:13): [True: 83.7k, False: 104M]
  ------------------
  704|   155k|            case '\r':
  ------------------
  |  Branch (704:13): [True: 60.8k, False: 104M]
  ------------------
  705|   347k|            case '\t':
  ------------------
  |  Branch (705:13): [True: 191k, False: 104M]
  ------------------
  706|       |                /* one character escape sequence */
  707|   347k|                escape_characters++;
  708|   347k|                break;
  709|   104M|            default:
  ------------------
  |  Branch (709:13): [True: 104M, False: 347k]
  ------------------
  710|   104M|                if (*input_pointer < 32) {
  ------------------
  |  Branch (710:21): [True: 45.4M, False: 59.1M]
  ------------------
  711|       |                    /* UTF-16 escape sequence uXXXX */
  712|  45.4M|                    escape_characters += 5;
  713|  45.4M|                }
  714|   104M|                break;
  715|   104M|        }
  716|   104M|    }
  717|  11.3M|    output_length = (size_t)(input_pointer - input) + escape_characters;
  718|       |
  719|  11.3M|    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
  720|  11.3M|    if (output == NULL) {
  ------------------
  |  Branch (720:9): [True: 5.60k, False: 11.3M]
  ------------------
  721|  5.60k|        return false;
  ------------------
  |  |   72|  5.60k|#define false ((cJSON_bool)0)
  ------------------
  722|  5.60k|    }
  723|       |
  724|       |    /* no characters have to be escaped */
  725|  11.3M|    if (escape_characters == 0) {
  ------------------
  |  Branch (725:9): [True: 10.9M, False: 391k]
  ------------------
  726|  10.9M|        memcpy(output, input, output_length);
  727|  10.9M|        output[output_length] = '\0';
  728|       |
  729|  10.9M|        return true;
  ------------------
  |  |   67|  10.9M|#define true ((cJSON_bool)1)
  ------------------
  730|  10.9M|    }
  731|       |
  732|   391k|    output_pointer = output;
  733|       |    /* copy the string */
  734|  54.5M|    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
  ------------------
  |  Branch (734:33): [True: 54.1M, False: 391k]
  ------------------
  735|  54.1M|        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
  ------------------
  |  Branch (735:13): [True: 9.21M, False: 44.9M]
  |  Branch (735:38): [True: 9.21M, False: 226]
  |  Branch (735:66): [True: 9.21M, False: 646]
  ------------------
  736|       |            /* normal character, copy */
  737|  9.21M|            *output_pointer = *input_pointer;
  738|  44.9M|        } else {
  739|       |            // Loader specific modification - don't add a backslash because that will 'double up' any existing back slashes.
  740|       |            // This change was added right after vulkan's public release, so while it may not be a problem, there are plenty
  741|       |            // of API calls made which might not work if the paths have "\\"" in them
  742|       |            /* character needs to be escaped */
  743|       |            //*output_pointer++ = '\\';
  744|  44.9M|            switch (*input_pointer) {
  745|    646|                case '\\':
  ------------------
  |  Branch (745:17): [True: 646, False: 44.9M]
  ------------------
  746|    646|                    *output_pointer = '\\';
  747|    646|                    break;
  748|    226|                case '\"':
  ------------------
  |  Branch (748:17): [True: 226, False: 44.9M]
  ------------------
  749|    226|                    *output_pointer = '\"';
  750|    226|                    break;
  751|  7.70k|                case '\b':
  ------------------
  |  Branch (751:17): [True: 7.70k, False: 44.9M]
  ------------------
  752|  7.70k|                    *output_pointer = '\b';
  753|  7.70k|                    break;
  754|  2.55k|                case '\f':
  ------------------
  |  Branch (754:17): [True: 2.55k, False: 44.9M]
  ------------------
  755|  2.55k|                    *output_pointer = '\f';
  756|  2.55k|                    break;
  757|  76.9k|                case '\n':
  ------------------
  |  Branch (757:17): [True: 76.9k, False: 44.8M]
  ------------------
  758|  76.9k|                    *output_pointer = '\n';
  759|  76.9k|                    break;
  760|  60.1k|                case '\r':
  ------------------
  |  Branch (760:17): [True: 60.1k, False: 44.8M]
  ------------------
  761|  60.1k|                    *output_pointer = '\r';
  762|  60.1k|                    break;
  763|   191k|                case '\t':
  ------------------
  |  Branch (763:17): [True: 191k, False: 44.7M]
  ------------------
  764|   191k|                    *output_pointer = '\t';
  765|   191k|                    break;
  766|  44.5M|                default:
  ------------------
  |  Branch (766:17): [True: 44.5M, False: 339k]
  ------------------
  767|       |                    /* escape and print as unicode codepoint */
  768|  44.5M|                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
  769|  44.5M|                    output_pointer += 4;
  770|  44.5M|                    break;
  771|  44.9M|            }
  772|  44.9M|        }
  773|  54.1M|    }
  774|       |    // The loader-specific escaping above emits one byte where the standard form emits two, so the written
  775|       |    // length is shorter than output_length. Terminate at the actual end, otherwise the bytes between it and
  776|       |    // output_length (uninitialized when the caller buffer is not zeroed) get read back as part of the string.
  777|   391k|    *output_pointer = '\0';
  778|       |
  779|   391k|    return true;
  ------------------
  |  |   67|   391k|#define true ((cJSON_bool)1)
  ------------------
  780|   391k|}
cJSON.c:print_array:
 1230|   217k|static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
 1231|   217k|    unsigned char *output_pointer = NULL;
 1232|   217k|    size_t length = 0;
 1233|   217k|    cJSON *current_element = item->child;
 1234|       |
 1235|   217k|    if (output_buffer == NULL) {
  ------------------
  |  Branch (1235:9): [True: 0, False: 217k]
  ------------------
 1236|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1237|      0|    }
 1238|       |
 1239|   217k|    if (output_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   217k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1239:9): [True: 0, False: 217k]
  ------------------
 1240|      0|        return false; /* nesting is too deep */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1241|      0|    }
 1242|       |
 1243|       |    /* Compose the output array. */
 1244|       |    /* opening square bracket */
 1245|   217k|    output_pointer = ensure(output_buffer, 1, out_of_memory);
 1246|   217k|    if (output_pointer == NULL) {
  ------------------
  |  Branch (1246:9): [True: 0, False: 217k]
  ------------------
 1247|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1248|      0|    }
 1249|       |
 1250|   217k|    *output_pointer = '[';
 1251|   217k|    output_buffer->offset++;
 1252|   217k|    output_buffer->depth++;
 1253|       |
 1254|   721k|    while (current_element != NULL) {
  ------------------
  |  Branch (1254:12): [True: 503k, False: 217k]
  ------------------
 1255|   503k|        if (!print_value(current_element, output_buffer, out_of_memory)) {
  ------------------
  |  Branch (1255:13): [True: 0, False: 503k]
  ------------------
 1256|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1257|      0|        }
 1258|   503k|        update_offset(output_buffer);
 1259|   503k|        if (current_element->next) {
  ------------------
  |  Branch (1259:13): [True: 289k, False: 213k]
  ------------------
 1260|   289k|            length = (size_t)(output_buffer->format ? 2 : 1);
  ------------------
  |  Branch (1260:31): [True: 289k, False: 0]
  ------------------
 1261|   289k|            output_pointer = ensure(output_buffer, length + 1, out_of_memory);
 1262|   289k|            if (output_pointer == NULL) {
  ------------------
  |  Branch (1262:17): [True: 0, False: 289k]
  ------------------
 1263|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1264|      0|            }
 1265|   289k|            *output_pointer++ = ',';
 1266|   289k|            if (output_buffer->format) {
  ------------------
  |  Branch (1266:17): [True: 289k, False: 0]
  ------------------
 1267|   289k|                *output_pointer++ = ' ';
 1268|   289k|            }
 1269|   289k|            *output_pointer = '\0';
 1270|   289k|            output_buffer->offset += length;
 1271|   289k|        }
 1272|   503k|        current_element = current_element->next;
 1273|   503k|    }
 1274|       |
 1275|   217k|    output_pointer = ensure(output_buffer, 2, out_of_memory);
 1276|   217k|    if (output_pointer == NULL) {
  ------------------
  |  Branch (1276:9): [True: 0, False: 217k]
  ------------------
 1277|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1278|      0|    }
 1279|   217k|    *output_pointer++ = ']';
 1280|   217k|    *output_pointer = '\0';
 1281|   217k|    output_buffer->depth--;
 1282|       |
 1283|   217k|    return true;
  ------------------
  |  |   67|   217k|#define true ((cJSON_bool)1)
  ------------------
 1284|   217k|}
cJSON.c:print_object:
 1389|   519k|static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
 1390|   519k|    unsigned char *output_pointer = NULL;
 1391|   519k|    size_t length = 0;
 1392|   519k|    cJSON *current_item = item->child;
 1393|       |
 1394|   519k|    if (output_buffer == NULL) {
  ------------------
  |  Branch (1394:9): [True: 0, False: 519k]
  ------------------
 1395|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1396|      0|    }
 1397|       |
 1398|   519k|    if (output_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   519k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1398:9): [True: 0, False: 519k]
  ------------------
 1399|      0|        return false; /* nesting is too deep */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1400|      0|    }
 1401|       |
 1402|       |    /* Compose the output: */
 1403|   519k|    length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
  ------------------
  |  Branch (1403:23): [True: 519k, False: 0]
  ------------------
 1404|   519k|    output_pointer = ensure(output_buffer, length + 1, out_of_memory);
 1405|   519k|    if (output_pointer == NULL) {
  ------------------
  |  Branch (1405:9): [True: 0, False: 519k]
  ------------------
 1406|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1407|      0|    }
 1408|       |
 1409|   519k|    *output_pointer++ = '{';
 1410|   519k|    output_buffer->depth++;
 1411|   519k|    if (output_buffer->format) {
  ------------------
  |  Branch (1411:9): [True: 519k, False: 0]
  ------------------
 1412|   519k|        *output_pointer++ = '\n';
 1413|   519k|    }
 1414|   519k|    output_buffer->offset += length;
 1415|       |
 1416|  1.31M|    while (current_item) {
  ------------------
  |  Branch (1416:12): [True: 790k, False: 519k]
  ------------------
 1417|   790k|        if (output_buffer->format) {
  ------------------
  |  Branch (1417:13): [True: 790k, False: 0]
  ------------------
 1418|   790k|            size_t i;
 1419|   790k|            output_pointer = ensure(output_buffer, output_buffer->depth, out_of_memory);
 1420|   790k|            if (output_pointer == NULL) {
  ------------------
  |  Branch (1420:17): [True: 0, False: 790k]
  ------------------
 1421|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1422|      0|            }
 1423|   325M|            for (i = 0; i < output_buffer->depth; i++) {
  ------------------
  |  Branch (1423:25): [True: 324M, False: 790k]
  ------------------
 1424|   324M|                *output_pointer++ = '\t';
 1425|   324M|            }
 1426|   790k|            output_buffer->offset += output_buffer->depth;
 1427|   790k|        }
 1428|       |
 1429|       |        /* print key */
 1430|   790k|        if (!print_string_ptr((unsigned char *)current_item->string, output_buffer, out_of_memory)) {
  ------------------
  |  Branch (1430:13): [True: 0, False: 790k]
  ------------------
 1431|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1432|      0|        }
 1433|   790k|        update_offset(output_buffer);
 1434|       |
 1435|   790k|        length = (size_t)(output_buffer->format ? 2 : 1);
  ------------------
  |  Branch (1435:27): [True: 790k, False: 0]
  ------------------
 1436|   790k|        output_pointer = ensure(output_buffer, length, out_of_memory);
 1437|   790k|        if (output_pointer == NULL) {
  ------------------
  |  Branch (1437:13): [True: 0, False: 790k]
  ------------------
 1438|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1439|      0|        }
 1440|   790k|        *output_pointer++ = ':';
 1441|   790k|        if (output_buffer->format) {
  ------------------
  |  Branch (1441:13): [True: 790k, False: 0]
  ------------------
 1442|   790k|            *output_pointer++ = '\t';
 1443|   790k|        }
 1444|   790k|        output_buffer->offset += length;
 1445|       |
 1446|       |        /* print value */
 1447|   790k|        if (!print_value(current_item, output_buffer, out_of_memory)) {
  ------------------
  |  Branch (1447:13): [True: 0, False: 790k]
  ------------------
 1448|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1449|      0|        }
 1450|   790k|        update_offset(output_buffer);
 1451|       |
 1452|       |        /* print comma if not last */
 1453|   790k|        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
  ------------------
  |  Branch (1453:28): [True: 790k, False: 0]
  |  Branch (1453:70): [True: 276k, False: 514k]
  ------------------
 1454|   790k|        output_pointer = ensure(output_buffer, length + 1, out_of_memory);
 1455|   790k|        if (output_pointer == NULL) {
  ------------------
  |  Branch (1455:13): [True: 0, False: 790k]
  ------------------
 1456|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1457|      0|        }
 1458|   790k|        if (current_item->next) {
  ------------------
  |  Branch (1458:13): [True: 276k, False: 514k]
  ------------------
 1459|   276k|            *output_pointer++ = ',';
 1460|   276k|        }
 1461|       |
 1462|   790k|        if (output_buffer->format) {
  ------------------
  |  Branch (1462:13): [True: 790k, False: 0]
  ------------------
 1463|   790k|            *output_pointer++ = '\n';
 1464|   790k|        }
 1465|   790k|        *output_pointer = '\0';
 1466|   790k|        output_buffer->offset += length;
 1467|       |
 1468|   790k|        current_item = current_item->next;
 1469|   790k|    }
 1470|       |
 1471|   519k|    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2, out_of_memory);
  ------------------
  |  Branch (1471:44): [True: 519k, False: 0]
  ------------------
 1472|   519k|    if (output_pointer == NULL) {
  ------------------
  |  Branch (1472:9): [True: 0, False: 519k]
  ------------------
 1473|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1474|      0|    }
 1475|   519k|    if (output_buffer->format) {
  ------------------
  |  Branch (1475:9): [True: 519k, False: 0]
  ------------------
 1476|   519k|        size_t i;
 1477|   211M|        for (i = 0; i < (output_buffer->depth - 1); i++) {
  ------------------
  |  Branch (1477:21): [True: 211M, False: 519k]
  ------------------
 1478|   211M|            *output_pointer++ = '\t';
 1479|   211M|        }
 1480|   519k|    }
 1481|   519k|    *output_pointer++ = '}';
 1482|   519k|    *output_pointer = '\0';
 1483|   519k|    output_buffer->depth--;
 1484|       |
 1485|   519k|    return true;
  ------------------
  |  |   67|   519k|#define true ((cJSON_bool)1)
  ------------------
 1486|   519k|}
cJSON.c:get_object_item:
 1533|  41.4M|static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
 1534|  41.4M|    cJSON *current_element = NULL;
 1535|       |
 1536|  41.4M|    if ((object == NULL) || (name == NULL)) {
  ------------------
  |  Branch (1536:9): [True: 0, False: 41.4M]
  |  Branch (1536:29): [True: 0, False: 41.4M]
  ------------------
 1537|      0|        return NULL;
 1538|      0|    }
 1539|       |
 1540|  41.4M|    current_element = object->child;
 1541|  41.4M|    if (case_sensitive) {
  ------------------
  |  Branch (1541:9): [True: 0, False: 41.4M]
  ------------------
 1542|      0|        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
  ------------------
  |  Branch (1542:16): [True: 0, False: 0]
  |  Branch (1542:45): [True: 0, False: 0]
  |  Branch (1542:82): [True: 0, False: 0]
  ------------------
 1543|      0|            current_element = current_element->next;
 1544|      0|        }
 1545|  41.4M|    } else {
 1546|   231M|        while ((current_element != NULL) &&
  ------------------
  |  Branch (1546:16): [True: 209M, False: 21.8M]
  ------------------
 1547|   209M|               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
  ------------------
  |  Branch (1547:16): [True: 190M, False: 19.5M]
  ------------------
 1548|   190M|            current_element = current_element->next;
 1549|   190M|        }
 1550|  41.4M|    }
 1551|       |
 1552|  41.4M|    if ((current_element == NULL) || (current_element->string == NULL)) {
  ------------------
  |  Branch (1552:9): [True: 21.8M, False: 19.5M]
  |  Branch (1552:38): [True: 0, False: 19.5M]
  ------------------
 1553|  21.8M|        return NULL;
 1554|  21.8M|    }
 1555|       |
 1556|  19.5M|    return current_element;
 1557|  41.4M|}
cJSON.c:case_insensitive_strcmp:
  120|   209M|static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
  121|   209M|    if ((string1 == NULL) || (string2 == NULL)) {
  ------------------
  |  Branch (121:9): [True: 0, False: 209M]
  |  Branch (121:30): [True: 1.18M, False: 208M]
  ------------------
  122|  1.18M|        return 1;
  123|  1.18M|    }
  124|       |
  125|   208M|    if (string1 == string2) {
  ------------------
  |  Branch (125:9): [True: 0, False: 208M]
  ------------------
  126|      0|        return 0;
  127|      0|    }
  128|       |
  129|   444M|    for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
  ------------------
  |  Branch (129:12): [True: 0, False: 0]
  |  Branch (129:12): [True: 0, False: 0]
  |  Branch (129:12): [Folded, False: 444M]
  |  Branch (129:12): [True: 255M, False: 189M]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [Folded, False: 444M]
  ------------------
  130|   255M|        if (*string1 == '\0') {
  ------------------
  |  Branch (130:13): [True: 19.5M, False: 235M]
  ------------------
  131|  19.5M|            return 0;
  132|  19.5M|        }
  133|   255M|    }
  134|       |
  135|   189M|    return tolower(*string1) - tolower(*string2);
  ------------------
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [Folded, False: 189M]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [Folded, False: 189M]
  ------------------
  136|   208M|}
cJSON.c:compare_double:
  366|  55.2k|static cJSON_bool compare_double(double a, double b) {
  367|  55.2k|    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
  ------------------
  |  Branch (367:21): [True: 2.06k, False: 53.1k]
  ------------------
  368|       |    return (fabs(a - b) <= maxVal * DBL_EPSILON);
  369|  55.2k|}

util_SubmitDebugUtilsMessageEXT:
   78|  10.4M|                                         const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
   79|  10.4M|    VkBool32 bail = false;
   80|       |
   81|  10.4M|    if (NULL != pCallbackData) {
  ------------------
  |  Branch (81:9): [True: 10.4M, False: 0]
  ------------------
   82|       |        // The messenger/report chain is guarded by loader_lock everywhere it is modified (see the create/destroy
   83|       |        // terminators). loader_lock is recursive, so taking it here is safe even when a caller already holds it.
   84|  10.4M|        loader_platform_thread_lock_mutex(&loader_lock);
   85|  10.4M|        VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
   86|  10.4M|        VkDebugReportObjectTypeEXT object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
   87|  10.4M|        VkDebugReportFlagsEXT object_flags = 0;
   88|  10.4M|        uint64_t object_handle = 0;
   89|       |
   90|  10.4M|        debug_utils_AnnotFlagsToReportFlags(messageSeverity, messageTypes, &object_flags);
   91|  10.4M|        if (0 < pCallbackData->objectCount) {
  ------------------
  |  Branch (91:13): [True: 10.4M, False: 0]
  ------------------
   92|  10.4M|            debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
   93|  10.4M|        }
   94|  10.4M|        while (pTrav) {
  ------------------
  |  Branch (94:16): [True: 0, False: 10.4M]
  ------------------
   95|      0|            if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
  ------------------
  |  Branch (95:17): [True: 0, False: 0]
  |  Branch (95:40): [True: 0, False: 0]
  ------------------
   96|      0|                (pTrav->messenger.messageType & messageTypes)) {
  ------------------
  |  Branch (96:17): [True: 0, False: 0]
  ------------------
   97|      0|                if (pTrav->messenger.pfnUserCallback(messageSeverity, messageTypes, pCallbackData, pTrav->pUserData)) {
  ------------------
  |  Branch (97:21): [True: 0, False: 0]
  ------------------
   98|      0|                    bail = true;
   99|      0|                }
  100|      0|            }
  101|      0|            if (!pTrav->is_messenger && pTrav->report.msgFlags & object_flags) {
  ------------------
  |  Branch (101:17): [True: 0, False: 0]
  |  Branch (101:41): [True: 0, False: 0]
  ------------------
  102|      0|                if (pTrav->report.pfnMsgCallback(object_flags, object_type, object_handle, 0, pCallbackData->messageIdNumber,
  ------------------
  |  Branch (102:21): [True: 0, False: 0]
  ------------------
  103|      0|                                                 pCallbackData->pMessageIdName, pCallbackData->pMessage, pTrav->pUserData)) {
  104|      0|                    bail = true;
  105|      0|                }
  106|      0|            }
  107|      0|            pTrav = pTrav->pNext;
  108|      0|        }
  109|  10.4M|        loader_platform_thread_unlock_mutex(&loader_lock);
  110|  10.4M|    }
  111|       |
  112|  10.4M|    return bail;
  113|  10.4M|}
util_CreateDebugUtilsMessengers:
  134|  8.37k|                                         const VkAllocationCallbacks *pAllocator) {
  135|  8.37k|    const void *pNext = pChain;
  136|  8.37k|    while (pNext) {
  ------------------
  |  Branch (136:12): [True: 0, False: 8.37k]
  ------------------
  137|      0|        VkBaseInStructure in_structure = {0};
  138|      0|        memcpy(&in_structure, pNext, sizeof(VkBaseInStructure));
  139|      0|        if (in_structure.sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
  ------------------
  |  Branch (139:13): [True: 0, False: 0]
  ------------------
  140|       |            // Assign a unique handle to each messenger (just use the address of the VkDebugUtilsMessengerCreateInfoEXT)
  141|       |            // This is only being used this way due to it being for an 'anonymous' callback during instance creation
  142|       |            // NOLINTNEXTLINE(performance-no-int-to-ptr) - non-dispatchable handle; round-trip via uintptr_t is required
  143|      0|            VkDebugUtilsMessengerEXT messenger_handle = (VkDebugUtilsMessengerEXT)(uintptr_t)pNext;
  144|      0|            VkResult ret = util_CreateDebugUtilsMessenger(inst, (const VkDebugUtilsMessengerCreateInfoEXT *)pNext, pAllocator,
  145|      0|                                                          messenger_handle);
  146|      0|            if (ret != VK_SUCCESS) {
  ------------------
  |  Branch (146:17): [True: 0, False: 0]
  ------------------
  147|      0|                return ret;
  148|      0|            }
  149|      0|        }
  150|      0|        pNext = in_structure.pNext;
  151|      0|    }
  152|  8.37k|    return VK_SUCCESS;
  153|  8.37k|}
util_CreateDebugReportCallbacks:
  417|  8.37k|                                         const VkAllocationCallbacks *pAllocator) {
  418|  8.37k|    const void *pNext = pChain;
  419|  8.37k|    while (pNext) {
  ------------------
  |  Branch (419:12): [True: 0, False: 8.37k]
  ------------------
  420|      0|        VkBaseInStructure in_structure = {0};
  421|      0|        memcpy(&in_structure, pNext, sizeof(VkBaseInStructure));
  422|      0|        if (in_structure.sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
  ------------------
  |  Branch (422:13): [True: 0, False: 0]
  ------------------
  423|       |            // Assign a unique handle to each callback (just use the address of the VkDebugReportCallbackCreateInfoEXT):
  424|       |            // This is only being used this way due to it being for an 'anonymous' callback during instance creation
  425|       |            // NOLINTNEXTLINE(performance-no-int-to-ptr) - non-dispatchable handle; round-trip via uintptr_t is required
  426|      0|            VkDebugReportCallbackEXT report_handle = (VkDebugReportCallbackEXT)(uintptr_t)pNext;
  427|      0|            VkResult ret =
  428|      0|                util_CreateDebugReportCallback(inst, (const VkDebugReportCallbackCreateInfoEXT *)pNext, pAllocator, report_handle);
  429|      0|            if (ret != VK_SUCCESS) {
  ------------------
  |  Branch (429:17): [True: 0, False: 0]
  ------------------
  430|      0|                return ret;
  431|      0|            }
  432|      0|        }
  433|      0|        pNext = in_structure.pNext;
  434|      0|    }
  435|  8.37k|    return VK_SUCCESS;
  436|  8.37k|}
destroy_debug_callbacks_chain:
  619|  8.37k|void destroy_debug_callbacks_chain(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) {
  620|  8.37k|    VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
  621|  8.37k|    VkLayerDbgFunctionNode *pNext = NULL;
  622|  8.37k|    while (pTrav) {
  ------------------
  |  Branch (622:12): [True: 0, False: 8.37k]
  ------------------
  623|      0|        pNext = pTrav->pNext;
  624|      0|        loader_free_with_instance_fallback(pAllocator, inst, pTrav);
  625|      0|        pTrav = pNext;
  626|      0|    }
  627|       |    inst->current_dbg_function_head = NULL;
  628|  8.37k|}
debug_utils_AnnotFlagsToReportFlags:
  704|  10.4M|                                         VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
  705|  10.4M|    if (NULL == dr_flags) {
  ------------------
  |  Branch (705:9): [True: 0, False: 10.4M]
  ------------------
  706|      0|        return false;
  707|      0|    }
  708|       |
  709|  10.4M|    *dr_flags = 0;
  710|       |
  711|  10.4M|    if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
  ------------------
  |  Branch (711:9): [True: 60.3k, False: 10.3M]
  ------------------
  712|  60.3k|        *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
  713|  10.3M|    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
  ------------------
  |  Branch (713:16): [True: 8.65M, False: 1.72M]
  ------------------
  714|  8.65M|        if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
  ------------------
  |  Branch (714:13): [True: 0, False: 8.65M]
  ------------------
  715|      0|            *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
  716|  8.65M|        } else {
  717|  8.65M|            *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
  718|  8.65M|        }
  719|  8.65M|    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
  ------------------
  |  Branch (719:16): [True: 1.18M, False: 531k]
  ------------------
  720|  1.18M|        *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
  721|  1.18M|    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
  ------------------
  |  Branch (721:16): [True: 531k, False: 0]
  ------------------
  722|   531k|        *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
  723|   531k|    }
  724|       |
  725|       |    return true;
  726|  10.4M|}
debug_utils_AnnotObjectToDebugReportObject:
  743|  10.4M|                                                VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle) {
  744|  10.4M|    if (NULL == da_object_name_info || NULL == dr_object_type || NULL == dr_object_handle) {
  ------------------
  |  Branch (744:9): [True: 0, False: 10.4M]
  |  Branch (744:40): [True: 0, False: 10.4M]
  |  Branch (744:66): [True: 0, False: 10.4M]
  ------------------
  745|      0|        return false;
  746|      0|    }
  747|  10.4M|    *dr_object_type = convertCoreObjectToDebugReportObject(da_object_name_info->objectType);
  748|  10.4M|    *dr_object_handle = da_object_name_info->objectHandle;
  749|       |    return true;
  750|  10.4M|}

debug_utils.c:convertCoreObjectToDebugReportObject:
  391|  10.4M|static inline VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj){
  392|  10.4M|    if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {
  ------------------
  |  Branch (392:9): [True: 0, False: 10.4M]
  ------------------
  393|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
  394|  10.4M|    } else if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {
  ------------------
  |  Branch (394:16): [True: 0, False: 10.4M]
  ------------------
  395|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
  396|  10.4M|    } else if (core_report_obj == VK_OBJECT_TYPE_INSTANCE) {
  ------------------
  |  Branch (396:16): [True: 10.4M, False: 0]
  ------------------
  397|  10.4M|        return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
  398|  10.4M|    } else if (core_report_obj == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {
  ------------------
  |  Branch (398:16): [True: 0, False: 0]
  ------------------
  399|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT;
  400|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DEVICE) {
  ------------------
  |  Branch (400:16): [True: 0, False: 0]
  ------------------
  401|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT;
  402|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_QUEUE) {
  ------------------
  |  Branch (402:16): [True: 0, False: 0]
  ------------------
  403|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT;
  404|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_SEMAPHORE) {
  ------------------
  |  Branch (404:16): [True: 0, False: 0]
  ------------------
  405|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT;
  406|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_COMMAND_BUFFER) {
  ------------------
  |  Branch (406:16): [True: 0, False: 0]
  ------------------
  407|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT;
  408|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_FENCE) {
  ------------------
  |  Branch (408:16): [True: 0, False: 0]
  ------------------
  409|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT;
  410|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DEVICE_MEMORY) {
  ------------------
  |  Branch (410:16): [True: 0, False: 0]
  ------------------
  411|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT;
  412|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_BUFFER) {
  ------------------
  |  Branch (412:16): [True: 0, False: 0]
  ------------------
  413|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;
  414|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_IMAGE) {
  ------------------
  |  Branch (414:16): [True: 0, False: 0]
  ------------------
  415|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT;
  416|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_EVENT) {
  ------------------
  |  Branch (416:16): [True: 0, False: 0]
  ------------------
  417|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT;
  418|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_QUERY_POOL) {
  ------------------
  |  Branch (418:16): [True: 0, False: 0]
  ------------------
  419|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT;
  420|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_BUFFER_VIEW) {
  ------------------
  |  Branch (420:16): [True: 0, False: 0]
  ------------------
  421|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT;
  422|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_IMAGE_VIEW) {
  ------------------
  |  Branch (422:16): [True: 0, False: 0]
  ------------------
  423|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT;
  424|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_SHADER_MODULE) {
  ------------------
  |  Branch (424:16): [True: 0, False: 0]
  ------------------
  425|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT;
  426|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_PIPELINE_CACHE) {
  ------------------
  |  Branch (426:16): [True: 0, False: 0]
  ------------------
  427|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT;
  428|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_PIPELINE_LAYOUT) {
  ------------------
  |  Branch (428:16): [True: 0, False: 0]
  ------------------
  429|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT;
  430|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_RENDER_PASS) {
  ------------------
  |  Branch (430:16): [True: 0, False: 0]
  ------------------
  431|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT;
  432|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_PIPELINE) {
  ------------------
  |  Branch (432:16): [True: 0, False: 0]
  ------------------
  433|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT;
  434|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT) {
  ------------------
  |  Branch (434:16): [True: 0, False: 0]
  ------------------
  435|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT;
  436|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_SAMPLER) {
  ------------------
  |  Branch (436:16): [True: 0, False: 0]
  ------------------
  437|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT;
  438|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_POOL) {
  ------------------
  |  Branch (438:16): [True: 0, False: 0]
  ------------------
  439|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT;
  440|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_SET) {
  ------------------
  |  Branch (440:16): [True: 0, False: 0]
  ------------------
  441|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT;
  442|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_FRAMEBUFFER) {
  ------------------
  |  Branch (442:16): [True: 0, False: 0]
  ------------------
  443|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT;
  444|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_COMMAND_POOL) {
  ------------------
  |  Branch (444:16): [True: 0, False: 0]
  ------------------
  445|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT;
  446|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE) {
  ------------------
  |  Branch (446:16): [True: 0, False: 0]
  ------------------
  447|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT;
  448|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION) {
  ------------------
  |  Branch (448:16): [True: 0, False: 0]
  ------------------
  449|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT;
  450|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_SURFACE_KHR) {
  ------------------
  |  Branch (450:16): [True: 0, False: 0]
  ------------------
  451|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT;
  452|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {
  ------------------
  |  Branch (452:16): [True: 0, False: 0]
  ------------------
  453|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT;
  454|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DISPLAY_KHR) {
  ------------------
  |  Branch (454:16): [True: 0, False: 0]
  ------------------
  455|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT;
  456|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DISPLAY_MODE_KHR) {
  ------------------
  |  Branch (456:16): [True: 0, False: 0]
  ------------------
  457|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT;
  458|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT) {
  ------------------
  |  Branch (458:16): [True: 0, False: 0]
  ------------------
  459|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT;
  460|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_CU_MODULE_NVX) {
  ------------------
  |  Branch (460:16): [True: 0, False: 0]
  ------------------
  461|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT;
  462|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_CU_FUNCTION_NVX) {
  ------------------
  |  Branch (462:16): [True: 0, False: 0]
  ------------------
  463|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT;
  464|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR) {
  ------------------
  |  Branch (464:16): [True: 0, False: 0]
  ------------------
  465|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT;
  466|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_VALIDATION_CACHE_EXT) {
  ------------------
  |  Branch (466:16): [True: 0, False: 0]
  ------------------
  467|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT;
  468|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV) {
  ------------------
  |  Branch (468:16): [True: 0, False: 0]
  ------------------
  469|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT;
  470|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_CUDA_MODULE_NV) {
  ------------------
  |  Branch (470:16): [True: 0, False: 0]
  ------------------
  471|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_MODULE_NV_EXT;
  472|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_CUDA_FUNCTION_NV) {
  ------------------
  |  Branch (472:16): [True: 0, False: 0]
  ------------------
  473|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_FUNCTION_NV_EXT;
  474|      0|    } else if (core_report_obj == VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA) {
  ------------------
  |  Branch (474:16): [True: 0, False: 0]
  ------------------
  475|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT;
  476|      0|    }
  477|      0|    return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
  478|  10.4M|}

loader_make_version:
  113|   551k|loader_api_version loader_make_version(uint32_t version) {
  114|   551k|    loader_api_version out_version;
  115|   551k|    out_version.major = VK_API_VERSION_MAJOR(version);
  116|       |    out_version.minor = VK_API_VERSION_MINOR(version);
  117|   551k|    out_version.patch = 0;
  118|   551k|    return out_version;
  119|   551k|}
loader_make_full_version:
  122|  70.6k|loader_api_version loader_make_full_version(uint32_t version) {
  123|  70.6k|    loader_api_version out_version;
  124|  70.6k|    out_version.major = VK_API_VERSION_MAJOR(version);
  125|  70.6k|    out_version.minor = VK_API_VERSION_MINOR(version);
  126|       |    out_version.patch = VK_API_VERSION_PATCH(version);
  127|  70.6k|    return out_version;
  128|  70.6k|}
loader_combine_version:
  131|   682k|loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32_t patch) {
  132|   682k|    loader_api_version out_version;
  133|   682k|    out_version.major = (uint16_t)major;
  134|   682k|    out_version.minor = (uint16_t)minor;
  135|   682k|    out_version.patch = (uint16_t)patch;
  136|   682k|    return out_version;
  137|   682k|}
loader_check_version_meets_required:
  140|   812k|bool loader_check_version_meets_required(loader_api_version required, loader_api_version version) {
  141|       |    // major version is satisfied
  142|   812k|    return (version.major > required.major) ||
  ------------------
  |  Branch (142:12): [True: 374k, False: 437k]
  ------------------
  143|       |           // major version is equal, minor version is patch version is greater to minimum minor
  144|   437k|           (version.major == required.major && version.minor > required.minor) ||
  ------------------
  |  Branch (144:13): [True: 123k, False: 314k]
  |  Branch (144:48): [True: 62.0k, False: 61.6k]
  ------------------
  145|       |           // major and minor version are equal, patch version is greater or equal to minimum patch
  146|   375k|           (version.major == required.major && version.minor == required.minor && version.patch >= required.patch);
  ------------------
  |  Branch (146:13): [True: 61.6k, False: 314k]
  |  Branch (146:48): [True: 46.0k, False: 15.6k]
  |  Branch (146:83): [True: 28.7k, False: 17.2k]
  ------------------
  147|   812k|}
loader_opendir:
  172|   127k|DIR *loader_opendir(const struct loader_instance *instance, const char *name) {
  173|       |#if defined(_WIN32)
  174|       |    return opendir(instance ? &instance->alloc_callbacks : NULL, name);
  175|       |#elif COMMON_UNIX_PLATFORMS
  176|       |    (void)instance;
  177|   127k|    return opendir(name);
  178|       |#else
  179|       |#warning dirent.h - opendir not available on this platform
  180|       |#endif  // _WIN32
  181|   127k|}
loader_closedir:
  182|  10.0k|int loader_closedir(const struct loader_instance *instance, DIR *dir) {
  183|       |#if defined(_WIN32)
  184|       |    return closedir(instance ? &instance->alloc_callbacks : NULL, dir);
  185|       |#elif COMMON_UNIX_PLATFORMS
  186|       |    (void)instance;
  187|  10.0k|    return closedir(dir);
  188|       |#else
  189|       |#warning dirent.h - closedir not available on this platform
  190|       |#endif  // _WIN32
  191|  10.0k|}
is_json:
  193|   523k|bool is_json(const char *path, size_t len) {
  194|   523k|    if (len < 5) {
  ------------------
  |  Branch (194:9): [True: 125k, False: 397k]
  ------------------
  195|   125k|        return false;
  196|   125k|    }
  197|   397k|    return !strncmp(path + len - 5, ".json", 5);
  198|   523k|}
loader_handle_load_library_error:
  202|     33|                                      enum loader_layer_library_status *lib_status) {
  203|     33|    const char *error_message = loader_platform_open_library_error(filename);
  204|       |    // If the error is due to incompatible architecture (eg 32 bit vs 64 bit), report it with INFO level
  205|       |    // Discussed in Github issue 262 & 644
  206|       |    // "wrong ELF class" is a linux error, " with error 193" is a windows error
  207|     33|    VkFlags err_flag = VULKAN_LOADER_ERROR_BIT;
  208|     33|    if (strstr(error_message, "wrong ELF class:") != NULL || strstr(error_message, " with error 193") != NULL) {
  ------------------
  |  Branch (208:9): [True: 1, False: 32]
  |  Branch (208:62): [True: 1, False: 31]
  ------------------
  209|      2|        err_flag = VULKAN_LOADER_INFO_BIT;
  210|      2|        if (NULL != lib_status) {
  ------------------
  |  Branch (210:13): [True: 2, False: 0]
  ------------------
  211|      2|            *lib_status = LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE;
  212|      2|        }
  213|      2|    }
  214|       |    // Check if the error is due to lack of memory
  215|       |    // "with error 8" is the windows error code for OOM cases, aka ERROR_NOT_ENOUGH_MEMORY
  216|       |    // Linux doesn't have such a nice error message - only if there are reported issues should this be called
  217|     31|    else if (strstr(error_message, " with error 8") != NULL) {
  ------------------
  |  Branch (217:14): [True: 1, False: 30]
  ------------------
  218|      1|        if (NULL != lib_status) {
  ------------------
  |  Branch (218:13): [True: 1, False: 0]
  ------------------
  219|      1|            *lib_status = LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY;
  220|      1|        }
  221|     30|    } else if (NULL != lib_status) {
  ------------------
  |  Branch (221:16): [True: 30, False: 0]
  ------------------
  222|     30|        *lib_status = LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD;
  223|     30|    }
  224|     33|    loader_log(inst, err_flag, 0, "%s", error_message);
  225|     33|}
loader_free_layer_properties:
  248|  5.27M|void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties) {
  249|  5.27M|    loader_instance_heap_free(inst, layer_properties->manifest_file_name);
  250|  5.27M|    loader_instance_heap_free(inst, layer_properties->lib_name);
  251|  5.27M|    loader_instance_heap_free(inst, layer_properties->functions.str_gipa);
  252|  5.27M|    loader_instance_heap_free(inst, layer_properties->functions.str_gdpa);
  253|  5.27M|    loader_instance_heap_free(inst, layer_properties->functions.str_negotiate_interface);
  254|  5.27M|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->instance_extension_list);
  255|  5.27M|    if (layer_properties->device_extension_list.capacity > 0 && NULL != layer_properties->device_extension_list.list) {
  ------------------
  |  Branch (255:9): [True: 6.31k, False: 5.26M]
  |  Branch (255:65): [True: 6.31k, False: 0]
  ------------------
  256|  47.2k|        for (uint32_t i = 0; i < layer_properties->device_extension_list.count; i++) {
  ------------------
  |  Branch (256:30): [True: 40.8k, False: 6.31k]
  ------------------
  257|  40.8k|            free_string_list(inst, &layer_properties->device_extension_list.list[i].entrypoints);
  258|  40.8k|        }
  259|  6.31k|    }
  260|  5.27M|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->device_extension_list);
  261|  5.27M|    loader_instance_heap_free(inst, layer_properties->disable_env_var.name);
  262|  5.27M|    loader_instance_heap_free(inst, layer_properties->disable_env_var.value);
  263|  5.27M|    loader_instance_heap_free(inst, layer_properties->enable_env_var.name);
  264|  5.27M|    loader_instance_heap_free(inst, layer_properties->enable_env_var.value);
  265|  5.27M|    free_string_list(inst, &layer_properties->component_layer_names);
  266|  5.27M|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_extension_properties);
  267|  5.27M|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_layer_properties);
  268|  5.27M|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_version);
  269|  5.27M|    free_string_list(inst, &layer_properties->override_paths);
  270|  5.27M|    free_string_list(inst, &layer_properties->blacklist_layer_names);
  271|  5.27M|    free_string_list(inst, &layer_properties->app_key_paths);
  272|       |
  273|       |    // Make sure to clear out the removed layer, in case new layers are added in the previous location
  274|  5.27M|    memset(layer_properties, 0, sizeof(struct loader_layer_properties));
  275|  5.27M|}
is_string_in_string_list:
  288|   355k|bool is_string_in_string_list(struct loader_string_list *string_list, const char *str) {
  289|       |    // Remove duplicate paths, or it would result in duplicate extensions, duplicate devices, etc.
  290|  63.1M|    for (size_t i = 0; i < string_list->count; i++) {
  ------------------
  |  Branch (290:24): [True: 62.8M, False: 260k]
  ------------------
  291|  62.8M|        if (strcmp(string_list->list[i], str) == 0) {
  ------------------
  |  Branch (291:13): [True: 94.3k, False: 62.7M]
  ------------------
  292|  94.3k|            return true;
  293|  94.3k|        }
  294|  62.8M|    }
  295|   260k|    return false;
  296|   355k|}
loader_copy_to_new_str:
  298|  5.22M|VkResult loader_copy_to_new_str(const struct loader_instance *inst, const char *source_str, char **dest_str) {
  299|  5.22M|    assert(source_str && dest_str);
  300|  5.22M|    size_t str_len = strlen(source_str) + 1;
  301|  5.22M|    *dest_str = loader_instance_heap_calloc(inst, str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  302|  5.22M|    if (NULL == *dest_str) return VK_ERROR_OUT_OF_HOST_MEMORY;
  ------------------
  |  Branch (302:9): [True: 0, False: 5.22M]
  ------------------
  303|  5.22M|    loader_strncpy(*dest_str, str_len, source_str, str_len);
  304|  5.22M|    (*dest_str)[str_len - 1] = 0;
  305|  5.22M|    return VK_SUCCESS;
  306|  5.22M|}
create_string_list:
  308|   195k|VkResult create_string_list(const struct loader_instance *inst, uint32_t allocated_count, struct loader_string_list *string_list) {
  309|   195k|    assert(string_list);
  310|   195k|    string_list->list =
  311|   195k|        (char **)loader_instance_heap_calloc(inst, sizeof(char *) * allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  312|   195k|    if (NULL == string_list->list) {
  ------------------
  |  Branch (312:9): [True: 0, False: 195k]
  ------------------
  313|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  314|      0|    }
  315|   195k|    string_list->allocated_count = allocated_count;
  316|   195k|    string_list->count = 0;
  317|   195k|    return VK_SUCCESS;
  318|   195k|}
increase_str_capacity_by_at_least_one:
  320|  1.25M|VkResult increase_str_capacity_by_at_least_one(const struct loader_instance *inst, struct loader_string_list *string_list) {
  321|  1.25M|    assert(string_list);
  322|  1.25M|    if (string_list->allocated_count == 0) {
  ------------------
  |  Branch (322:9): [True: 27.4k, False: 1.23M]
  ------------------
  323|  27.4k|        string_list->allocated_count = 32;
  324|  27.4k|        string_list->list = (char **)loader_instance_heap_calloc(inst, sizeof(char *) * string_list->allocated_count,
  325|  27.4k|                                                                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  326|  27.4k|        if (NULL == string_list->list) {
  ------------------
  |  Branch (326:13): [True: 0, False: 27.4k]
  ------------------
  327|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  328|      0|        }
  329|  1.23M|    } else if (string_list->count + 1 > string_list->allocated_count) {
  ------------------
  |  Branch (329:16): [True: 1.13k, False: 1.22M]
  ------------------
  330|  1.13k|        uint32_t new_allocated_count = string_list->allocated_count * 2;
  331|  1.13k|        void *new_ptr = loader_instance_heap_realloc(inst, (void *)string_list->list, sizeof(char *) * string_list->allocated_count,
  332|  1.13k|                                                     sizeof(char *) * new_allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  333|  1.13k|        if (NULL == new_ptr) {
  ------------------
  |  Branch (333:13): [True: 0, False: 1.13k]
  ------------------
  334|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  335|      0|        }
  336|  1.13k|        string_list->list = (char **)new_ptr;
  337|  1.13k|        string_list->allocated_count *= 2;
  338|  1.13k|    }
  339|  1.25M|    return VK_SUCCESS;
  340|  1.25M|}
append_str_to_string_list:
  342|  1.25M|VkResult append_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, char *str) {
  343|  1.25M|    assert(string_list && str);
  344|  1.25M|    VkResult res = increase_str_capacity_by_at_least_one(inst, string_list);
  345|  1.25M|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (345:9): [True: 0, False: 1.25M]
  ------------------
  346|      0|        loader_instance_heap_free(inst, str);  // Must clean up in case of failure
  347|      0|        return res;
  348|      0|    }
  349|  1.25M|    string_list->list[string_list->count++] = str;
  350|  1.25M|    return VK_SUCCESS;
  351|  1.25M|}
append_str_to_string_list_if_unique:
  354|   248k|                                             char *str) {
  355|   248k|    if (is_string_in_string_list(string_list, str)) {
  ------------------
  |  Branch (355:9): [True: 94.3k, False: 154k]
  ------------------
  356|       |        // Since this string is a duplicate and this function takes ownership, we need to free it.
  357|  94.3k|        loader_instance_heap_free(inst, str);
  358|  94.3k|        return VK_SUCCESS;
  359|  94.3k|    }
  360|   154k|    return append_str_to_string_list(inst, string_list, str);
  361|   248k|}
copy_str_to_string_list:
  379|   106k|                                 size_t str_len) {
  380|   106k|    assert(string_list && str);
  381|   106k|    char *new_str = loader_instance_heap_calloc(inst, str_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  382|   106k|    if (NULL == new_str) {
  ------------------
  |  Branch (382:9): [True: 0, False: 106k]
  ------------------
  383|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  384|      0|    }
  385|   106k|    loader_strncpy(new_str, str_len + 1, str, str_len);
  386|   106k|    new_str[str_len] = '\0';
  387|   106k|    return append_str_to_string_list(inst, string_list, new_str);
  388|   106k|}
copy_str_to_string_list_if_unique:
  391|   106k|                                           const char *str, size_t str_len) {
  392|   106k|    if (is_string_in_string_list(string_list, str)) {
  ------------------
  |  Branch (392:9): [True: 4, False: 106k]
  ------------------
  393|      4|        return VK_SUCCESS;
  394|      4|    }
  395|   106k|    return copy_str_to_string_list(inst, string_list, str, str_len);
  396|   106k|}
free_string_list:
  423|  21.2M|void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list) {
  424|  21.2M|    assert(string_list);
  425|  21.2M|    if (string_list->list) {
  ------------------
  |  Branch (425:9): [True: 222k, False: 20.9M]
  ------------------
  426|  1.48M|        for (uint32_t i = 0; i < string_list->count; i++) {
  ------------------
  |  Branch (426:30): [True: 1.25M, False: 222k]
  ------------------
  427|  1.25M|            loader_instance_heap_free(inst, string_list->list[i]);
  428|       |            string_list->list[i] = NULL;
  429|  1.25M|        }
  430|   222k|        loader_instance_heap_free(inst, (void *)string_list->list);
  431|   222k|    }
  432|  21.2M|    memset(string_list, 0, sizeof(struct loader_string_list));
  433|  21.2M|}
loader_parse_version_string:
  710|  3.06M|uint32_t loader_parse_version_string(char *vers_str) {
  711|  3.06M|    uint32_t variant = 0;
  712|  3.06M|    uint32_t major = 0;
  713|  3.06M|    uint32_t minor = 0;
  714|  3.06M|    uint32_t patch = 0;
  715|  3.06M|    char *vers_tok;
  716|  3.06M|    char *context = NULL;
  717|  3.06M|    if (!vers_str) {
  ------------------
  |  Branch (717:9): [True: 0, False: 3.06M]
  ------------------
  718|      0|        return 0;
  719|      0|    }
  720|       |
  721|  3.06M|    vers_tok = thread_safe_strtok(vers_str, ".\"\n\r", &context);
  722|  3.06M|    if (NULL != vers_tok) {
  ------------------
  |  Branch (722:9): [True: 557k, False: 2.50M]
  ------------------
  723|   557k|        major = (uint16_t)strtoul(vers_tok, NULL, 10);
  724|   557k|        vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  725|   557k|        if (NULL != vers_tok) {
  ------------------
  |  Branch (725:13): [True: 177k, False: 380k]
  ------------------
  726|   177k|            minor = (uint16_t)strtoul(vers_tok, NULL, 10);
  727|   177k|            vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  728|   177k|            if (NULL != vers_tok) {
  ------------------
  |  Branch (728:17): [True: 143k, False: 33.2k]
  ------------------
  729|   143k|                patch = (uint16_t)strtoul(vers_tok, NULL, 10);
  730|   143k|                vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  731|       |                // check that we are using a 4 part version string
  732|   143k|                if (NULL != vers_tok) {
  ------------------
  |  Branch (732:21): [True: 519, False: 143k]
  ------------------
  733|       |                    // if we are, move the values over into the correct place
  734|    519|                    variant = major;
  735|    519|                    major = minor;
  736|    519|                    minor = patch;
  737|    519|                    patch = (uint16_t)strtoul(vers_tok, NULL, 10);
  738|    519|                }
  739|   143k|            }
  740|   177k|        }
  741|   557k|    }
  742|       |
  743|       |    return VK_MAKE_API_VERSION(variant, major, minor, patch);
  744|  3.06M|}
compare_vk_extension_properties:
  746|  7.61M|TEST_FUNCTION_EXPORT bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) {
  747|  7.61M|    return strncmp(op1->extensionName, op2->extensionName, VK_MAX_EXTENSION_NAME_SIZE) == 0 ? true : false;
  ------------------
  |  Branch (747:12): [True: 120k, False: 7.49M]
  ------------------
  748|  7.61M|}
has_vk_extension_property:
  760|   340k|bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) {
  761|  6.76M|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (761:26): [True: 6.53M, False: 232k]
  ------------------
  762|  6.53M|        if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true;
  ------------------
  |  Branch (762:13): [True: 108k, False: 6.42M]
  ------------------
  763|  6.53M|    }
  764|   232k|    return false;
  765|   340k|}
has_vk_dev_ext_property:
  768|  77.0k|bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) {
  769|  1.14M|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (769:26): [True: 1.07M, False: 64.9k]
  ------------------
  770|  1.07M|        if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true;
  ------------------
  |  Branch (770:13): [True: 12.1k, False: 1.06M]
  ------------------
  771|  1.07M|    }
  772|  64.9k|    return false;
  773|  77.0k|}
loader_append_layer_property:
  776|  2.56M|                                      struct loader_layer_properties *layer_property) {
  777|  2.56M|    VkResult res = VK_SUCCESS;
  778|  2.56M|    if (layer_list->capacity == 0) {
  ------------------
  |  Branch (778:9): [True: 5.93k, False: 2.55M]
  ------------------
  779|  5.93k|        res = loader_init_generic_list(inst, (struct loader_generic_list *)layer_list, sizeof(struct loader_layer_properties));
  780|  5.93k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (780:13): [True: 0, False: 5.93k]
  ------------------
  781|      0|            goto out;
  782|      0|        }
  783|  5.93k|    }
  784|       |
  785|       |    // Ensure enough room to add an entry
  786|  2.56M|    if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) {
  ------------------
  |  Branch (786:9): [True: 2.75k, False: 2.56M]
  ------------------
  787|  2.75k|        void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2,
  788|  2.75k|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  789|  2.75k|        if (NULL == new_ptr) {
  ------------------
  |  Branch (789:13): [True: 0, False: 2.75k]
  ------------------
  790|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_append_layer_property: realloc failed for layer list");
  791|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  792|      0|            goto out;
  793|      0|        }
  794|  2.75k|        layer_list->list = new_ptr;
  795|  2.75k|        layer_list->capacity *= 2;
  796|  2.75k|    }
  797|  2.56M|    memcpy(&layer_list->list[layer_list->count], layer_property, sizeof(struct loader_layer_properties));
  798|  2.56M|    layer_list->count++;
  799|  2.56M|    memset(layer_property, 0, sizeof(struct loader_layer_properties));
  800|  2.56M|out:
  801|  2.56M|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (801:9): [True: 0, False: 2.56M]
  ------------------
  802|      0|        loader_free_layer_properties(inst, layer_property);
  803|      0|    }
  804|  2.56M|    return res;
  805|  2.56M|}
loader_find_layer_property:
  808|   191k|struct loader_layer_properties *loader_find_layer_property(const char *name, const struct loader_layer_list *layer_list) {
  809|   867M|    for (uint32_t i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (809:26): [True: 867M, False: 46.5k]
  ------------------
  810|   867M|        const VkLayerProperties *item = &layer_list->list[i].info;
  811|   867M|        if (strcmp(name, item->layerName) == 0) return &layer_list->list[i];
  ------------------
  |  Branch (811:13): [True: 144k, False: 867M]
  ------------------
  812|   867M|    }
  813|  46.5k|    return NULL;
  814|   191k|}
loader_find_layer_name_in_blacklist:
  837|  2.14M|bool loader_find_layer_name_in_blacklist(const char *layer_name, struct loader_layer_properties *meta_layer_props) {
  838|  2.14M|    for (uint32_t black_layer = 0; black_layer < meta_layer_props->blacklist_layer_names.count; ++black_layer) {
  ------------------
  |  Branch (838:36): [True: 0, False: 2.14M]
  ------------------
  839|      0|        if (!strcmp(meta_layer_props->blacklist_layer_names.list[black_layer], layer_name)) {
  ------------------
  |  Branch (839:13): [True: 0, False: 0]
  ------------------
  840|      0|            return true;
  841|      0|        }
  842|      0|    }
  843|  2.14M|    return false;
  844|  2.14M|}
loader_delete_layer_list_and_properties:
  848|  25.1k|                                                                  struct loader_layer_list *layer_list) {
  849|  25.1k|    uint32_t i;
  850|  25.1k|    if (!layer_list) return;
  ------------------
  |  Branch (850:9): [True: 0, False: 25.1k]
  ------------------
  851|       |
  852|  1.35M|    for (i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (852:17): [True: 1.33M, False: 25.1k]
  ------------------
  853|  1.33M|        if (layer_list->list[i].lib_handle) {
  ------------------
  |  Branch (853:13): [True: 0, False: 1.33M]
  ------------------
  854|      0|            loader_platform_close_library(layer_list->list[i].lib_handle);
  855|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Unloading layer library %s",
  856|      0|                       layer_list->list[i].lib_name);
  857|      0|            layer_list->list[i].lib_handle = NULL;
  858|      0|        }
  859|  1.33M|        loader_free_layer_properties(inst, &(layer_list->list[i]));
  860|  1.33M|    }
  861|  25.1k|    layer_list->count = 0;
  862|       |
  863|  25.1k|    if (layer_list->capacity > 0) {
  ------------------
  |  Branch (863:9): [True: 6.55k, False: 18.5k]
  ------------------
  864|  6.55k|        layer_list->capacity = 0;
  865|  6.55k|        loader_instance_heap_free(inst, layer_list->list);
  866|  6.55k|    }
  867|  25.1k|    memset(layer_list, 0, sizeof(struct loader_layer_list));
  868|  25.1k|}
loader_remove_layer_in_list:
  871|  1.23M|                                 uint32_t layer_to_remove) {
  872|  1.23M|    if (layer_list == NULL || layer_to_remove >= layer_list->count) {
  ------------------
  |  Branch (872:9): [True: 0, False: 1.23M]
  |  Branch (872:31): [True: 0, False: 1.23M]
  ------------------
  873|      0|        return;
  874|      0|    }
  875|  1.23M|    loader_free_layer_properties(inst, &(layer_list->list[layer_to_remove]));
  876|       |
  877|       |    // Remove the current invalid meta-layer from the layer list.  Use memmove since we are
  878|       |    // overlapping the source and destination addresses.
  879|  1.23M|    if (layer_to_remove + 1 <= layer_list->count) {
  ------------------
  |  Branch (879:9): [True: 1.23M, False: 0]
  ------------------
  880|  1.23M|        memmove(&layer_list->list[layer_to_remove], &layer_list->list[layer_to_remove + 1],
  881|  1.23M|                sizeof(struct loader_layer_properties) * (layer_list->count - 1 - layer_to_remove));
  882|  1.23M|    }
  883|       |    // Decrement the count (because we now have one less) and decrement the loop index since we need to
  884|       |    // re-check this index.
  885|  1.23M|    layer_list->count--;
  886|  1.23M|}
loader_remove_layers_in_blacklist:
  890|  1.36k|void loader_remove_layers_in_blacklist(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
  891|  1.36k|    struct loader_layer_properties *override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list);
  ------------------
  |  |  142|  1.36k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  892|  1.36k|    if (NULL == override_prop) {
  ------------------
  |  Branch (892:9): [True: 0, False: 1.36k]
  ------------------
  893|      0|        return;
  894|      0|    }
  895|       |
  896|  2.14M|    for (int32_t j = 0; j < (int32_t)(layer_list->count); j++) {
  ------------------
  |  Branch (896:25): [True: 2.14M, False: 1.36k]
  ------------------
  897|  2.14M|        struct loader_layer_properties cur_layer_prop = layer_list->list[j];
  898|  2.14M|        const char *cur_layer_name = &cur_layer_prop.info.layerName[0];
  899|       |
  900|       |        // Skip the override layer itself.
  901|  2.14M|        if (!strcmp(VK_OVERRIDE_LAYER_NAME, cur_layer_name)) {
  ------------------
  |  |  142|  2.14M|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (901:13): [True: 3.04k, False: 2.14M]
  ------------------
  902|  3.04k|            continue;
  903|  3.04k|        }
  904|       |
  905|       |        // If found in the override layer's blacklist, remove it
  906|  2.14M|        if (loader_find_layer_name_in_blacklist(cur_layer_name, override_prop)) {
  ------------------
  |  Branch (906:13): [True: 0, False: 2.14M]
  ------------------
  907|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  908|      0|                       "loader_remove_layers_in_blacklist: Override layer is active and layer %s is in the blacklist inside of it. "
  909|      0|                       "Removing that layer from current layer list.",
  910|      0|                       cur_layer_name);
  911|      0|            loader_remove_layer_in_list(inst, layer_list, j);
  912|      0|            j--;
  913|       |
  914|       |            // Re-do the query for the override layer
  915|      0|            override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list);
  ------------------
  |  |  142|      0|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  916|      0|        }
  917|  2.14M|    }
  918|  1.36k|}
loader_init_generic_list:
 1075|  20.1k|VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) {
 1076|  20.1k|    size_t capacity = 32 * element_size;
 1077|  20.1k|    list_info->count = 0;
 1078|  20.1k|    list_info->capacity = 0;
 1079|  20.1k|    list_info->list = loader_instance_heap_calloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1080|  20.1k|    if (list_info->list == NULL) {
  ------------------
  |  Branch (1080:9): [True: 0, False: 20.1k]
  ------------------
 1081|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_init_generic_list: Failed to allocate space for generic list");
 1082|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
 1083|      0|    }
 1084|  20.1k|    list_info->capacity = capacity;
 1085|  20.1k|    return VK_SUCCESS;
 1086|  20.1k|}
loader_destroy_generic_list:
 1104|  10.5M|void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
 1105|  10.5M|    loader_instance_heap_free(inst, list->list);
 1106|  10.5M|    memset(list, 0, sizeof(struct loader_generic_list));
 1107|  10.5M|}
loader_add_to_ext_list:
 1160|   325k|                                uint32_t prop_list_count, const VkExtensionProperties *props) {
 1161|   325k|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1161:9): [True: 7.23k, False: 318k]
  |  Branch (1161:35): [True: 0, False: 318k]
  ------------------
 1162|  7.23k|        VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
 1163|  7.23k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1163:13): [True: 0, False: 7.23k]
  ------------------
 1164|      0|            return res;
 1165|      0|        }
 1166|  7.23k|    }
 1167|       |
 1168|   651k|    for (uint32_t i = 0; i < prop_list_count; i++) {
  ------------------
  |  Branch (1168:26): [True: 325k, False: 325k]
  ------------------
 1169|   325k|        const VkExtensionProperties *cur_ext = &props[i];
 1170|       |
 1171|       |        // look for duplicates
 1172|   325k|        if (has_vk_extension_property(cur_ext, ext_list)) {
  ------------------
  |  Branch (1172:13): [True: 107k, False: 217k]
  ------------------
 1173|   107k|            continue;
 1174|   107k|        }
 1175|       |
 1176|       |        // add to list at end
 1177|       |        // check for enough capacity
 1178|   217k|        if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) {
  ------------------
  |  Branch (1178:13): [True: 6.04k, False: 211k]
  ------------------
 1179|  6.04k|            void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1180|  6.04k|                                                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1181|  6.04k|            if (new_ptr == NULL) {
  ------------------
  |  Branch (1181:17): [True: 0, False: 6.04k]
  ------------------
 1182|      0|                loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1183|      0|                           "loader_add_to_ext_list: Failed to reallocate space for extension list");
 1184|      0|                return VK_ERROR_OUT_OF_HOST_MEMORY;
 1185|      0|            }
 1186|  6.04k|            ext_list->list = new_ptr;
 1187|       |
 1188|       |            // double capacity
 1189|  6.04k|            ext_list->capacity *= 2;
 1190|  6.04k|        }
 1191|       |
 1192|       |        // every caller passes the address of an array element or on-stack struct, never NULL
 1193|       |        // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
 1194|   217k|        memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
 1195|   217k|        ext_list->count++;
 1196|   217k|    }
 1197|   325k|    return VK_SUCCESS;
 1198|   325k|}
loader_add_to_dev_ext_list:
 1205|  52.3k|                                    const VkExtensionProperties *props, struct loader_string_list *entrys) {
 1206|  52.3k|    VkResult res = VK_SUCCESS;
 1207|  52.3k|    bool should_free_entrys = true;
 1208|  52.3k|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1208:9): [True: 6.31k, False: 46.0k]
  |  Branch (1208:35): [True: 0, False: 46.0k]
  ------------------
 1209|  6.31k|        res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props));
 1210|  6.31k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1210:13): [True: 0, False: 6.31k]
  ------------------
 1211|      0|            goto out;
 1212|      0|        }
 1213|  6.31k|    }
 1214|       |
 1215|       |    // look for duplicates
 1216|  52.3k|    if (has_vk_dev_ext_property(props, ext_list)) {
  ------------------
  |  Branch (1216:9): [True: 11.4k, False: 40.8k]
  ------------------
 1217|  11.4k|        goto out;
 1218|  11.4k|    }
 1219|       |
 1220|  40.8k|    uint32_t idx = ext_list->count;
 1221|       |    // add to list at end
 1222|       |    // check for enough capacity
 1223|  40.8k|    if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
  ------------------
  |  Branch (1223:9): [True: 813, False: 40.0k]
  ------------------
 1224|    813|        void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1225|    813|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1226|       |
 1227|    813|        if (NULL == new_ptr) {
  ------------------
  |  Branch (1227:13): [True: 0, False: 813]
  ------------------
 1228|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1229|      0|                       "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list");
 1230|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1231|      0|            goto out;
 1232|      0|        }
 1233|    813|        ext_list->list = new_ptr;
 1234|       |
 1235|       |        // double capacity
 1236|    813|        ext_list->capacity *= 2;
 1237|    813|    }
 1238|       |
 1239|       |    // every caller passes the address of an array element or on-stack struct, never NULL
 1240|       |    // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
 1241|  40.8k|    memcpy(&ext_list->list[idx].props, props, sizeof(*props));
 1242|  40.8k|    if (entrys) {
  ------------------
  |  Branch (1242:9): [True: 2.17k, False: 38.7k]
  ------------------
 1243|  2.17k|        ext_list->list[idx].entrypoints = *entrys;
 1244|  2.17k|        should_free_entrys = false;
 1245|  38.7k|    } else {
 1246|  38.7k|        memset(&ext_list->list[idx].entrypoints, 0, sizeof(ext_list->list[idx].entrypoints));
 1247|  38.7k|    }
 1248|  40.8k|    ext_list->count++;
 1249|  52.3k|out:
 1250|  52.3k|    if (NULL != entrys && should_free_entrys) {
  ------------------
  |  Branch (1250:9): [True: 3.62k, False: 48.7k]
  |  Branch (1250:27): [True: 1.45k, False: 2.17k]
  ------------------
 1251|  1.45k|        free_string_list(inst, entrys);
 1252|  1.45k|    }
 1253|  52.3k|    return res;
 1254|  40.8k|}
loader_destroy_pointer_layer_list:
 1281|  8.37k|void loader_destroy_pointer_layer_list(const struct loader_instance *inst, struct loader_pointer_layer_list *layer_list) {
 1282|  8.37k|    loader_instance_heap_free(inst, (void *)layer_list->list);
 1283|  8.37k|    memset(layer_list, 0, sizeof(struct loader_pointer_layer_list));
 1284|  8.37k|}
loader_layer_is_available:
 1315|  2.16M|                               const struct loader_layer_properties *prop) {
 1316|  2.16M|    bool available = true;
 1317|  2.16M|    bool is_implicit = (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER));
 1318|  2.16M|    bool disabled_by_type =
 1319|  2.16M|        is_implicit ? filters->disable_filter.disable_all_implicit : filters->disable_filter.disable_all_explicit;
  ------------------
  |  Branch (1319:9): [True: 103k, False: 2.06M]
  ------------------
 1320|  2.16M|    if ((filters->disable_filter.disable_all || disabled_by_type ||
  ------------------
  |  Branch (1320:10): [True: 0, False: 2.16M]
  |  Branch (1320:49): [True: 0, False: 2.16M]
  ------------------
 1321|  2.16M|         check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) &&
  ------------------
  |  Branch (1321:10): [True: 0, False: 2.16M]
  ------------------
 1322|      0|        !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) {
  ------------------
  |  Branch (1322:9): [True: 0, False: 0]
  ------------------
 1323|      0|        available = false;
 1324|      0|    }
 1325|  2.16M|    if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) {
  ------------------
  |  Branch (1325:9): [True: 448, False: 2.16M]
  ------------------
 1326|    448|        available = true;
 1327|  2.16M|    } else if (!available) {
  ------------------
  |  Branch (1327:16): [True: 0, False: 2.16M]
  ------------------
 1328|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1329|      0|                   "Layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName,
 1330|      0|                   VK_LAYERS_DISABLE_ENV_VAR);
  ------------------
  |  |  120|      0|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
 1331|      0|    }
 1332|       |
 1333|  2.16M|    return available;
 1334|  2.16M|}
loader_implicit_layer_is_enabled:
 1379|  4.39k|                                      const struct loader_layer_properties *prop) {
 1380|  4.39k|    bool enable = false;
 1381|  4.39k|    bool forced_disabled = false;
 1382|  4.39k|    bool forced_enabled = false;
 1383|       |
 1384|  4.39k|    if ((filters->disable_filter.disable_all || filters->disable_filter.disable_all_implicit ||
  ------------------
  |  Branch (1384:10): [True: 0, False: 4.39k]
  |  Branch (1384:49): [True: 0, False: 4.39k]
  ------------------
 1385|  4.39k|         check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) &&
  ------------------
  |  Branch (1385:10): [True: 0, False: 4.39k]
  ------------------
 1386|      0|        !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) {
  ------------------
  |  Branch (1386:9): [True: 0, False: 0]
  ------------------
 1387|      0|        forced_disabled = true;
 1388|      0|    }
 1389|  4.39k|    if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) {
  ------------------
  |  Branch (1389:9): [True: 0, False: 4.39k]
  ------------------
 1390|      0|        forced_enabled = true;
 1391|      0|    }
 1392|       |
 1393|       |    // If no enable_environment variable is specified, this implicit layer is always be enabled by default.
 1394|  4.39k|    if (NULL == prop->enable_env_var.name) {
  ------------------
  |  Branch (1394:9): [True: 4.23k, False: 162]
  ------------------
 1395|  4.23k|        enable = true;
 1396|  4.23k|    } else {
 1397|    162|        char *env_value = loader_getenv(prop->enable_env_var.name, inst);
 1398|    162|        if (env_value && !strcmp(prop->enable_env_var.value, env_value)) {
  ------------------
  |  Branch (1398:13): [True: 158, False: 4]
  |  Branch (1398:26): [True: 0, False: 158]
  ------------------
 1399|      0|            enable = true;
 1400|      0|        }
 1401|       |
 1402|       |        // Otherwise, only enable this layer if the enable environment variable is defined
 1403|    162|        loader_free_getenv(env_value, inst);
 1404|    162|    }
 1405|       |
 1406|  4.39k|    if (forced_enabled) {
  ------------------
  |  Branch (1406:9): [True: 0, False: 4.39k]
  ------------------
 1407|       |        // Only report a message that we've forced on a layer if it wouldn't have been enabled
 1408|       |        // normally.
 1409|      0|        if (!enable) {
  ------------------
  |  Branch (1409:13): [True: 0, False: 0]
  ------------------
 1410|      0|            enable = true;
 1411|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1412|      0|                       "Implicit layer \"%s\" forced enabled due to env var \'%s\'.", prop->info.layerName,
 1413|      0|                       VK_LAYERS_ENABLE_ENV_VAR);
  ------------------
  |  |  119|      0|#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
  ------------------
 1414|      0|        }
 1415|  4.39k|    } else if (enable && forced_disabled) {
  ------------------
  |  Branch (1415:16): [True: 4.23k, False: 162]
  |  Branch (1415:26): [True: 0, False: 4.23k]
  ------------------
 1416|      0|        enable = false;
 1417|       |        // Report a message that we've forced off a layer if it would have been enabled normally.
 1418|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1419|      0|                   "Implicit layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName,
 1420|      0|                   VK_LAYERS_DISABLE_ENV_VAR);
  ------------------
  |  |  120|      0|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
 1421|      0|        return enable;
 1422|      0|    }
 1423|       |
 1424|       |    // The disable_environment has priority over everything else.  If it is defined, the layer is always
 1425|       |    // disabled.
 1426|  4.39k|    if (NULL != prop->disable_env_var.name) {
  ------------------
  |  Branch (1426:9): [True: 2.89k, False: 1.50k]
  ------------------
 1427|  2.89k|        char *env_value = loader_getenv(prop->disable_env_var.name, inst);
 1428|  2.89k|        if (NULL != env_value) {
  ------------------
  |  Branch (1428:13): [True: 3, False: 2.89k]
  ------------------
 1429|      3|            enable = false;
 1430|      3|        }
 1431|  2.89k|        loader_free_getenv(env_value, inst);
 1432|  2.89k|    } else if ((prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER) == 0) {
  ------------------
  |  Branch (1432:16): [True: 0, False: 1.50k]
  ------------------
 1433|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1434|      0|                   "Implicit layer \"%s\" missing disabled environment variable!", prop->info.layerName);
 1435|      0|    }
 1436|       |
 1437|       |    // Enable this layer if it is included in the override layer
 1438|  4.39k|    if (inst != NULL && inst->override_layer_present) {
  ------------------
  |  Branch (1438:9): [True: 4.39k, False: 0]
  |  Branch (1438:25): [True: 0, False: 4.39k]
  ------------------
 1439|      0|        struct loader_layer_properties *override = NULL;
 1440|      0|        for (uint32_t i = 0; i < inst->instance_layer_list.count; ++i) {
  ------------------
  |  Branch (1440:30): [True: 0, False: 0]
  ------------------
 1441|      0|            if (strcmp(inst->instance_layer_list.list[i].info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) {
  ------------------
  |  |  142|      0|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (1441:17): [True: 0, False: 0]
  ------------------
 1442|      0|                override = &inst->instance_layer_list.list[i];
 1443|      0|                break;
 1444|      0|            }
 1445|      0|        }
 1446|      0|        if (override != NULL) {
  ------------------
  |  Branch (1446:13): [True: 0, False: 0]
  ------------------
 1447|      0|            for (uint32_t i = 0; i < override->component_layer_names.count; ++i) {
  ------------------
  |  Branch (1447:34): [True: 0, False: 0]
  ------------------
 1448|      0|                if (strcmp(override->component_layer_names.list[i], prop->info.layerName) == 0) {
  ------------------
  |  Branch (1448:21): [True: 0, False: 0]
  ------------------
 1449|      0|                    enable = true;
 1450|      0|                    break;
 1451|      0|                }
 1452|      0|            }
 1453|      0|        }
 1454|      0|    }
 1455|       |
 1456|  4.39k|    return enable;
 1457|  4.39k|}
loader_clear_scanned_icd_list:
 1881|  9.20k|void loader_clear_scanned_icd_list(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
 1882|  9.20k|    if (0 != icd_tramp_list->capacity && icd_tramp_list->scanned_list) {
  ------------------
  |  Branch (1882:9): [True: 838, False: 8.37k]
  |  Branch (1882:42): [True: 838, False: 0]
  ------------------
 1883|    838|        for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
  ------------------
  |  Branch (1883:30): [True: 0, False: 838]
  ------------------
 1884|      0|            if (icd_tramp_list->scanned_list[i].handle) {
  ------------------
  |  Branch (1884:17): [True: 0, False: 0]
  ------------------
 1885|      0|                loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
 1886|       |                icd_tramp_list->scanned_list[i].handle = NULL;
 1887|      0|            }
 1888|      0|            loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name);
 1889|      0|        }
 1890|    838|        loader_instance_heap_free(inst, icd_tramp_list->scanned_list);
 1891|    838|    }
 1892|  9.20k|    memset(icd_tramp_list, 0, sizeof(struct loader_icd_tramp_list));
 1893|  9.20k|}
loader_init_scanned_icd_list:
 1895|    838|VkResult loader_init_scanned_icd_list(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
 1896|    838|    VkResult res = VK_SUCCESS;
 1897|    838|    loader_clear_scanned_icd_list(inst, icd_tramp_list);
 1898|    838|    icd_tramp_list->capacity = 8 * sizeof(struct loader_scanned_icd);
 1899|    838|    icd_tramp_list->scanned_list = loader_instance_heap_alloc(inst, icd_tramp_list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1900|    838|    if (NULL == icd_tramp_list->scanned_list) {
  ------------------
  |  Branch (1900:9): [True: 0, False: 838]
  ------------------
 1901|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1902|      0|                   "loader_init_scanned_icd_list: Realloc failed for layer list when attempting to add new layer");
 1903|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1904|      0|    }
 1905|    838|    return res;
 1906|    838|}
loader_scan_for_direct_drivers:
 2044|    838|                                        struct loader_icd_tramp_list *icd_tramp_list, bool *direct_driver_loading_exclusive_mode) {
 2045|    838|    if (NULL == pCreateInfo) {
  ------------------
  |  Branch (2045:9): [True: 0, False: 838]
  ------------------
 2046|       |        // Don't do this logic unless we are being called from vkCreateInstance, when pCreateInfo will be non-null
 2047|      0|        return VK_SUCCESS;
 2048|      0|    }
 2049|    838|    bool direct_driver_loading_enabled = false;
 2050|       |    // Try to if VK_LUNARG_direct_driver_loading is enabled and if we are using it exclusively
 2051|       |    // Skip this step if inst is NULL, aka when this function is being called before instance creation
 2052|    838|    if (inst != NULL && pCreateInfo->ppEnabledExtensionNames && pCreateInfo->enabledExtensionCount > 0) {
  ------------------
  |  Branch (2052:9): [True: 838, False: 0]
  |  Branch (2052:25): [True: 0, False: 838]
  |  Branch (2052:65): [True: 0, False: 0]
  ------------------
 2053|       |        // Look through the enabled extension list, make sure VK_LUNARG_direct_driver_loading is present
 2054|      0|        for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
  ------------------
  |  Branch (2054:30): [True: 0, False: 0]
  ------------------
 2055|      0|            if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME) == 0) {
  ------------------
  |  Branch (2055:17): [True: 0, False: 0]
  ------------------
 2056|      0|                direct_driver_loading_enabled = true;
 2057|      0|                break;
 2058|      0|            }
 2059|      0|        }
 2060|      0|    }
 2061|    838|    const VkDirectDriverLoadingListLUNARG *ddl_list = NULL;
 2062|       |    // Find the VkDirectDriverLoadingListLUNARG struct in the pNext chain of vkInstanceCreateInfo
 2063|    838|    const void *pNext = pCreateInfo->pNext;
 2064|    838|    while (pNext) {
  ------------------
  |  Branch (2064:12): [True: 0, False: 838]
  ------------------
 2065|      0|        VkBaseInStructure out_structure = {0};
 2066|      0|        memcpy(&out_structure, pNext, sizeof(VkBaseInStructure));
 2067|      0|        if (out_structure.sType == VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG) {
  ------------------
  |  Branch (2067:13): [True: 0, False: 0]
  ------------------
 2068|      0|            ddl_list = (VkDirectDriverLoadingListLUNARG *)pNext;
 2069|      0|            break;
 2070|      0|        }
 2071|      0|        pNext = out_structure.pNext;
 2072|      0|    }
 2073|    838|    if (NULL == ddl_list) {
  ------------------
  |  Branch (2073:9): [True: 838, False: 0]
  ------------------
 2074|    838|        if (direct_driver_loading_enabled) {
  ------------------
  |  Branch (2074:13): [True: 0, False: 838]
  ------------------
 2075|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2076|      0|                       "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension was enabled but the "
 2077|      0|                       "pNext chain of "
 2078|      0|                       "VkInstanceCreateInfo did not contain the "
 2079|      0|                       "VkDirectDriverLoadingListLUNARG structure.");
 2080|      0|        }
 2081|       |        // Always want to exit early if there was no VkDirectDriverLoadingListLUNARG in the pNext chain
 2082|    838|        return VK_SUCCESS;
 2083|    838|    }
 2084|       |
 2085|      0|    if (!direct_driver_loading_enabled) {
  ------------------
  |  Branch (2085:9): [True: 0, False: 0]
  ------------------
 2086|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2087|      0|                   "loader_scan_for_direct_drivers: The pNext chain of VkInstanceCreateInfo contained the "
 2088|      0|                   "VkDirectDriverLoadingListLUNARG structure, but the VK_LUNARG_direct_driver_loading extension was "
 2089|      0|                   "not enabled.");
 2090|      0|        return VK_SUCCESS;
 2091|      0|    }
 2092|       |    // If we are using exclusive mode, skip looking for any more drivers from system or environment variables
 2093|      0|    if (ddl_list->mode == VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG) {
  ------------------
  |  Branch (2093:9): [True: 0, False: 0]
  ------------------
 2094|      0|        *direct_driver_loading_exclusive_mode = true;
 2095|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2096|      0|                   "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension is active and specified "
 2097|      0|                   "VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG, skipping system and environment "
 2098|      0|                   "variable driver search mechanisms.");
 2099|      0|    }
 2100|      0|    if (NULL == ddl_list->pDrivers) {
  ------------------
  |  Branch (2100:9): [True: 0, False: 0]
  ------------------
 2101|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2102|      0|                   "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
 2103|      0|                   "VkInstanceCreateInfo has a NULL pDrivers member.");
 2104|      0|        return VK_SUCCESS;
 2105|      0|    }
 2106|      0|    if (ddl_list->driverCount == 0) {
  ------------------
  |  Branch (2106:9): [True: 0, False: 0]
  ------------------
 2107|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2108|      0|                   "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
 2109|      0|                   "VkInstanceCreateInfo has a non-null pDrivers member but a driverCount member with a value "
 2110|      0|                   "of zero.");
 2111|      0|        return VK_SUCCESS;
 2112|      0|    }
 2113|       |    // Go through all VkDirectDriverLoadingInfoLUNARG entries and add each driver
 2114|       |    // Because icd_tramp's are prepended, this will result in the drivers appearing at the end
 2115|      0|    for (uint32_t i = 0; i < ddl_list->driverCount; i++) {
  ------------------
  |  Branch (2115:26): [True: 0, False: 0]
  ------------------
 2116|      0|        VkResult res = loader_add_direct_driver(inst, i, &ddl_list->pDrivers[i], icd_tramp_list);
 2117|      0|        if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2117:13): [True: 0, False: 0]
  ------------------
 2118|      0|            return res;
 2119|      0|        }
 2120|      0|    }
 2121|       |
 2122|      0|    return VK_SUCCESS;
 2123|      0|}
loader_scanned_icd_add:
 2126|     33|                                const char *filename, uint32_t api_version, enum loader_layer_library_status *lib_status) {
 2127|     33|    loader_platform_dl_handle handle = NULL;
 2128|     33|    PFN_vkCreateInstance fp_create_inst = NULL;
 2129|     33|    PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props = NULL;
 2130|     33|    PFN_vkGetInstanceProcAddr fp_get_proc_addr = NULL;
 2131|     33|    PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL;
 2132|     33|    PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version = NULL;
 2133|       |#if defined(VK_USE_PLATFORM_WIN32_KHR)
 2134|       |    PFN_vk_icdEnumerateAdapterPhysicalDevices fp_enum_dxgi_adapter_phys_devs = NULL;
 2135|       |#endif
 2136|     33|    struct loader_scanned_icd *new_scanned_icd = NULL;
 2137|     33|    uint32_t interface_vers;
 2138|     33|    VkResult res = VK_SUCCESS;
 2139|       |
 2140|       |    // loader_icd_scan reads *lib_status whenever this returns VK_ERROR_INCOMPATIBLE_DRIVER, but several of the failure
 2141|       |    // paths below (NULL filename, missing vkCreateInstance / vkEnumerateInstanceExtensionProperties) don't set it. Seed a
 2142|       |    // default so the caller never switches on an indeterminate value; the more specific paths still override it.
 2143|     33|    if (NULL != lib_status) {
  ------------------
  |  Branch (2143:9): [True: 33, False: 0]
  ------------------
 2144|     33|        *lib_status = LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD;
 2145|     33|    }
 2146|       |
 2147|       |    // This shouldn't happen, but the check is necessary because dlopen returns a handle to the main program when
 2148|       |    // filename is NULL
 2149|     33|    if (filename == NULL) {
  ------------------
  |  Branch (2149:9): [True: 0, False: 33]
  ------------------
 2150|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_scanned_icd_add: A NULL filename was used, skipping this ICD");
 2151|      0|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2152|      0|        goto out;
 2153|      0|    }
 2154|       |
 2155|       |// TODO implement smarter opening/closing of libraries. For now this
 2156|       |// function leaves libraries open and the scanned_icd_clear closes them
 2157|       |#if defined(__Fuchsia__)
 2158|       |    handle = loader_platform_open_driver(filename);
 2159|       |#else
 2160|     33|    handle = loader_platform_open_library(filename);
 2161|     33|#endif
 2162|     33|    if (NULL == handle) {
  ------------------
  |  Branch (2162:9): [True: 33, False: 0]
  ------------------
 2163|     33|        loader_handle_load_library_error(inst, filename, lib_status);
 2164|     33|        if (lib_status && *lib_status == LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY) {
  ------------------
  |  Branch (2164:13): [True: 33, False: 0]
  |  Branch (2164:27): [True: 1, False: 32]
  ------------------
 2165|      1|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 2166|     32|        } else {
 2167|     32|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2168|     32|        }
 2169|     33|        goto out;
 2170|     33|    }
 2171|       |
 2172|       |    // Try to load the driver's exported vk_icdNegotiateLoaderICDInterfaceVersion
 2173|      0|    fp_negotiate_icd_version = loader_platform_get_proc_address(handle, "vk_icdNegotiateLoaderICDInterfaceVersion");
 2174|       |
 2175|       |    // If it isn't exported, we are dealing with either a v0, v1, or a v7 and up driver
 2176|      0|    if (NULL == fp_negotiate_icd_version) {
  ------------------
  |  Branch (2176:9): [True: 0, False: 0]
  ------------------
 2177|       |        // Try to load the driver's exported vk_icdGetInstanceProcAddr - if this is a v7 or up driver, we can use it to get
 2178|       |        // the driver's vk_icdNegotiateLoaderICDInterfaceVersion function
 2179|      0|        fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
 2180|       |
 2181|       |        // If we successfully loaded vk_icdGetInstanceProcAddr, try to get vk_icdNegotiateLoaderICDInterfaceVersion
 2182|      0|        if (fp_get_proc_addr) {
  ------------------
  |  Branch (2182:13): [True: 0, False: 0]
  ------------------
 2183|      0|            fp_negotiate_icd_version =
 2184|      0|                (PFN_vk_icdNegotiateLoaderICDInterfaceVersion)fp_get_proc_addr(NULL, "vk_icdNegotiateLoaderICDInterfaceVersion");
 2185|      0|        }
 2186|      0|    }
 2187|       |
 2188|       |    // Try to negotiate the Loader and Driver Interface Versions
 2189|       |    // loader_get_icd_interface_version will check if fp_negotiate_icd_version is NULL, so we don't have to.
 2190|       |    // If it *is* NULL, that means this driver uses interface version 0 or 1
 2191|      0|    if (!loader_get_icd_interface_version(fp_negotiate_icd_version, &interface_vers)) {
  ------------------
  |  Branch (2191:9): [True: 0, False: 0]
  ------------------
 2192|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 2193|      0|                   "loader_scanned_icd_add: ICD %s doesn't support interface version compatible with loader, skip this ICD.",
 2194|      0|                   filename);
 2195|      0|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2196|      0|        *lib_status = LOADER_LAYER_LIB_ERROR_NEGOTIATE_INTERFACE_VERSION_FAILED;
 2197|      0|        goto out;
 2198|      0|    }
 2199|       |
 2200|       |    // If we didn't already query vk_icdGetInstanceProcAddr, try now
 2201|      0|    if (NULL == fp_get_proc_addr) {
  ------------------
  |  Branch (2201:9): [True: 0, False: 0]
  ------------------
 2202|      0|        fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
 2203|      0|    }
 2204|       |
 2205|       |    // If vk_icdGetInstanceProcAddr is NULL, this ICD is using version 0 and so we should respond accordingly.
 2206|      0|    if (NULL == fp_get_proc_addr) {
  ------------------
  |  Branch (2206:9): [True: 0, False: 0]
  ------------------
 2207|       |        // Exporting vk_icdNegotiateLoaderICDInterfaceVersion but not vk_icdGetInstanceProcAddr violates Version 2's
 2208|       |        // requirements, as for Version 2 to be supported Version 1 must also be supported
 2209|      0|        if (interface_vers != 0) {
  ------------------
  |  Branch (2209:13): [True: 0, False: 0]
  ------------------
 2210|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 2211|      0|                       "loader_scanned_icd_add: ICD %s reports an interface version of %d but doesn't export "
 2212|      0|                       "vk_icdGetInstanceProcAddr, skip this ICD.",
 2213|      0|                       filename, interface_vers);
 2214|      0|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2215|      0|            *lib_status = LOADER_LAYER_LIB_ERROR_UNABLE_TO_FIND_VK_GET_INSTANCE_PROC_ADDR;
 2216|      0|            goto out;
 2217|      0|        }
 2218|       |        // Use deprecated interface from version 0
 2219|      0|        fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
 2220|      0|        if (NULL == fp_get_proc_addr) {
  ------------------
  |  Branch (2220:13): [True: 0, False: 0]
  ------------------
 2221|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 2222|      0|                       "loader_scanned_icd_add: Attempt to retrieve either \'vkGetInstanceProcAddr\' or "
 2223|      0|                       "\'vk_icdGetInstanceProcAddr\' from ICD %s failed.",
 2224|      0|                       filename);
 2225|      0|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2226|      0|            *lib_status = LOADER_LAYER_LIB_ERROR_UNABLE_TO_FIND_VK_GET_INSTANCE_PROC_ADDR;
 2227|      0|            goto out;
 2228|      0|        } else {
 2229|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2230|      0|                       "loader_scanned_icd_add: Using deprecated ICD interface of \'vkGetInstanceProcAddr\' instead of "
 2231|      0|                       "\'vk_icdGetInstanceProcAddr\' for ICD %s",
 2232|      0|                       filename);
 2233|      0|        }
 2234|      0|        fp_create_inst = loader_platform_get_proc_address(handle, "vkCreateInstance");
 2235|      0|        if (NULL == fp_create_inst) {
  ------------------
  |  Branch (2235:13): [True: 0, False: 0]
  ------------------
 2236|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 2237|      0|                       "loader_scanned_icd_add:  Failed querying \'vkCreateInstance\' via dlsym/LoadLibrary for ICD %s", filename);
 2238|      0|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2239|      0|            goto out;
 2240|      0|        }
 2241|      0|        fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties");
 2242|      0|        if (NULL == fp_get_inst_ext_props) {
  ------------------
  |  Branch (2242:13): [True: 0, False: 0]
  ------------------
 2243|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 2244|      0|                       "loader_scanned_icd_add: Could not get \'vkEnumerateInstanceExtensionProperties\' via dlsym/LoadLibrary "
 2245|      0|                       "for ICD %s",
 2246|      0|                       filename);
 2247|      0|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2248|      0|            goto out;
 2249|      0|        }
 2250|      0|    } else {
 2251|       |        // vk_icdGetInstanceProcAddr was successfully found, we can assume the version is at least one
 2252|       |        // If vk_icdNegotiateLoaderICDInterfaceVersion was also found, interface_vers must be 2 or greater, so this check is
 2253|       |        // fine
 2254|      0|        if (interface_vers == 0) {
  ------------------
  |  Branch (2254:13): [True: 0, False: 0]
  ------------------
 2255|      0|            interface_vers = 1;
 2256|      0|        }
 2257|       |
 2258|      0|        fp_create_inst = (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance");
 2259|      0|        if (NULL == fp_create_inst) {
  ------------------
  |  Branch (2259:13): [True: 0, False: 0]
  ------------------
 2260|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 2261|      0|                       "loader_scanned_icd_add: Could not get \'vkCreateInstance\' via \'vk_icdGetInstanceProcAddr\' for ICD %s",
 2262|      0|                       filename);
 2263|      0|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2264|      0|            *lib_status = LOADER_LAYER_LIB_ERROR_UNABLE_TO_FIND_VK_GET_INSTANCE_PROC_ADDR;
 2265|      0|            goto out;
 2266|      0|        }
 2267|      0|        fp_get_inst_ext_props =
 2268|      0|            (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties");
 2269|      0|        if (NULL == fp_get_inst_ext_props) {
  ------------------
  |  Branch (2269:13): [True: 0, False: 0]
  ------------------
 2270|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 2271|      0|                       "loader_scanned_icd_add: Could not get \'vkEnumerateInstanceExtensionProperties\' via "
 2272|      0|                       "\'vk_icdGetInstanceProcAddr\' for ICD %s",
 2273|      0|                       filename);
 2274|      0|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 2275|      0|            goto out;
 2276|      0|        }
 2277|       |        // Query "vk_icdGetPhysicalDeviceProcAddr" with vk_icdGetInstanceProcAddr if the library reports interface version 7 or
 2278|       |        // greater, otherwise fallback to loading it from the platform dynamic linker
 2279|      0|        if (interface_vers >= 7) {
  ------------------
  |  Branch (2279:13): [True: 0, False: 0]
  ------------------
 2280|      0|            fp_get_phys_dev_proc_addr =
 2281|      0|                (PFN_vk_icdGetPhysicalDeviceProcAddr)fp_get_proc_addr(NULL, "vk_icdGetPhysicalDeviceProcAddr");
 2282|      0|        }
 2283|      0|        if (NULL == fp_get_phys_dev_proc_addr && interface_vers >= 3) {
  ------------------
  |  Branch (2283:13): [True: 0, False: 0]
  |  Branch (2283:50): [True: 0, False: 0]
  ------------------
 2284|      0|            fp_get_phys_dev_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetPhysicalDeviceProcAddr");
 2285|      0|        }
 2286|       |#if defined(VK_USE_PLATFORM_WIN32_KHR)
 2287|       |        // Query "vk_icdEnumerateAdapterPhysicalDevices" with vk_icdGetInstanceProcAddr if the library reports interface version
 2288|       |        // 7 or greater, otherwise fallback to loading it from the platform dynamic linker
 2289|       |        if (interface_vers >= 7) {
 2290|       |            fp_enum_dxgi_adapter_phys_devs =
 2291|       |                (PFN_vk_icdEnumerateAdapterPhysicalDevices)fp_get_proc_addr(NULL, "vk_icdEnumerateAdapterPhysicalDevices");
 2292|       |        }
 2293|       |        if (NULL == fp_enum_dxgi_adapter_phys_devs && interface_vers >= 6) {
 2294|       |            fp_enum_dxgi_adapter_phys_devs = loader_platform_get_proc_address(handle, "vk_icdEnumerateAdapterPhysicalDevices");
 2295|       |        }
 2296|       |#endif
 2297|      0|    }
 2298|       |
 2299|       |    // check for enough capacity
 2300|      0|    if ((icd_tramp_list->count * sizeof(struct loader_scanned_icd)) >= icd_tramp_list->capacity) {
  ------------------
  |  Branch (2300:9): [True: 0, False: 0]
  ------------------
 2301|      0|        void *new_ptr = loader_instance_heap_realloc(inst, icd_tramp_list->scanned_list, icd_tramp_list->capacity,
 2302|      0|                                                     icd_tramp_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 2303|      0|        if (NULL == new_ptr) {
  ------------------
  |  Branch (2303:13): [True: 0, False: 0]
  ------------------
 2304|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 2305|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_scanned_icd_add: Realloc failed on icd library list for ICD %s",
 2306|      0|                       filename);
 2307|      0|            goto out;
 2308|      0|        }
 2309|      0|        icd_tramp_list->scanned_list = new_ptr;
 2310|       |
 2311|       |        // double capacity
 2312|      0|        icd_tramp_list->capacity *= 2;
 2313|      0|    }
 2314|       |
 2315|      0|    loader_api_version api_version_struct = loader_make_version(api_version);
 2316|      0|    if (interface_vers <= 4 && loader_check_version_meets_required(LOADER_VERSION_1_1_0, api_version_struct)) {
  ------------------
  |  |  270|      0|#define LOADER_VERSION_1_1_0 loader_combine_version(1, 1, 0)
  ------------------
  |  Branch (2316:9): [True: 0, False: 0]
  |  Branch (2316:32): [True: 0, False: 0]
  ------------------
 2317|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2318|      0|                   "loader_scanned_icd_add: Driver %s supports Vulkan %u.%u, but only supports loader interface version %u."
 2319|      0|                   " Interface version 5 or newer required to support this version of Vulkan (Policy #LDP_DRIVER_7)",
 2320|      0|                   filename, api_version_struct.major, api_version_struct.minor, interface_vers);
 2321|      0|    }
 2322|       |
 2323|      0|    new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
 2324|      0|    new_scanned_icd->handle = handle;
 2325|      0|    new_scanned_icd->api_version = api_version;
 2326|      0|    new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr;
 2327|      0|    new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr;
 2328|      0|    new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
 2329|      0|    new_scanned_icd->CreateInstance = fp_create_inst;
 2330|       |#if defined(VK_USE_PLATFORM_WIN32_KHR)
 2331|       |    new_scanned_icd->EnumerateAdapterPhysicalDevices = fp_enum_dxgi_adapter_phys_devs;
 2332|       |#endif
 2333|      0|    new_scanned_icd->interface_version = interface_vers;
 2334|       |
 2335|      0|    res = loader_copy_to_new_str(inst, filename, &new_scanned_icd->lib_name);
 2336|      0|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2336:9): [True: 0, False: 0]
  ------------------
 2337|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_scanned_icd_add: Out of memory can't add ICD %s", filename);
 2338|      0|        goto out;
 2339|      0|    }
 2340|       |
 2341|       |    // Uses OS calls to find the 'true' path to the binary, for more accurate logging later on.
 2342|      0|    res = fixup_library_binary_path(inst, &(new_scanned_icd->lib_name), new_scanned_icd->handle, fp_get_proc_addr);
 2343|      0|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2343:9): [True: 0, False: 0]
  ------------------
 2344|      0|        loader_instance_heap_free(inst, new_scanned_icd->lib_name);
 2345|      0|        goto out;
 2346|      0|    }
 2347|       |
 2348|      0|    icd_tramp_list->count++;
 2349|       |
 2350|     33|out:
 2351|     33|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (2351:9): [True: 33, False: 0]
  ------------------
 2352|     33|        if (NULL != handle) {
  ------------------
  |  Branch (2352:13): [True: 0, False: 33]
  ------------------
 2353|      0|            loader_platform_close_library(handle);
 2354|      0|        }
 2355|     33|    }
 2356|       |
 2357|     33|    return res;
 2358|      0|}
loader_initialize:
 2366|      2|void loader_initialize(void) {
 2367|      2|    loader_platform_thread_create_mutex(&loader_lock);
 2368|      2|    loader_platform_thread_create_mutex(&loader_preload_icd_lock);
 2369|      2|    init_global_loader_settings();
 2370|      2|#endif
 2371|       |
 2372|       |    // initialize logging
 2373|      2|    loader_init_global_debug_level();
 2374|       |#if defined(_WIN32)
 2375|       |    windows_initialization();
 2376|       |#endif
 2377|       |
 2378|      2|    loader_api_version version = loader_make_full_version(VK_HEADER_VERSION_COMPLETE);
 2379|      2|    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", version.major, version.minor, version.patch);
 2380|       |
 2381|       |#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO)
 2382|       |    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "[Vulkan Loader Git - Tag: " GIT_BRANCH_NAME ", Branch/Commit: " GIT_TAG_INFO "]");
 2383|       |#endif
 2384|       |
 2385|      2|    char *loader_disable_dynamic_library_unloading_env_var = loader_getenv("VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING", NULL);
 2386|      2|    if (loader_disable_dynamic_library_unloading_env_var &&
  ------------------
  |  Branch (2386:9): [True: 0, False: 2]
  ------------------
 2387|       |        // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - n=2 intentionally excludes "1x" values like "10"
 2388|      0|        0 == strncmp(loader_disable_dynamic_library_unloading_env_var, "1", 2)) {
  ------------------
  |  Branch (2388:9): [True: 0, False: 0]
  ------------------
 2389|      0|        loader_disable_dynamic_library_unloading = true;
 2390|      0|        loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: library unloading is disabled");
 2391|      2|    } else {
 2392|      2|        loader_disable_dynamic_library_unloading = false;
 2393|      2|    }
 2394|      2|    loader_free_getenv(loader_disable_dynamic_library_unloading_env_var, NULL);
 2395|       |#if defined(LOADER_USE_UNSAFE_FILE_SEARCH)
 2396|       |    loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: unsafe searching is enabled");
 2397|       |#endif
 2398|       |#if defined(_WIN32)
 2399|       |    return TRUE;
 2400|       |#endif
 2401|      2|}
loader_init_library:
 2438|      2|__attribute__((constructor)) void loader_init_library(void) { loader_initialize(); }
loader_get_next_path:
 2449|   271k|char *loader_get_next_path(char *path) {
 2450|   271k|    uint32_t len;
 2451|   271k|    char *next;
 2452|       |
 2453|   271k|    if (path == NULL) return NULL;
  ------------------
  |  Branch (2453:9): [True: 0, False: 271k]
  ------------------
 2454|   271k|    next = strchr(path, PATH_SEPARATOR);
  ------------------
  |  |  154|   271k|#define PATH_SEPARATOR ':'
  ------------------
 2455|   271k|    if (next == NULL) {
  ------------------
  |  Branch (2455:9): [True: 271k, False: 0]
  ------------------
 2456|   271k|        len = (uint32_t)strlen(path);
 2457|   271k|        next = path + len;
 2458|   271k|    } else {
 2459|      0|        *next = '\0';
 2460|      0|        next++;
 2461|      0|    }
 2462|       |
 2463|   271k|    return next;
 2464|   271k|}
combine_manifest_directory_and_library_path:
 2474|  1.94M|                                                     const char *manifest_file_path, char **out_fullpath) {
 2475|  1.94M|    assert(library_path && manifest_file_path && out_fullpath);
 2476|  1.94M|    if (loader_platform_is_path_absolute(library_path)) {
  ------------------
  |  Branch (2476:9): [True: 1.88M, False: 56.8k]
  ------------------
 2477|  1.88M|        *out_fullpath = library_path;
 2478|  1.88M|        return VK_SUCCESS;
 2479|  1.88M|    }
 2480|  56.8k|    VkResult res = VK_SUCCESS;
 2481|       |
 2482|  56.8k|    size_t library_path_len = strlen(library_path);
 2483|  56.8k|    size_t manifest_file_path_str_len = strlen(manifest_file_path);
 2484|  56.8k|    bool library_path_contains_directory_symbol = false;
 2485|  51.6M|    for (size_t i = 0; i < library_path_len; i++) {
  ------------------
  |  Branch (2485:24): [True: 51.5M, False: 12.7k]
  ------------------
 2486|  51.5M|        if (library_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  155|  51.5M|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2486:13): [True: 44.1k, False: 51.5M]
  ------------------
 2487|  44.1k|            library_path_contains_directory_symbol = true;
 2488|  44.1k|            break;
 2489|  44.1k|        }
 2490|  51.5M|    }
 2491|       |    // Means that the library_path is neither absolute nor relative - thus we should not modify it at all
 2492|  56.8k|    if (!library_path_contains_directory_symbol) {
  ------------------
  |  Branch (2492:9): [True: 12.7k, False: 44.1k]
  ------------------
 2493|  12.7k|        *out_fullpath = library_path;
 2494|  12.7k|        return VK_SUCCESS;
 2495|  12.7k|    }
 2496|       |    // must include both a directory symbol and the null terminator
 2497|  44.1k|    size_t new_str_len = library_path_len + manifest_file_path_str_len + 1 + 1;
 2498|       |
 2499|  44.1k|    *out_fullpath = loader_instance_heap_calloc(inst, new_str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 2500|  44.1k|    if (NULL == *out_fullpath) {
  ------------------
  |  Branch (2500:9): [True: 0, False: 44.1k]
  ------------------
 2501|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 2502|      0|        goto out;
 2503|      0|    }
 2504|  44.1k|    size_t cur_loc_in_out_fullpath = 0;
 2505|       |    // look for the last occurrence of DIRECTORY_SYMBOL in manifest_file_path
 2506|  44.1k|    size_t last_directory_symbol = 0;
 2507|  44.1k|    bool found_directory_symbol = false;
 2508|  1.57M|    for (size_t i = 0; i < manifest_file_path_str_len; i++) {
  ------------------
  |  Branch (2508:24): [True: 1.53M, False: 44.1k]
  ------------------
 2509|  1.53M|        if (manifest_file_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  155|  1.53M|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2509:13): [True: 153k, False: 1.38M]
  ------------------
 2510|   153k|            last_directory_symbol = i + 1;  // we want to include the symbol
 2511|   153k|            found_directory_symbol = true;
 2512|       |            // dont break because we want to find the last occurrence
 2513|   153k|        }
 2514|  1.53M|    }
 2515|       |    // Add manifest_file_path up to the last directory symbol
 2516|  44.1k|    if (found_directory_symbol) {
  ------------------
  |  Branch (2516:9): [True: 24.5k, False: 19.5k]
  ------------------
 2517|  24.5k|        loader_strncpy(*out_fullpath, new_str_len, manifest_file_path, last_directory_symbol);
 2518|  24.5k|        cur_loc_in_out_fullpath += last_directory_symbol;
 2519|  24.5k|    }
 2520|  44.1k|    loader_strncpy(&(*out_fullpath)[cur_loc_in_out_fullpath], new_str_len - cur_loc_in_out_fullpath, library_path,
 2521|  44.1k|                   library_path_len);
 2522|  44.1k|    cur_loc_in_out_fullpath += library_path_len + 1;
 2523|  44.1k|    (*out_fullpath)[cur_loc_in_out_fullpath] = '\0';
 2524|       |
 2525|  44.1k|out:
 2526|  44.1k|    loader_instance_heap_free(inst, library_path);
 2527|       |
 2528|  44.1k|    return res;
 2529|  44.1k|}
loader_get_fullpath:
 2535|   138k|void loader_get_fullpath(const char *file, const char *in_dirs, size_t out_size, char *out_fullpath) {
 2536|   138k|    if (!loader_platform_is_path(file) && *in_dirs) {
  ------------------
  |  Branch (2536:9): [True: 137k, False: 1.14k]
  |  Branch (2536:43): [True: 137k, False: 0]
  ------------------
 2537|   137k|        size_t dirs_copy_len = strlen(in_dirs) + 1;
 2538|   137k|        char *dirs_copy = loader_stack_alloc(dirs_copy_len);
  ------------------
  |  |   42|   137k|#define loader_stack_alloc(size) alloca(size)
  ------------------
 2539|   137k|        loader_strncpy(dirs_copy, dirs_copy_len, in_dirs, dirs_copy_len);
 2540|       |
 2541|       |        // find if file exists after prepending paths in given list
 2542|       |        // for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); dir = next_dir) {
 2543|   137k|        char *dir = dirs_copy;
 2544|   137k|        char *next_dir = loader_get_next_path(dir);
 2545|   139k|        while (*dir && next_dir && out_fullpath) {
  ------------------
  |  Branch (2545:16): [True: 137k, False: 2.69k]
  |  Branch (2545:24): [True: 137k, False: 0]
  |  Branch (2545:36): [True: 137k, False: 0]
  ------------------
 2546|   137k|            int path_concat_ret = snprintf(out_fullpath, out_size, "%s%c%s", dir, DIRECTORY_SYMBOL, file);
  ------------------
  |  |  155|   137k|#define DIRECTORY_SYMBOL '/'
  ------------------
 2547|   137k|            if (path_concat_ret >= 0 && loader_platform_file_exists(out_fullpath)) {
  ------------------
  |  Branch (2547:17): [True: 137k, False: 0]
  |  Branch (2547:41): [True: 134k, False: 2.69k]
  ------------------
 2548|   134k|                return;
 2549|   134k|            }
 2550|  2.69k|            dir = next_dir;
 2551|  2.69k|            next_dir = loader_get_next_path(dir);
 2552|  2.69k|        }
 2553|   137k|    }
 2554|       |
 2555|  3.83k|    (void)snprintf(out_fullpath, out_size, "%s", file);
 2556|  3.83k|}
verify_meta_layer_component_layers:
 2563|   413k|                                        struct loader_layer_list *instance_layers, bool *already_checked_meta_layers) {
 2564|   413k|    struct loader_layer_properties *prop = &instance_layers->list[prop_index];
 2565|   413k|    loader_api_version meta_layer_version = loader_make_version(prop->info.specVersion);
 2566|       |
 2567|   413k|    if (NULL == already_checked_meta_layers) {
  ------------------
  |  Branch (2567:9): [True: 400k, False: 13.4k]
  ------------------
 2568|   400k|        already_checked_meta_layers = loader_stack_alloc(sizeof(bool) * instance_layers->count);
  ------------------
  |  |   42|   400k|#define loader_stack_alloc(size) alloca(size)
  ------------------
 2569|   400k|        if (already_checked_meta_layers == NULL) {
  ------------------
  |  Branch (2569:13): [True: 0, False: 400k]
  ------------------
 2570|      0|            return false;
 2571|      0|        }
 2572|   400k|        memset(already_checked_meta_layers, 0, sizeof(bool) * instance_layers->count);
 2573|   400k|    }
 2574|       |
 2575|       |    // Mark this meta layer as 'already checked', indicating which layers have already been recursed.
 2576|   413k|    already_checked_meta_layers[prop_index] = true;
 2577|       |
 2578|   428k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2578:35): [True: 168k, False: 260k]
  ------------------
 2579|   168k|        struct loader_layer_properties *comp_prop =
 2580|   168k|            loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers);
 2581|   168k|        if (comp_prop == NULL) {
  ------------------
  |  Branch (2581:13): [True: 39.0k, False: 129k]
  ------------------
 2582|  39.0k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2583|  39.0k|                       "verify_meta_layer_component_layers: Meta-layer %s can't find component layer %s at index %d."
 2584|  39.0k|                       "  Skipping this layer.",
 2585|  39.0k|                       prop->info.layerName, prop->component_layer_names.list[comp_layer], comp_layer);
 2586|       |
 2587|  39.0k|            return false;
 2588|  39.0k|        }
 2589|       |
 2590|       |        // Check the version of each layer, they need to be at least MAJOR and MINOR
 2591|   129k|        loader_api_version comp_prop_version = loader_make_version(comp_prop->info.specVersion);
 2592|   129k|        if (!loader_check_version_meets_required(meta_layer_version, comp_prop_version)) {
  ------------------
  |  Branch (2592:13): [True: 108k, False: 21.2k]
  ------------------
 2593|   108k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2594|   108k|                       "verify_meta_layer_component_layers: Meta-layer uses API version %d.%d, but component "
 2595|   108k|                       "layer %d has API version %d.%d that is lower.  Skipping this layer.",
 2596|   108k|                       meta_layer_version.major, meta_layer_version.minor, comp_layer, comp_prop_version.major,
 2597|   108k|                       comp_prop_version.minor);
 2598|       |
 2599|   108k|            return false;
 2600|   108k|        }
 2601|       |
 2602|       |        // Make sure the layer isn't using it's own name
 2603|  21.2k|        if (!strcmp(prop->info.layerName, prop->component_layer_names.list[comp_layer])) {
  ------------------
  |  Branch (2603:13): [True: 3.46k, False: 17.8k]
  ------------------
 2604|  3.46k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2605|  3.46k|                       "verify_meta_layer_component_layers: Meta-layer %s lists itself in its component layer "
 2606|  3.46k|                       "list at index %d.  Skipping this layer.",
 2607|  3.46k|                       prop->info.layerName, comp_layer);
 2608|       |
 2609|  3.46k|            return false;
 2610|  3.46k|        }
 2611|  17.8k|        if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (2611:13): [True: 13.7k, False: 4.07k]
  ------------------
 2612|  13.7k|            size_t comp_prop_index = INT32_MAX;
 2613|       |            // Make sure we haven't verified this meta layer before
 2614|  61.0M|            for (uint32_t i = 0; i < instance_layers->count; i++) {
  ------------------
  |  Branch (2614:34): [True: 61.0M, False: 13.7k]
  ------------------
 2615|  61.0M|                if (strcmp(comp_prop->info.layerName, instance_layers->list[i].info.layerName) == 0) {
  ------------------
  |  Branch (2615:21): [True: 36.5M, False: 24.4M]
  ------------------
 2616|  36.5M|                    comp_prop_index = i;
 2617|  36.5M|                }
 2618|  61.0M|            }
 2619|  13.7k|            if (comp_prop_index != INT32_MAX && already_checked_meta_layers[comp_prop_index]) {
  ------------------
  |  Branch (2619:17): [True: 13.7k, False: 0]
  |  Branch (2619:49): [True: 278, False: 13.4k]
  ------------------
 2620|    278|                loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2621|    278|                           "verify_meta_layer_component_layers: Recursive dependency between Meta-layer %s and  Meta-layer %s.  "
 2622|    278|                           "Skipping this layer.",
 2623|    278|                           instance_layers->list[prop_index].info.layerName, comp_prop->info.layerName);
 2624|    278|                return false;
 2625|    278|            }
 2626|       |
 2627|  13.4k|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 2628|  13.4k|                       "verify_meta_layer_component_layers: Adding meta-layer %s which also contains meta-layer %s",
 2629|  13.4k|                       prop->info.layerName, comp_prop->info.layerName);
 2630|       |
 2631|       |            // Make sure if the layer is using a meta-layer in its component list that we also verify that.
 2632|  13.4k|            if (!verify_meta_layer_component_layers(inst, comp_prop_index, instance_layers, already_checked_meta_layers)) {
  ------------------
  |  Branch (2632:17): [True: 2.55k, False: 10.9k]
  ------------------
 2633|  2.55k|                loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2634|  2.55k|                           "Meta-layer %s component layer %s can not find all component layers."
 2635|  2.55k|                           "  Skipping this layer.",
 2636|  2.55k|                           prop->info.layerName, prop->component_layer_names.list[comp_layer]);
 2637|  2.55k|                return false;
 2638|  2.55k|            }
 2639|  13.4k|        }
 2640|  17.8k|    }
 2641|       |    // Didn't exit early so that means it passed all checks
 2642|   260k|    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2643|   260k|               "Meta-layer \"%s\" all %d component layers appear to be valid.", prop->info.layerName,
 2644|   260k|               prop->component_layer_names.count);
 2645|       |
 2646|       |    // If layer logging is on, list the internals included in the meta-layer
 2647|   275k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2647:35): [True: 14.9k, False: 260k]
  ------------------
 2648|  14.9k|        loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "  [%d] %s", comp_layer, prop->component_layer_names.list[comp_layer]);
 2649|  14.9k|    }
 2650|       |    return true;
 2651|   413k|}
update_meta_layer_extensions_from_component_layers:
 2657|   249k|                                                            struct loader_layer_list *instance_layers) {
 2658|   249k|    VkResult res = VK_SUCCESS;
 2659|   262k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2659:35): [True: 13.3k, False: 249k]
  ------------------
 2660|  13.3k|        struct loader_layer_properties *comp_prop =
 2661|  13.3k|            loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers);
 2662|       |
 2663|  13.3k|        if (NULL != comp_prop->instance_extension_list.list) {
  ------------------
  |  Branch (2663:13): [True: 747, False: 12.6k]
  ------------------
 2664|  16.1k|            for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) {
  ------------------
  |  Branch (2664:36): [True: 15.4k, False: 747]
  ------------------
 2665|  15.4k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding instance extension %s",
 2666|  15.4k|                           prop->info.layerName, prop->component_layer_names.list[comp_layer],
 2667|  15.4k|                           comp_prop->instance_extension_list.list[ext].extensionName);
 2668|       |
 2669|  15.4k|                if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) {
  ------------------
  |  Branch (2669:21): [True: 15.1k, False: 323]
  ------------------
 2670|  15.1k|                    res = loader_add_to_ext_list(inst, &prop->instance_extension_list, 1,
 2671|  15.1k|                                                 &comp_prop->instance_extension_list.list[ext]);
 2672|  15.1k|                    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2672:25): [True: 0, False: 15.1k]
  ------------------
 2673|      0|                        return res;
 2674|      0|                    }
 2675|  15.1k|                }
 2676|  15.4k|            }
 2677|    747|        }
 2678|  13.3k|        if (NULL != comp_prop->device_extension_list.list) {
  ------------------
  |  Branch (2678:13): [True: 4.17k, False: 9.21k]
  ------------------
 2679|  28.9k|            for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) {
  ------------------
  |  Branch (2679:36): [True: 24.7k, False: 4.17k]
  ------------------
 2680|  24.7k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding device extension %s",
 2681|  24.7k|                           prop->info.layerName, prop->component_layer_names.list[comp_layer],
 2682|  24.7k|                           comp_prop->device_extension_list.list[ext].props.extensionName);
 2683|       |
 2684|  24.7k|                if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) {
  ------------------
  |  Branch (2684:21): [True: 24.0k, False: 654]
  ------------------
 2685|  24.0k|                    res = loader_add_to_dev_ext_list(inst, &prop->device_extension_list,
 2686|  24.0k|                                                     &comp_prop->device_extension_list.list[ext].props, NULL);
 2687|  24.0k|                    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2687:25): [True: 0, False: 24.0k]
  ------------------
 2688|      0|                        return res;
 2689|      0|                    }
 2690|  24.0k|                }
 2691|  24.7k|            }
 2692|  4.17k|        }
 2693|  13.3k|    }
 2694|   249k|    return res;
 2695|   249k|}
verify_all_meta_layers:
 2699|  7.98k|                                struct loader_layer_list *instance_layers, bool *override_layer_present) {
 2700|  7.98k|    VkResult res = VK_SUCCESS;
 2701|  7.98k|    *override_layer_present = false;
 2702|  2.32M|    for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
  ------------------
  |  Branch (2702:25): [True: 2.31M, False: 7.98k]
  ------------------
 2703|  2.31M|        struct loader_layer_properties *prop = &instance_layers->list[i];
 2704|       |
 2705|       |        // If this is a meta-layer, make sure it is valid
 2706|  2.31M|        if (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (2706:13): [True: 400k, False: 1.91M]
  ------------------
 2707|   400k|            if (verify_meta_layer_component_layers(inst, i, instance_layers, NULL)) {
  ------------------
  |  Branch (2707:17): [True: 249k, False: 150k]
  ------------------
 2708|       |                // If any meta layer is valid, update its extension list to include the extensions from its component layers.
 2709|   249k|                res = update_meta_layer_extensions_from_component_layers(inst, prop, instance_layers);
 2710|   249k|                if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2710:21): [True: 0, False: 249k]
  ------------------
 2711|      0|                    return res;
 2712|      0|                }
 2713|   249k|                if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop)) {
  ------------------
  |  Branch (2713:21): [True: 2.88k, False: 246k]
  |  Branch (2713:42): [True: 2.86k, False: 19]
  ------------------
 2714|  2.86k|                    *override_layer_present = true;
 2715|  2.86k|                }
 2716|   249k|            } else {
 2717|   150k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
 2718|   150k|                           "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName);
 2719|       |
 2720|   150k|                loader_remove_layer_in_list(inst, instance_layers, i);
 2721|   150k|                i--;
 2722|   150k|            }
 2723|   400k|        }
 2724|  2.31M|    }
 2725|  7.98k|    return res;
 2726|  7.98k|}
remove_all_non_valid_override_layers:
 2730|  7.98k|void remove_all_non_valid_override_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
 2731|  7.98k|    if (instance_layers == NULL) {
  ------------------
  |  Branch (2731:9): [True: 0, False: 7.98k]
  ------------------
 2732|      0|        return;
 2733|      0|    }
 2734|       |
 2735|  7.98k|    char cur_path[1024];
 2736|  7.98k|    char *ret = loader_platform_executable_path(cur_path, 1024);
 2737|  7.98k|    if (NULL == ret) {
  ------------------
  |  Branch (2737:9): [True: 0, False: 7.98k]
  ------------------
 2738|      0|        return;
 2739|      0|    }
 2740|       |    // Find out if there is an override layer with same the app_key_path as the path to the current executable.
 2741|       |    // If more than one is found, remove it and use the first layer
 2742|       |    // Remove any layers which aren't global and do not have the same app_key_path as the path to the current executable.
 2743|  7.98k|    bool found_active_override_layer = false;
 2744|  7.98k|    int global_layer_index = -1;
 2745|   117k|    for (uint32_t i = 0; i < instance_layers->count; i++) {
  ------------------
  |  Branch (2745:26): [True: 109k, False: 7.98k]
  ------------------
 2746|   109k|        struct loader_layer_properties *props = &instance_layers->list[i];
 2747|   109k|        if (strcmp(props->info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) {
  ------------------
  |  |  142|   109k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (2747:13): [True: 2.64k, False: 106k]
  ------------------
 2748|  2.64k|            if (props->app_key_paths.count > 0) {  // not the global layer
  ------------------
  |  Branch (2748:17): [True: 807, False: 1.83k]
  ------------------
 2749|  55.6k|                for (uint32_t j = 0; j < props->app_key_paths.count; j++) {
  ------------------
  |  Branch (2749:38): [True: 54.8k, False: 807]
  ------------------
 2750|  54.8k|                    if (strcmp(props->app_key_paths.list[j], cur_path) == 0) {
  ------------------
  |  Branch (2750:25): [True: 0, False: 54.8k]
  ------------------
 2751|      0|                        if (!found_active_override_layer) {
  ------------------
  |  Branch (2751:29): [True: 0, False: 0]
  ------------------
 2752|      0|                            found_active_override_layer = true;
 2753|      0|                        } else {
 2754|      0|                            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2755|      0|                                       "remove_all_non_valid_override_layers: Multiple override layers where the same path in "
 2756|      0|                                       "app_keys "
 2757|      0|                                       "was found. Using the first layer found");
 2758|       |
 2759|       |                            // Remove duplicate active override layers that have the same app_key_path
 2760|      0|                            loader_remove_layer_in_list(inst, instance_layers, i);
 2761|      0|                            i--;
 2762|      0|                        }
 2763|      0|                    }
 2764|  54.8k|                }
 2765|    807|                if (!found_active_override_layer) {
  ------------------
  |  Branch (2765:21): [True: 807, False: 0]
  ------------------
 2766|    807|                    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2767|    807|                               "--Override layer found but not used because app \'%s\' is not in \'app_keys\' list!", cur_path);
 2768|       |
 2769|       |                    // Remove non-global override layers that don't have an app_key that matches cur_path
 2770|    807|                    loader_remove_layer_in_list(inst, instance_layers, i);
 2771|    807|                    i--;
 2772|    807|                }
 2773|  1.83k|            } else {
 2774|  1.83k|                if (global_layer_index == -1) {
  ------------------
  |  Branch (2774:21): [True: 1.51k, False: 323]
  ------------------
 2775|  1.51k|                    global_layer_index = (int)i;
 2776|  1.51k|                } else {
 2777|    323|                    loader_log(
 2778|    323|                        inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2779|    323|                        "remove_all_non_valid_override_layers: Multiple global override layers found. Using the first global "
 2780|    323|                        "layer found");
 2781|    323|                    loader_remove_layer_in_list(inst, instance_layers, i);
 2782|    323|                    i--;
 2783|    323|                }
 2784|  1.83k|            }
 2785|  2.64k|        }
 2786|   109k|    }
 2787|       |    // Remove global layer if layer with same the app_key_path as the path to the current executable is found
 2788|  7.98k|    if (found_active_override_layer && global_layer_index >= 0) {
  ------------------
  |  Branch (2788:9): [True: 0, False: 7.98k]
  |  Branch (2788:40): [True: 0, False: 0]
  ------------------
 2789|      0|        loader_remove_layer_in_list(inst, instance_layers, global_layer_index);
 2790|      0|    }
 2791|       |    // Should be at most 1 override layer in the list now.
 2792|  7.98k|    if (found_active_override_layer) {
  ------------------
  |  Branch (2792:9): [True: 0, False: 7.98k]
  ------------------
 2793|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the override layer for app key %s", cur_path);
 2794|  7.98k|    } else if (global_layer_index >= 0) {
  ------------------
  |  Branch (2794:16): [True: 1.51k, False: 6.47k]
  ------------------
 2795|  1.51k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the global override layer");
 2796|  1.51k|    }
 2797|  7.98k|}
loader_read_layer_json:
 2811|  4.99M|                                cJSON *layer_node, loader_api_version version, bool is_implicit, char *filename) {
 2812|  4.99M|    assert(layer_instance_list);
 2813|  4.99M|    char *library_path = NULL;
 2814|  4.99M|    VkResult result = VK_SUCCESS;
 2815|  4.99M|    struct loader_layer_properties props = {0};
 2816|       |
 2817|  4.99M|    result = loader_copy_to_new_str(inst, filename, &props.manifest_file_name);
 2818|  4.99M|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2818:9): [True: 0, False: 4.99M]
  ------------------
 2819|      0|        goto out;
 2820|      0|    }
 2821|       |
 2822|       |    // Parse name
 2823|       |
 2824|  4.99M|    result = loader_parse_json_string_to_existing_str(layer_node, "name", VK_MAX_EXTENSION_NAME_SIZE, props.info.layerName);
 2825|  4.99M|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2825:9): [True: 419k, False: 4.57M]
  ------------------
 2826|   419k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2827|   419k|                   "Layer located at %s didn't find required layer value \"name\" in manifest JSON file, skipping this layer",
 2828|   419k|                   filename);
 2829|   419k|        goto out;
 2830|   419k|    }
 2831|       |
 2832|       |    // Check if this layer's name matches the override layer name, set is_override to true if so.
 2833|  4.57M|    if (!strcmp(props.info.layerName, VK_OVERRIDE_LAYER_NAME)) {
  ------------------
  |  |  142|  4.57M|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (2833:9): [True: 5.53k, False: 4.56M]
  ------------------
 2834|  5.53k|        props.is_override = true;
 2835|  5.53k|    }
 2836|       |
 2837|  4.57M|    if (0 != strncmp(props.info.layerName, "VK_LAYER_", 9)) {
  ------------------
  |  Branch (2837:9): [True: 4.56M, False: 11.4k]
  ------------------
 2838|  4.56M|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Layer name %s does not conform to naming standard (Policy #LLP_LAYER_3)",
 2839|  4.56M|                   props.info.layerName);
 2840|  4.56M|    }
 2841|       |
 2842|       |    // Parse type
 2843|  4.57M|    char *type = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "type"));
 2844|  4.57M|    if (NULL == type) {
  ------------------
  |  Branch (2844:9): [True: 1.10M, False: 3.46M]
  ------------------
 2845|  1.10M|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2846|  1.10M|                   "Layer located at %s didn't find required layer value \"type\" in manifest JSON file, skipping this layer",
 2847|  1.10M|                   filename);
 2848|  1.10M|        result = VK_ERROR_INITIALIZATION_FAILED;
 2849|  1.10M|        goto out;
 2850|  1.10M|    }
 2851|       |
 2852|       |    // Add list entry
 2853|  3.46M|    if (!strcmp(type, "DEVICE")) {
  ------------------
  |  Branch (2853:9): [True: 199, False: 3.46M]
  ------------------
 2854|    199|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Device layers are deprecated. Skipping layer %s",
 2855|    199|                   props.info.layerName);
 2856|    199|        result = VK_ERROR_INITIALIZATION_FAILED;
 2857|    199|        goto out;
 2858|    199|    }
 2859|       |
 2860|       |    // Allow either GLOBAL or INSTANCE type interchangeably to handle layers that must work with older loaders
 2861|  3.46M|    if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
  ------------------
  |  Branch (2861:9): [True: 3.09M, False: 370k]
  |  Branch (2861:38): [True: 178k, False: 191k]
  ------------------
 2862|  3.27M|        props.type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER;
 2863|  3.27M|        if (!is_implicit) {
  ------------------
  |  Branch (2863:13): [True: 3.14M, False: 128k]
  ------------------
 2864|  3.14M|            props.type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER;
 2865|  3.14M|        }
 2866|  3.27M|    } else {
 2867|   191k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2868|   191k|        goto out;
 2869|   191k|    }
 2870|       |
 2871|       |    // Parse api_version
 2872|  3.27M|    char *api_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "api_version"));
 2873|  3.27M|    if (NULL == api_version) {
  ------------------
  |  Branch (2873:9): [True: 283k, False: 2.99M]
  ------------------
 2874|   283k|        loader_log(
 2875|   283k|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2876|   283k|            "Layer located at %s didn't find required layer value \"api_version\" in manifest JSON file, skipping this layer",
 2877|   283k|            filename);
 2878|   283k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2879|   283k|        goto out;
 2880|   283k|    }
 2881|       |
 2882|  2.99M|    props.info.specVersion = loader_parse_version_string(api_version);
 2883|       |
 2884|       |    // Make sure the layer's manifest doesn't contain a non zero variant value
 2885|  2.99M|    if (VK_API_VERSION_VARIANT(props.info.specVersion) != 0) {
  ------------------
  |  Branch (2885:9): [True: 24.1k, False: 2.96M]
  ------------------
 2886|  24.1k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2887|  24.1k|                   "Layer \"%s\" has an \'api_version\' field which contains a non-zero variant value of %d. "
 2888|  24.1k|                   " Skipping Layer.",
 2889|  24.1k|                   props.info.layerName, VK_API_VERSION_VARIANT(props.info.specVersion));
 2890|  24.1k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2891|  24.1k|        goto out;
 2892|  24.1k|    }
 2893|       |
 2894|       |    // Parse implementation_version
 2895|  2.96M|    char *implementation_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "implementation_version"));
 2896|  2.96M|    if (NULL == implementation_version) {
  ------------------
  |  Branch (2896:9): [True: 325k, False: 2.64M]
  ------------------
 2897|   325k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2898|   325k|                   "Layer located at %s didn't find required layer value \"implementation_version\" in manifest JSON file, "
 2899|   325k|                   "skipping this layer",
 2900|   325k|                   filename);
 2901|   325k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2902|   325k|        goto out;
 2903|   325k|    }
 2904|  2.64M|    props.info.implementationVersion = (uint32_t)strtoul(implementation_version, NULL, 10);
 2905|       |
 2906|       |    // Parse description
 2907|       |
 2908|  2.64M|    result = loader_parse_json_string_to_existing_str(layer_node, "description", VK_MAX_DESCRIPTION_SIZE, props.info.description);
 2909|  2.64M|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2909:9): [True: 229k, False: 2.41M]
  ------------------
 2910|   229k|        loader_log(
 2911|   229k|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2912|   229k|            "Layer located at %s didn't find required layer value \"description\" in manifest JSON file, skipping this layer",
 2913|   229k|            filename);
 2914|   229k|        goto out;
 2915|   229k|    }
 2916|       |
 2917|       |    // Parse library_path
 2918|       |
 2919|       |    // Library path no longer required unless component_layers is also not defined
 2920|  2.41M|    result = loader_parse_json_string(layer_node, "library_path", &library_path);
 2921|  2.41M|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2921:9): [True: 0, False: 2.41M]
  ------------------
 2922|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2923|      0|                   "Skipping layer \"%s\" due to problem accessing the library_path value in the manifest JSON file",
 2924|      0|                   props.info.layerName);
 2925|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
 2926|      0|        goto out;
 2927|      0|    }
 2928|  2.41M|    if (NULL != library_path) {
  ------------------
  |  Branch (2928:9): [True: 1.94M, False: 469k]
  ------------------
 2929|  1.94M|        if (NULL != loader_cJSON_GetObjectItem(layer_node, "component_layers")) {
  ------------------
  |  Branch (2929:13): [True: 2.00k, False: 1.94M]
  ------------------
 2930|  2.00k|            loader_log(
 2931|  2.00k|                inst, VULKAN_LOADER_WARN_BIT, 0,
 2932|  2.00k|                "Layer \"%s\" contains meta-layer-specific component_layers, but also defining layer library path.  Both are not "
 2933|  2.00k|                "compatible, so skipping this layer",
 2934|  2.00k|                props.info.layerName);
 2935|  2.00k|            result = VK_ERROR_INITIALIZATION_FAILED;
 2936|  2.00k|            loader_instance_heap_free(inst, library_path);
 2937|  2.00k|            goto out;
 2938|  2.00k|        }
 2939|       |
 2940|       |        // This function takes ownership of library_path_str - so we don't need to clean it up
 2941|  1.94M|        result = combine_manifest_directory_and_library_path(inst, library_path, filename, &props.lib_name);
 2942|  1.94M|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2942:13): [True: 0, False: 1.94M]
  ------------------
 2943|  1.94M|    }
 2944|       |
 2945|       |    // Parse component_layers
 2946|       |
 2947|  2.41M|    if (NULL == library_path) {
  ------------------
  |  Branch (2947:9): [True: 469k, False: 1.94M]
  ------------------
 2948|   469k|        if (!loader_check_version_meets_required(LOADER_VERSION_1_1_0, version)) {
  ------------------
  |  |  270|   469k|#define LOADER_VERSION_1_1_0 loader_combine_version(1, 1, 0)
  ------------------
  |  Branch (2948:13): [True: 172k, False: 297k]
  ------------------
 2949|   172k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2950|   172k|                       "Layer \"%s\" contains meta-layer-specific component_layers, but using older JSON file version.",
 2951|   172k|                       props.info.layerName);
 2952|   172k|        }
 2953|       |
 2954|   469k|        result = loader_parse_json_array_of_strings(inst, layer_node, "component_layers", &(props.component_layer_names));
 2955|   469k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2955:13): [True: 0, False: 469k]
  ------------------
 2956|      0|            goto out;
 2957|      0|        }
 2958|   469k|        if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2958:13): [True: 62.9k, False: 406k]
  ------------------
 2959|  62.9k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2960|  62.9k|                       "Layer \"%s\" is missing both library_path and component_layers fields.  One or the other MUST be defined.  "
 2961|  62.9k|                       "Skipping this layer",
 2962|  62.9k|                       props.info.layerName);
 2963|  62.9k|            goto out;
 2964|  62.9k|        }
 2965|       |        // This is now, officially, a meta-layer
 2966|   406k|        props.type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
 2967|   406k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Encountered meta-layer \"%s\"",
 2968|   406k|                   props.info.layerName);
 2969|   406k|    }
 2970|       |
 2971|       |    // Parse blacklisted_layers
 2972|       |
 2973|  2.34M|    if (props.is_override) {
  ------------------
  |  Branch (2973:9): [True: 4.79k, False: 2.34M]
  ------------------
 2974|  4.79k|        result = loader_parse_json_array_of_strings(inst, layer_node, "blacklisted_layers", &(props.blacklist_layer_names));
 2975|  4.79k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2975:13): [True: 0, False: 4.79k]
  ------------------
 2976|      0|            goto out;
 2977|      0|        }
 2978|  4.79k|    }
 2979|       |
 2980|       |    // Parse override_paths
 2981|       |
 2982|  2.34M|    result = loader_parse_json_array_of_strings(inst, layer_node, "override_paths", &(props.override_paths));
 2983|  2.34M|    if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2983:9): [True: 0, False: 2.34M]
  ------------------
 2984|      0|        goto out;
 2985|      0|    }
 2986|  2.34M|    if (NULL != props.override_paths.list && !loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2986:9): [True: 3.79k, False: 2.34M]
  |  Branch (2986:46): [True: 2.25k, False: 1.54k]
  ------------------
 2987|  2.25k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2988|  2.25k|                   "Layer \"%s\" contains meta-layer-specific override paths, but using older JSON file version.",
 2989|  2.25k|                   props.info.layerName);
 2990|  2.25k|    }
 2991|       |
 2992|       |    // Parse disable_environment
 2993|       |
 2994|  2.34M|    if (is_implicit) {
  ------------------
  |  Branch (2994:9): [True: 115k, False: 2.23M]
  ------------------
 2995|   115k|        cJSON *disable_environment = loader_cJSON_GetObjectItem(layer_node, "disable_environment");
 2996|   115k|        if (disable_environment == NULL) {
  ------------------
  |  Branch (2996:13): [True: 5.72k, False: 110k]
  ------------------
 2997|  5.72k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2998|  5.72k|                       "Layer \"%s\" doesn't contain required layer object disable_environment in the manifest JSON file, skipping "
 2999|  5.72k|                       "this layer",
 3000|  5.72k|                       props.info.layerName);
 3001|  5.72k|            result = VK_ERROR_INITIALIZATION_FAILED;
 3002|  5.72k|            goto out;
 3003|  5.72k|        }
 3004|       |
 3005|   110k|        if (!disable_environment->child || disable_environment->child->type != cJSON_String ||
  ------------------
  |  |  101|   220k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (3005:13): [True: 362, False: 109k]
  |  Branch (3005:44): [True: 199, False: 109k]
  ------------------
 3006|   109k|            !disable_environment->child->string || !disable_environment->child->valuestring) {
  ------------------
  |  Branch (3006:13): [True: 199, False: 109k]
  |  Branch (3006:52): [True: 0, False: 109k]
  ------------------
 3007|    760|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 3008|    760|                       "Layer \"%s\" doesn't contain required child value in object disable_environment in the manifest JSON file, "
 3009|    760|                       "skipping this layer (Policy #LLP_LAYER_9)",
 3010|    760|                       props.info.layerName);
 3011|    760|            result = VK_ERROR_INITIALIZATION_FAILED;
 3012|    760|            goto out;
 3013|    760|        }
 3014|   109k|        result = loader_copy_to_new_str(inst, disable_environment->child->string, &(props.disable_env_var.name));
 3015|   109k|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3015:13): [True: 0, False: 109k]
  ------------------
 3016|   109k|        result = loader_copy_to_new_str(inst, disable_environment->child->valuestring, &(props.disable_env_var.value));
 3017|   109k|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3017:13): [True: 0, False: 109k]
  ------------------
 3018|   109k|    }
 3019|       |
 3020|       |    // Now get all optional items and objects and put in list:
 3021|       |    // functions
 3022|       |    // instance_extensions
 3023|       |    // device_extensions
 3024|       |    // enable_environment (implicit layers only)
 3025|       |    // library_arch
 3026|       |
 3027|       |    // Layer interface functions
 3028|       |    //    vkGetInstanceProcAddr
 3029|       |    //    vkGetDeviceProcAddr
 3030|       |    //    vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
 3031|  2.34M|    cJSON *functions = loader_cJSON_GetObjectItem(layer_node, "functions");
 3032|  2.34M|    if (functions != NULL) {
  ------------------
  |  Branch (3032:9): [True: 7.39k, False: 2.33M]
  ------------------
 3033|  7.39k|        if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (3033:13): [True: 5.09k, False: 2.30k]
  ------------------
 3034|  5.09k|            result = loader_parse_json_string(functions, "vkNegotiateLoaderLayerInterfaceVersion",
 3035|  5.09k|                                              &props.functions.str_negotiate_interface);
 3036|  5.09k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3036:17): [True: 0, False: 5.09k]
  ------------------
 3037|  5.09k|        }
 3038|  7.39k|        result = loader_parse_json_string(functions, "vkGetInstanceProcAddr", &props.functions.str_gipa);
 3039|  7.39k|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3039:13): [True: 0, False: 7.39k]
  ------------------
 3040|       |
 3041|  7.39k|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gipa &&
  ------------------
  |  Branch (3041:13): [True: 7.39k, False: 0]
  |  Branch (3041:64): [True: 0, False: 7.39k]
  ------------------
 3042|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (3042:13): [True: 0, False: 0]
  ------------------
 3043|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3044|      0|                       "Layer \"%s\" using deprecated \'vkGetInstanceProcAddr\' tag which was deprecated starting with JSON "
 3045|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 3046|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 3047|      0|                       props.info.layerName);
 3048|      0|        }
 3049|       |
 3050|  7.39k|        result = loader_parse_json_string(functions, "vkGetDeviceProcAddr", &props.functions.str_gdpa);
 3051|  7.39k|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3051:13): [True: 0, False: 7.39k]
  ------------------
 3052|       |
 3053|  7.39k|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gdpa &&
  ------------------
  |  Branch (3053:13): [True: 7.39k, False: 0]
  |  Branch (3053:64): [True: 0, False: 7.39k]
  ------------------
 3054|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (3054:13): [True: 0, False: 0]
  ------------------
 3055|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3056|      0|                       "Layer \"%s\" using deprecated \'vkGetDeviceProcAddr\' tag which was deprecated starting with JSON "
 3057|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 3058|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 3059|      0|                       props.info.layerName);
 3060|      0|        }
 3061|  7.39k|    }
 3062|       |
 3063|       |    // instance_extensions
 3064|       |    //   array of {
 3065|       |    //     name
 3066|       |    //     spec_version
 3067|       |    //   }
 3068|       |
 3069|  2.34M|    cJSON *instance_extensions = loader_cJSON_GetObjectItem(layer_node, "instance_extensions");
 3070|  2.34M|    if (instance_extensions != NULL && instance_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|  6.98k|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3070:9): [True: 6.98k, False: 2.33M]
  |  Branch (3070:40): [True: 6.78k, False: 195]
  ------------------
 3071|  6.78k|        cJSON *ext_item = NULL;
 3072|   509k|        cJSON_ArrayForEach(ext_item, instance_extensions) {
  ------------------
  |  |  213|   516k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 6.78k, False: 0]
  |  |  |  Branch (213:61): [True: 509k, False: 6.78k]
  |  |  ------------------
  ------------------
 3073|   509k|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|   509k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3073:17): [True: 11.5k, False: 497k]
  ------------------
 3074|  11.5k|                continue;
 3075|  11.5k|            }
 3076|       |
 3077|   497k|            VkExtensionProperties ext_prop = {0};
 3078|   497k|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3079|   497k|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3079:17): [True: 186k, False: 310k]
  ------------------
 3080|   186k|                continue;
 3081|   186k|            }
 3082|   310k|            char *spec_version = NULL;
 3083|   310k|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3084|   310k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3084:17): [True: 0, False: 310k]
  ------------------
 3085|   310k|            if (NULL != spec_version) {
  ------------------
  |  Branch (3085:17): [True: 241, False: 310k]
  ------------------
 3086|    241|                ext_prop.specVersion = (uint32_t)strtoul(spec_version, NULL, 10);
 3087|    241|            }
 3088|   310k|            loader_instance_heap_free(inst, spec_version);
 3089|   310k|            bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop);
 3090|   310k|            if (!ext_unsupported) {
  ------------------
  |  Branch (3090:17): [True: 310k, False: 456]
  ------------------
 3091|   310k|                result = loader_add_to_ext_list(inst, &props.instance_extension_list, 1, &ext_prop);
 3092|   310k|                if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3092:21): [True: 0, False: 310k]
  ------------------
 3093|   310k|            }
 3094|   310k|        }
 3095|  6.78k|    }
 3096|       |
 3097|       |    // device_extensions
 3098|       |    //   array of {
 3099|       |    //     name
 3100|       |    //     spec_version
 3101|       |    //     entrypoints
 3102|       |    //   }
 3103|  2.34M|    cJSON *device_extensions = loader_cJSON_GetObjectItem(layer_node, "device_extensions");
 3104|  2.34M|    if (device_extensions != NULL && device_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|   110k|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3104:9): [True: 110k, False: 2.23M]
  |  Branch (3104:38): [True: 85.9k, False: 24.1k]
  ------------------
 3105|  85.9k|        cJSON *ext_item = NULL;
 3106|  85.9k|        cJSON_ArrayForEach(ext_item, device_extensions) {
  ------------------
  |  |  213|   121k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 85.9k, False: 0]
  |  |  |  Branch (213:61): [True: 35.5k, False: 85.9k]
  |  |  ------------------
  ------------------
 3107|  35.5k|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|  35.5k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3107:17): [True: 434, False: 35.0k]
  ------------------
 3108|    434|                continue;
 3109|    434|            }
 3110|       |
 3111|  35.0k|            VkExtensionProperties ext_prop = {0};
 3112|  35.0k|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3113|  35.0k|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3113:17): [True: 6.82k, False: 28.2k]
  ------------------
 3114|  6.82k|                continue;
 3115|  6.82k|            }
 3116|       |
 3117|  28.2k|            char *spec_version = NULL;
 3118|  28.2k|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3119|  28.2k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3119:17): [True: 0, False: 28.2k]
  ------------------
 3120|  28.2k|            if (NULL != spec_version) {
  ------------------
  |  Branch (3120:17): [True: 237, False: 28.0k]
  ------------------
 3121|    237|                ext_prop.specVersion = (uint32_t)strtoul(spec_version, NULL, 10);
 3122|    237|            }
 3123|  28.2k|            loader_instance_heap_free(inst, spec_version);
 3124|       |
 3125|  28.2k|            cJSON *entrypoints = loader_cJSON_GetObjectItem(ext_item, "entrypoints");
 3126|  28.2k|            if (entrypoints == NULL) {
  ------------------
  |  Branch (3126:17): [True: 24.6k, False: 3.62k]
  ------------------
 3127|  24.6k|                result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, NULL);
 3128|  24.6k|                if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3128:21): [True: 0, False: 24.6k]
  ------------------
 3129|  24.6k|                continue;
 3130|  24.6k|            }
 3131|       |
 3132|  3.62k|            struct loader_string_list entrys = {0};
 3133|  3.62k|            result = loader_parse_json_array_of_strings(inst, ext_item, "entrypoints", &entrys);
 3134|  3.62k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3134:17): [True: 0, False: 3.62k]
  ------------------
 3135|  3.62k|            result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, &entrys);
 3136|  3.62k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3136:17): [True: 0, False: 3.62k]
  ------------------
 3137|  3.62k|        }
 3138|  85.9k|    }
 3139|  2.34M|    if (is_implicit) {
  ------------------
  |  Branch (3139:9): [True: 109k, False: 2.23M]
  ------------------
 3140|   109k|        cJSON *enable_environment = loader_cJSON_GetObjectItem(layer_node, "enable_environment");
 3141|       |
 3142|       |        // enable_environment is optional
 3143|   109k|        if (enable_environment && enable_environment->child && enable_environment->child->type == cJSON_String &&
  ------------------
  |  |  101|   110k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (3143:13): [True: 1.27k, False: 108k]
  |  Branch (3143:35): [True: 1.06k, False: 212]
  |  Branch (3143:64): [True: 867, False: 195]
  ------------------
 3144|    867|            enable_environment->child->string && enable_environment->child->valuestring) {
  ------------------
  |  Branch (3144:13): [True: 665, False: 202]
  |  Branch (3144:50): [True: 665, False: 0]
  ------------------
 3145|    665|            result = loader_copy_to_new_str(inst, enable_environment->child->string, &(props.enable_env_var.name));
 3146|    665|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3146:17): [True: 0, False: 665]
  ------------------
 3147|    665|            result = loader_copy_to_new_str(inst, enable_environment->child->valuestring, &(props.enable_env_var.value));
 3148|    665|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3148:17): [True: 0, False: 665]
  ------------------
 3149|    665|        }
 3150|   109k|    }
 3151|       |
 3152|       |    // Read in the pre-instance stuff
 3153|  2.34M|    cJSON *pre_instance = loader_cJSON_GetObjectItem(layer_node, "pre_instance_functions");
 3154|  2.34M|    if (NULL != pre_instance) {
  ------------------
  |  Branch (3154:9): [True: 135k, False: 2.20M]
  ------------------
 3155|       |        // Supported versions started in 1.1.2, so anything newer
 3156|   135k|        if (!loader_check_version_meets_required(loader_combine_version(1, 1, 2), version)) {
  ------------------
  |  Branch (3156:13): [True: 15.5k, False: 120k]
  ------------------
 3157|  15.5k|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3158|  15.5k|                       "Found pre_instance_functions section in layer from \"%s\". This section is only valid in manifest version "
 3159|  15.5k|                       "1.1.2 or later. The section will be ignored",
 3160|  15.5k|                       filename);
 3161|   120k|        } else if (!is_implicit) {
  ------------------
  |  Branch (3161:20): [True: 60.0k, False: 59.9k]
  ------------------
 3162|  60.0k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 3163|  60.0k|                       "Found pre_instance_functions section in explicit layer from \"%s\". This section is only valid in implicit "
 3164|  60.0k|                       "layers. The section will be ignored",
 3165|  60.0k|                       filename);
 3166|  60.0k|        } else {
 3167|  59.9k|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceExtensionProperties",
 3168|  59.9k|                                              &props.pre_instance_functions.enumerate_instance_extension_properties);
 3169|  59.9k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3169:17): [True: 0, False: 59.9k]
  ------------------
 3170|       |
 3171|  59.9k|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceLayerProperties",
 3172|  59.9k|                                              &props.pre_instance_functions.enumerate_instance_layer_properties);
 3173|  59.9k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3173:17): [True: 0, False: 59.9k]
  ------------------
 3174|       |
 3175|  59.9k|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceVersion",
 3176|  59.9k|                                              &props.pre_instance_functions.enumerate_instance_version);
 3177|  59.9k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3177:17): [True: 0, False: 59.9k]
  ------------------
 3178|  59.9k|        }
 3179|   135k|    }
 3180|       |
 3181|  2.34M|    if (loader_cJSON_GetObjectItem(layer_node, "app_keys")) {
  ------------------
  |  Branch (3181:9): [True: 21.7k, False: 2.32M]
  ------------------
 3182|  21.7k|        if (!props.is_override) {
  ------------------
  |  Branch (3182:13): [True: 20.7k, False: 972]
  ------------------
 3183|  20.7k|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3184|  20.7k|                       "Layer %s contains app_keys, but any app_keys can only be provided by the override meta layer. "
 3185|  20.7k|                       "These will be ignored.",
 3186|  20.7k|                       props.info.layerName);
 3187|  20.7k|        }
 3188|       |
 3189|  21.7k|        result = loader_parse_json_array_of_strings(inst, layer_node, "app_keys", &props.app_key_paths);
 3190|  21.7k|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3190:13): [True: 0, False: 21.7k]
  ------------------
 3191|  21.7k|    }
 3192|       |
 3193|  2.34M|    char *library_arch = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "library_arch"));
 3194|  2.34M|    if (NULL != library_arch) {
  ------------------
  |  Branch (3194:9): [True: 1.37k, False: 2.34M]
  ------------------
 3195|  1.37k|        if ((strncmp(library_arch, "32", 2) == 0 && sizeof(void *) != 4) ||
  ------------------
  |  Branch (3195:14): [True: 986, False: 389]
  |  Branch (3195:53): [True: 0, Folded]
  ------------------
 3196|    986|            (strncmp(library_arch, "64", 2) == 0 && sizeof(void *) != 8)) {
  ------------------
  |  Branch (3196:14): [True: 0, False: 389]
  |  Branch (3196:53): [Folded, False: 0]
  ------------------
 3197|    986|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3198|    986|                       "The library architecture in layer %s doesn't match the current running architecture, skipping this layer",
 3199|    986|                       filename);
 3200|    986|            result = VK_ERROR_INITIALIZATION_FAILED;
 3201|    986|            goto out;
 3202|    986|        }
 3203|  1.37k|    }
 3204|       |
 3205|  2.34M|    result = VK_SUCCESS;
 3206|       |
 3207|  4.99M|out:
 3208|       |    // Try to append the layer property
 3209|  4.99M|    if (VK_SUCCESS == result) {
  ------------------
  |  Branch (3209:9): [True: 2.34M, False: 2.65M]
  ------------------
 3210|  2.34M|        result = loader_append_layer_property(inst, layer_instance_list, &props);
 3211|  2.34M|    }
 3212|       |    // If appending fails - free all the memory allocated in it
 3213|  4.99M|    if (VK_SUCCESS != result) {
  ------------------
  |  Branch (3213:9): [True: 2.65M, False: 2.34M]
  ------------------
 3214|  2.65M|        loader_free_layer_properties(inst, &props);
 3215|  2.65M|    }
 3216|  4.99M|    return result;
 3217|  2.34M|}
is_valid_layer_json_version:
 3219|  69.7k|bool is_valid_layer_json_version(const loader_api_version *layer_json) {
 3220|       |    // Supported versions are: 1.0.0, 1.0.1, 1.1.0 - 1.1.2, and 1.2.0 - 1.2.1.
 3221|  69.7k|    if ((layer_json->major == 1 && layer_json->minor == 2 && layer_json->patch < 2) ||
  ------------------
  |  Branch (3221:10): [True: 25.6k, False: 44.1k]
  |  Branch (3221:36): [True: 3.42k, False: 22.2k]
  |  Branch (3221:62): [True: 3.17k, False: 258]
  ------------------
 3222|  66.6k|        (layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) ||
  ------------------
  |  Branch (3222:10): [True: 22.4k, False: 44.1k]
  |  Branch (3222:36): [True: 1.19k, False: 21.2k]
  |  Branch (3222:62): [True: 1.06k, False: 130]
  ------------------
 3223|  65.5k|        (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
  ------------------
  |  Branch (3223:10): [True: 21.4k, False: 44.1k]
  |  Branch (3223:36): [True: 18.0k, False: 3.42k]
  |  Branch (3223:62): [True: 17.2k, False: 726]
  ------------------
 3224|  21.5k|        return true;
 3225|  21.5k|    }
 3226|  48.2k|    return false;
 3227|  69.7k|}
loader_add_layer_properties:
 3239|  73.7k|                                     bool is_implicit, char *filename) {
 3240|       |    // The following Fields in layer manifest file that are required:
 3241|       |    //   - "file_format_version"
 3242|       |    //   - If more than one "layer" object are used, then the "layers" array is
 3243|       |    //     required
 3244|  73.7k|    VkResult result = VK_ERROR_INITIALIZATION_FAILED;
 3245|       |    // Make sure sure the top level json value is an object
 3246|  73.7k|    if (!json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  73.7k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3246:9): [True: 0, False: 73.7k]
  |  Branch (3246:18): [True: 3.92k, False: 69.8k]
  ------------------
 3247|  3.92k|        goto out;
 3248|  3.92k|    }
 3249|  69.8k|    char *file_vers = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(json, "file_format_version"));
 3250|  69.8k|    if (NULL == file_vers) {
  ------------------
  |  Branch (3250:9): [True: 17, False: 69.7k]
  ------------------
 3251|     17|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3252|     17|                   "loader_add_layer_properties: Manifest %s missing required field file_format_version", filename);
 3253|     17|        goto out;
 3254|     17|    }
 3255|       |
 3256|  69.7k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Found manifest file %s (file version %s)", filename, file_vers);
 3257|       |    // Get the major/minor/and patch as integers for easier comparison
 3258|  69.7k|    loader_api_version json_version = loader_make_full_version(loader_parse_version_string(file_vers));
 3259|       |
 3260|  69.7k|    if (!is_valid_layer_json_version(&json_version)) {
  ------------------
  |  Branch (3260:9): [True: 48.2k, False: 21.5k]
  ------------------
 3261|  48.2k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3262|  48.2k|                   "loader_add_layer_properties: %s has unknown layer manifest file version %d.%d.%d.  May cause errors.", filename,
 3263|  48.2k|                   json_version.major, json_version.minor, json_version.patch);
 3264|  48.2k|    }
 3265|       |
 3266|       |    // If "layers" is present, read in the array of layer objects
 3267|  69.7k|    cJSON *layers_node = loader_cJSON_GetObjectItem(json, "layers");
 3268|  69.7k|    if (layers_node != NULL) {
  ------------------
  |  Branch (3268:9): [True: 50.9k, False: 18.8k]
  ------------------
 3269|       |        // Supported versions started in 1.0.1, so anything newer
 3270|  50.9k|        if (!loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3270:13): [True: 33.9k, False: 16.9k]
  ------------------
 3271|  33.9k|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3272|  33.9k|                       "loader_add_layer_properties: \'layers\' tag not supported until file version 1.0.1, but %s is reporting "
 3273|  33.9k|                       "version %s",
 3274|  33.9k|                       filename, file_vers);
 3275|  33.9k|        }
 3276|  50.9k|        cJSON *layer_node = NULL;
 3277|  4.90M|        cJSON_ArrayForEach(layer_node, layers_node) {
  ------------------
  |  |  213|  4.93M|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 50.9k, False: 0]
  |  |  |  Branch (213:61): [True: 4.90M, False: 26.1k]
  |  |  ------------------
  ------------------
 3278|  4.90M|            if (layer_node->type != cJSON_Object) {
  ------------------
  |  |  103|  4.90M|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3278:17): [True: 24.8k, False: 4.87M]
  ------------------
 3279|  24.8k|                loader_log(
 3280|  24.8k|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3281|  24.8k|                    "loader_add_layer_properties: Array element in \"layers\" field in manifest JSON file %s is not an object.  "
 3282|  24.8k|                    "Skipping this file",
 3283|  24.8k|                    filename);
 3284|  24.8k|                goto out;
 3285|  24.8k|            }
 3286|  4.87M|            result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3287|  4.87M|        }
 3288|  50.9k|    } else {
 3289|       |        // Otherwise, try to read in individual layers
 3290|  18.8k|        cJSON *layer_node = loader_cJSON_GetObjectItem(json, "layer");
 3291|  18.8k|        if (layer_node == NULL) {
  ------------------
  |  Branch (3291:13): [True: 3.62k, False: 15.2k]
  ------------------
 3292|       |            // Don't warn if this happens to be an ICD manifest
 3293|  3.62k|            if (loader_cJSON_GetObjectItem(json, "ICD") == NULL) {
  ------------------
  |  Branch (3293:17): [True: 2.51k, False: 1.11k]
  ------------------
 3294|  2.51k|                loader_log(
 3295|  2.51k|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3296|  2.51k|                    "loader_add_layer_properties: Can not find 'layer' object in manifest JSON file %s.  Skipping this file.",
 3297|  2.51k|                    filename);
 3298|  2.51k|            }
 3299|  3.62k|            goto out;
 3300|  3.62k|        }
 3301|       |        // Loop through all "layer" objects in the file to get a count of them
 3302|       |        // first.
 3303|  15.2k|        uint16_t layer_count = 0;
 3304|  15.2k|        cJSON *tempNode = layer_node;
 3305|   122k|        do {
 3306|   122k|            tempNode = tempNode->next;
 3307|   122k|            layer_count++;
 3308|   122k|        } while (tempNode != NULL);
  ------------------
  |  Branch (3308:18): [True: 107k, False: 15.2k]
  ------------------
 3309|       |
 3310|       |        // Throw a warning if we encounter multiple "layer" objects in file
 3311|       |        // versions newer than 1.0.0.  Having multiple objects with the same
 3312|       |        // name at the same level is actually a JSON standard violation.
 3313|  15.2k|        if (layer_count > 1 && loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3313:13): [True: 14.5k, False: 679]
  |  Branch (3313:32): [True: 2.83k, False: 11.7k]
  ------------------
 3314|  2.83k|            loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3315|  2.83k|                       "loader_add_layer_properties: Multiple 'layer' nodes are deprecated starting in file version \"1.0.1\".  "
 3316|  2.83k|                       "Please use 'layers' : [] array instead in %s.",
 3317|  2.83k|                       filename);
 3318|  12.4k|        } else {
 3319|   114k|            do {
 3320|   114k|                result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3321|   114k|                if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3321:21): [True: 0, False: 114k]
  ------------------
 3322|      0|                    goto out;
 3323|      0|                }
 3324|   114k|                layer_node = layer_node->next;
 3325|   114k|            } while (layer_node != NULL);
  ------------------
  |  Branch (3325:22): [True: 101k, False: 12.4k]
  ------------------
 3326|  12.4k|        }
 3327|  15.2k|    }
 3328|       |
 3329|  73.7k|out:
 3330|       |
 3331|  73.7k|    return result;
 3332|  69.7k|}
copy_data_file_info:
 3336|   219k|                             size_t relative_path_size, struct loader_string_list *search_paths) {
 3337|   219k|    if (NULL != cur_path) {
  ------------------
  |  Branch (3337:9): [True: 219k, False: 0]
  ------------------
 3338|   219k|        uint32_t start = 0;
 3339|   219k|        uint32_t stop = 0;
 3340|       |
 3341|   468k|        while (cur_path[start] != '\0') {
  ------------------
  |  Branch (3341:16): [True: 249k, False: 219k]
  ------------------
 3342|   315k|            while (cur_path[start] == PATH_SEPARATOR && cur_path[start] != '\0') {
  ------------------
  |  |  154|   630k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3342:20): [True: 66.3k, False: 249k]
  |  Branch (3342:57): [True: 66.3k, False: 0]
  ------------------
 3343|  66.3k|                start++;
 3344|  66.3k|            }
 3345|   249k|            stop = start;
 3346|   184M|            while (cur_path[stop] != PATH_SEPARATOR && cur_path[stop] != '\0') {
  ------------------
  |  |  154|   368M|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3346:20): [True: 184M, False: 43.9k]
  |  Branch (3346:56): [True: 184M, False: 205k]
  ------------------
 3347|   184M|                stop++;
 3348|   184M|            }
 3349|   249k|            const size_t s = stop - start;
 3350|   249k|            if (s) {
  ------------------
  |  Branch (3350:17): [True: 248k, False: 464]
  ------------------
 3351|       |                // space enough for base path, relative path, path separator, and null terminator
 3352|   248k|                size_t new_str_len = s + relative_path_size + 2;
 3353|       |
 3354|   248k|                char *new_str = loader_instance_heap_calloc(inst, new_str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 3355|   248k|                if (NULL == new_str) {
  ------------------
  |  Branch (3355:21): [True: 0, False: 248k]
  ------------------
 3356|      0|                    return VK_ERROR_OUT_OF_HOST_MEMORY;
 3357|      0|                }
 3358|   248k|                memcpy(new_str, &cur_path[start], s);
 3359|   248k|                new_str[s] = '\0';
 3360|       |
 3361|       |                // If this is a specific JSON file, just add it and don't add any
 3362|       |                // relative path or directory symbol to it.
 3363|   248k|                if (!is_json(new_str, s)) {
  ------------------
  |  Branch (3363:21): [True: 240k, False: 8.48k]
  ------------------
 3364|       |                    // Add the relative directory if present.
 3365|   240k|                    if (relative_path_size > 0) {
  ------------------
  |  Branch (3365:25): [True: 109k, False: 130k]
  ------------------
 3366|   109k|                        char *rel_start = new_str + s;
 3367|       |
 3368|       |                        // If last symbol written was not a directory symbol, add it.
 3369|   109k|                        if (*(rel_start - 1) != DIRECTORY_SYMBOL) {
  ------------------
  |  |  155|   109k|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (3369:29): [True: 109k, False: 0]
  ------------------
 3370|   109k|                            *rel_start++ = DIRECTORY_SYMBOL;
  ------------------
  |  |  155|   109k|#define DIRECTORY_SYMBOL '/'
  ------------------
 3371|   109k|                        }
 3372|   109k|                        memcpy(rel_start, relative_path, relative_path_size);
 3373|   109k|                        rel_start[relative_path_size] = '\0';
 3374|   109k|                    }
 3375|   240k|                }
 3376|       |
 3377|   248k|                VkResult res = append_str_to_string_list_if_unique(inst, search_paths, new_str);
 3378|   248k|                if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3378:21): [True: 0, False: 248k]
  ------------------
 3379|      0|                    return res;
 3380|      0|                }
 3381|   248k|                start = stop;
 3382|   248k|            }
 3383|   249k|        }
 3384|   219k|    }
 3385|   219k|    return VK_SUCCESS;
 3386|   219k|}
add_if_manifest_file:
 3389|   138k|VkResult add_if_manifest_file(const struct loader_instance *inst, const char *file_name, struct loader_string_list *out_files) {
 3390|   138k|    assert(NULL != file_name && "add_if_manifest_file: Received NULL pointer for file_name");
 3391|   138k|    assert(NULL != out_files && "add_if_manifest_file: Received NULL pointer for out_files");
 3392|       |
 3393|       |    // Look for files ending with ".json" suffix
 3394|   138k|    size_t name_len = strlen(file_name);
 3395|   138k|    if (!is_json(file_name, name_len)) {
  ------------------
  |  Branch (3395:9): [True: 31.8k, False: 106k]
  ------------------
 3396|       |        // Use incomplete to indicate invalid name, but to keep going.
 3397|  31.8k|        return VK_INCOMPLETE;
 3398|  31.8k|    }
 3399|       |
 3400|       |    // A directory search path and a file inside it can reach the same manifest.
 3401|   106k|    return copy_str_to_string_list_if_unique(inst, out_files, file_name, name_len);
 3402|   138k|}
add_data_files:
 3425|  16.8k|                        struct loader_string_list *out_files) {
 3426|  16.8k|    VkResult vk_result = VK_SUCCESS;
 3427|  16.8k|    char full_path[2048];
 3428|  16.8k|#if !defined(_WIN32)
 3429|  16.8k|    char temp_path[2048];
 3430|  16.8k|#endif
 3431|       |
 3432|   148k|    for (size_t i = 0; i < search_paths->count; i++) {
  ------------------
  |  Branch (3432:24): [True: 131k, False: 16.8k]
  ------------------
 3433|       |        // Now, parse the paths
 3434|   131k|        char *next_file = search_paths->list[i];
 3435|   263k|        while (NULL != next_file && *next_file != '\0') {
  ------------------
  |  Branch (3435:16): [True: 263k, False: 0]
  |  Branch (3435:37): [True: 131k, False: 131k]
  ------------------
 3436|   131k|            char *name = NULL;
 3437|   131k|            char *cur_file = next_file;
 3438|   131k|            next_file = loader_get_next_path(cur_file);
 3439|       |
 3440|       |            // Is this a JSON file, then try to open it.
 3441|   131k|            size_t len = strlen(cur_file);
 3442|   131k|            if (is_json(cur_file, len)) {
  ------------------
  |  Branch (3442:17): [True: 4.05k, False: 127k]
  ------------------
 3443|       |#if defined(_WIN32)
 3444|       |                name = cur_file;
 3445|       |#elif COMMON_UNIX_PLATFORMS
 3446|       |                // Only Linux has relative paths, make a copy of location so it isn't modified
 3447|  4.05k|                size_t str_len;
 3448|  4.05k|                if (NULL != next_file) {
  ------------------
  |  Branch (3448:21): [True: 4.05k, False: 0]
  ------------------
 3449|  4.05k|                    str_len = next_file - cur_file + 1;
 3450|  4.05k|                } else {
 3451|      0|                    str_len = strlen(cur_file) + 1;
 3452|      0|                }
 3453|  4.05k|                if (str_len > sizeof(temp_path)) {
  ------------------
  |  Branch (3453:21): [True: 218, False: 3.83k]
  ------------------
 3454|    218|                    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "add_data_files: Path to %s too long", cur_file);
 3455|    218|                    continue;
 3456|    218|                }
 3457|  3.83k|                strncpy(temp_path, cur_file, str_len);
 3458|  3.83k|                name = temp_path;
 3459|       |#else
 3460|       |#warning add_data_files must define relative path copy for this platform
 3461|       |#endif
 3462|  3.83k|                loader_get_fullpath(cur_file, name, sizeof(full_path), full_path);
 3463|  3.83k|                name = full_path;
 3464|       |
 3465|  3.83k|                VkResult local_res;
 3466|  3.83k|                local_res = add_if_manifest_file(inst, name, out_files);
 3467|       |
 3468|       |                // Incomplete means this was not a valid data file.
 3469|  3.83k|                if (local_res == VK_INCOMPLETE) {
  ------------------
  |  Branch (3469:21): [True: 0, False: 3.83k]
  ------------------
 3470|      0|                    continue;
 3471|      0|                }
 3472|  3.83k|                if (local_res != VK_SUCCESS) {
  ------------------
  |  Branch (3472:21): [True: 0, False: 3.83k]
  ------------------
 3473|      0|                    vk_result = local_res;
 3474|      0|                    break;
 3475|      0|                }
 3476|   127k|            } else {  // Otherwise, treat it as a directory
 3477|   127k|                DIR *dir_stream = loader_opendir(inst, cur_file);
 3478|   127k|                if (NULL == dir_stream) {
  ------------------
  |  Branch (3478:21): [True: 117k, False: 10.0k]
  ------------------
 3479|   117k|                    continue;
 3480|   117k|                }
 3481|   144k|                while (1) {
  ------------------
  |  Branch (3481:24): [True: 144k, Folded]
  ------------------
 3482|   144k|                    errno = 0;
 3483|       |                    // NOLINTNEXTLINE(concurrency-mt-unsafe) - readdir is safe here since each thread uses its own dir_stream
 3484|   144k|                    struct dirent *dir_entry = readdir(dir_stream);
 3485|   144k|#if !defined(WIN32)  // Windows doesn't use readdir, don't check errors on functions which aren't called
 3486|   144k|                    if (errno != 0) {
  ------------------
  |  Branch (3486:25): [True: 0, False: 144k]
  ------------------
 3487|       |                        // NOLINTNEXTLINE(concurrency-mt-unsafe) - strerror's static buffer is used immediately and not retained
 3488|      0|                        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "readdir failed with %d: %s", errno, strerror(errno));
 3489|      0|                        break;
 3490|      0|                    }
 3491|   144k|#endif
 3492|   144k|                    if (NULL == dir_entry) {
  ------------------
  |  Branch (3492:25): [True: 10.0k, False: 134k]
  ------------------
 3493|  10.0k|                        break;
 3494|  10.0k|                    }
 3495|       |
 3496|   134k|                    name = &(dir_entry->d_name[0]);
 3497|       |                    // 'name' is the bare filename, 'cur_file' is the directory being scanned; the substring "file" in
 3498|       |                    // cur_file just confuses the naming heuristic below.
 3499|       |                    // NOLINTNEXTLINE(readability-suspicious-call-argument) - arguments are correctly ordered, not swapped
 3500|   134k|                    loader_get_fullpath(name, cur_file, sizeof(full_path), full_path);
 3501|   134k|                    name = full_path;
 3502|       |
 3503|   134k|                    VkResult local_res;
 3504|   134k|                    local_res = add_if_manifest_file(inst, name, out_files);
 3505|       |
 3506|       |                    // Incomplete means this was not a valid data file.
 3507|   134k|                    if (local_res == VK_INCOMPLETE) {
  ------------------
  |  Branch (3507:25): [True: 31.8k, False: 102k]
  ------------------
 3508|  31.8k|                        continue;
 3509|  31.8k|                    }
 3510|   102k|                    if (local_res != VK_SUCCESS) {
  ------------------
  |  Branch (3510:25): [True: 0, False: 102k]
  ------------------
 3511|      0|                        vk_result = local_res;
 3512|      0|                        break;
 3513|      0|                    }
 3514|   102k|                }
 3515|  10.0k|                loader_closedir(inst, dir_stream);
 3516|  10.0k|                if (vk_result != VK_SUCCESS) {
  ------------------
  |  Branch (3516:21): [True: 0, False: 10.0k]
  ------------------
 3517|      0|                    goto out;
 3518|      0|                }
 3519|  10.0k|            }
 3520|   131k|        }
 3521|   131k|    }
 3522|       |
 3523|  16.8k|out:
 3524|       |
 3525|  16.8k|    return vk_result;
 3526|  16.8k|}
read_data_files_in_search_paths:
 3532|  16.8k|                                         struct loader_string_list *out_files) {
 3533|  16.8k|    VkResult vk_result = VK_SUCCESS;
 3534|  16.8k|    char *override_env = NULL;
 3535|  16.8k|    char *additional_env = NULL;
 3536|  16.8k|    struct loader_string_list search_paths = {0};
 3537|       |
 3538|  16.8k|#if COMMON_UNIX_PLATFORMS
 3539|  16.8k|    const char *relative_location = NULL;  // Only used on unix platforms
 3540|  16.8k|    size_t rel_size = 0;                   // unused in windows, dont declare so no compiler warnings are generated
 3541|  16.8k|#endif
 3542|       |
 3543|       |#if defined(__APPLE__)
 3544|       |    char *bundle_path = NULL;
 3545|       |    char *search_only_in_bundle_env_var = loader_secure_getenv(VK_LOADER_SEARCH_ONLY_IN_BUNDLE_ENV_VAR, inst);
 3546|       |#endif
 3547|       |
 3548|       |#if defined(_WIN32)
 3549|       |    char *package_path = NULL;
 3550|       |#elif COMMON_UNIX_PLATFORMS
 3551|       |    // Determine how much space is needed to generate the full search path
 3552|       |    // for the current manifest files.
 3553|  16.8k|    char *xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
 3554|  16.8k|    char *xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
 3555|       |
 3556|  16.8k|#if !defined(__Fuchsia__) && !defined(__QNX__)
 3557|  16.8k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (3557:9): [True: 16.8k, False: 0]
  |  Branch (3557:36): [True: 0, False: 0]
  ------------------
 3558|  16.8k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
 3559|  16.8k|    }
 3560|  16.8k|#endif
 3561|       |
 3562|  16.8k|    char *xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
 3563|  16.8k|    char *xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
 3564|       |
 3565|  16.8k|#if !defined(__Fuchsia__) && !defined(__QNX__)
 3566|  16.8k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (3566:9): [True: 16.8k, False: 0]
  |  Branch (3566:34): [True: 0, False: 0]
  ------------------
 3567|  16.8k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
 3568|  16.8k|    }
 3569|  16.8k|#endif
 3570|       |
 3571|  16.8k|    char *home = NULL;
 3572|  16.8k|    char *default_data_home = NULL;
 3573|  16.8k|    char *default_config_home = NULL;
 3574|  16.8k|    char *home_data_dir = NULL;
 3575|  16.8k|    char *home_config_dir = NULL;
 3576|       |
 3577|       |    // Only use HOME if XDG_DATA_HOME is not present on the system
 3578|  16.8k|    home = loader_secure_getenv("HOME", inst);
 3579|  16.8k|    if (home != NULL) {
  ------------------
  |  Branch (3579:9): [True: 16.8k, False: 0]
  ------------------
 3580|  16.8k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (3580:13): [True: 16.8k, False: 0]
  |  Branch (3580:40): [True: 0, False: 0]
  ------------------
 3581|  16.8k|            const char config_suffix[] = "/.config";
 3582|  16.8k|            size_t default_config_home_len = strlen(home) + sizeof(config_suffix) + 1;
 3583|  16.8k|            default_config_home = loader_instance_heap_calloc(inst, default_config_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3584|  16.8k|            if (default_config_home == NULL) {
  ------------------
  |  Branch (3584:17): [True: 0, False: 16.8k]
  ------------------
 3585|      0|                vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3586|      0|                goto out;
 3587|      0|            }
 3588|  16.8k|            strncpy(default_config_home, home, default_config_home_len);
 3589|  16.8k|            strncat(default_config_home, config_suffix, default_config_home_len);
 3590|  16.8k|        }
 3591|  16.8k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (3591:13): [True: 16.8k, False: 0]
  |  Branch (3591:38): [True: 0, False: 0]
  ------------------
 3592|  16.8k|            const char data_suffix[] = "/.local/share";
 3593|  16.8k|            size_t default_data_home_len = strlen(home) + sizeof(data_suffix) + 1;
 3594|  16.8k|            default_data_home = loader_instance_heap_calloc(inst, default_data_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3595|  16.8k|            if (default_data_home == NULL) {
  ------------------
  |  Branch (3595:17): [True: 0, False: 16.8k]
  ------------------
 3596|      0|                vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3597|      0|                goto out;
 3598|      0|            }
 3599|  16.8k|            strncpy(default_data_home, home, default_data_home_len);
 3600|  16.8k|            strncat(default_data_home, data_suffix, default_data_home_len);
 3601|  16.8k|        }
 3602|  16.8k|    }
 3603|       |
 3604|  16.8k|    if (NULL != default_config_home) {
  ------------------
  |  Branch (3604:9): [True: 16.8k, False: 0]
  ------------------
 3605|  16.8k|        home_config_dir = default_config_home;
 3606|  16.8k|    } else {
 3607|      0|        home_config_dir = xdg_config_home;
 3608|      0|    }
 3609|  16.8k|    if (NULL != default_data_home) {
  ------------------
  |  Branch (3609:9): [True: 16.8k, False: 0]
  ------------------
 3610|  16.8k|        home_data_dir = default_data_home;
 3611|  16.8k|    } else {
 3612|      0|        home_data_dir = xdg_data_home;
 3613|      0|    }
 3614|       |#else
 3615|       |#warning read_data_files_in_search_paths unsupported platform
 3616|       |#endif
 3617|       |
 3618|  16.8k|    switch (manifest_type) {
 3619|    838|        case LOADER_DATA_FILE_MANIFEST_DRIVER:
  ------------------
  |  Branch (3619:9): [True: 838, False: 15.9k]
  ------------------
 3620|    838|            if (loader_settings_should_use_driver_environment_variables(inst)) {
  ------------------
  |  Branch (3620:17): [True: 838, False: 0]
  ------------------
 3621|    838|                override_env = loader_secure_getenv(VK_DRIVER_FILES_ENV_VAR, inst);
  ------------------
  |  |  113|    838|#define VK_DRIVER_FILES_ENV_VAR "VK_DRIVER_FILES"
  ------------------
 3622|    838|                if (NULL == override_env) {
  ------------------
  |  Branch (3622:21): [True: 838, False: 0]
  ------------------
 3623|       |                    // Not there, so fall back to the old name
 3624|    838|                    override_env = loader_secure_getenv(VK_ICD_FILENAMES_ENV_VAR, inst);
  ------------------
  |  |  112|    838|#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES"  // Deprecated in v1.3.207 loader
  ------------------
 3625|    838|                }
 3626|    838|                additional_env = loader_secure_getenv(VK_ADDITIONAL_DRIVER_FILES_ENV_VAR, inst);
  ------------------
  |  |  116|    838|#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
  ------------------
 3627|    838|            }
 3628|    838|#if COMMON_UNIX_PLATFORMS
 3629|    838|            relative_location = VK_DRIVERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  165|    838|#define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
  |  |  ------------------
  |  |  |  |  157|    838|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
  |  |  ------------------
  |  |  |  |  158|    838|#define VULKAN_ICDCONF_DIR "icd.d"
  |  |  ------------------
  ------------------
 3630|    838|#endif
 3631|       |#if defined(_WIN32)
 3632|       |            package_path = windows_get_app_package_manifest_path(inst);
 3633|       |#endif
 3634|    838|            break;
 3635|  7.98k|        case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER:
  ------------------
  |  Branch (3635:9): [True: 7.98k, False: 8.82k]
  ------------------
 3636|  7.98k|            override_env = loader_secure_getenv(VK_IMPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  130|  7.98k|#define VK_IMPLICIT_LAYER_PATH_ENV_VAR "VK_IMPLICIT_LAYER_PATH"
  ------------------
 3637|  7.98k|            additional_env = loader_secure_getenv(VK_ADDITIONAL_IMPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  131|  7.98k|#define VK_ADDITIONAL_IMPLICIT_LAYER_PATH_ENV_VAR "VK_ADD_IMPLICIT_LAYER_PATH"
  ------------------
 3638|  7.98k|#if COMMON_UNIX_PLATFORMS
 3639|  7.98k|            relative_location = VK_ILAYERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  168|  7.98k|#define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  157|  7.98k|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  162|  7.98k|#define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
  |  |  ------------------
  ------------------
 3640|  7.98k|#endif
 3641|       |#if defined(_WIN32)
 3642|       |            package_path = windows_get_app_package_manifest_path(inst);
 3643|       |#endif
 3644|  7.98k|            break;
 3645|  7.98k|        case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER:
  ------------------
  |  Branch (3645:9): [True: 7.98k, False: 8.82k]
  ------------------
 3646|  7.98k|            override_env = loader_secure_getenv(VK_EXPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  114|  7.98k|#define VK_EXPLICIT_LAYER_PATH_ENV_VAR "VK_LAYER_PATH"
  ------------------
 3647|  7.98k|            additional_env = loader_secure_getenv(VK_ADDITIONAL_EXPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  117|  7.98k|#define VK_ADDITIONAL_EXPLICIT_LAYER_PATH_ENV_VAR "VK_ADD_LAYER_PATH"
  ------------------
 3648|  7.98k|#if COMMON_UNIX_PLATFORMS
 3649|  7.98k|            relative_location = VK_ELAYERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  167|  7.98k|#define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  157|  7.98k|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  161|  7.98k|#define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
  |  |  ------------------
  ------------------
 3650|  7.98k|#endif
 3651|  7.98k|            break;
 3652|      0|        default:
  ------------------
  |  Branch (3652:9): [True: 0, False: 16.8k]
  ------------------
 3653|      0|            assert(false && "Shouldn't get here!");
 3654|      0|            break;
 3655|  16.8k|    }
 3656|       |
 3657|       |    // Log a message when VK_LAYER_PATH is set but the override layer paths take priority
 3658|  16.8k|    if (manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER &&
  ------------------
  |  Branch (3658:9): [True: 7.98k, False: 8.82k]
  ------------------
 3659|  7.98k|        (NULL != override_env && NULL != path_overrides && path_overrides->count > 0)) {
  ------------------
  |  Branch (3659:10): [True: 0, False: 7.98k]
  |  Branch (3659:34): [True: 0, False: 0]
  |  Branch (3659:60): [True: 0, False: 0]
  ------------------
 3660|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3661|      0|                   "Ignoring VK_LAYER_PATH. The Override layer is active and has override paths set, which takes priority. "
 3662|      0|                   "VK_LAYER_PATH is set to %s",
 3663|      0|                   override_env);
 3664|      0|    }
 3665|       |
 3666|       |    // Add the remaining paths to the list
 3667|  16.8k|    if (NULL != path_overrides && path_overrides->count > 0) {
  ------------------
  |  Branch (3667:9): [True: 7.98k, False: 8.82k]
  |  Branch (3667:35): [True: 1.16k, False: 6.82k]
  ------------------
 3668|  23.5k|        for (size_t i = 0; i < path_overrides->count; i++) {
  ------------------
  |  Branch (3668:28): [True: 22.3k, False: 1.16k]
  ------------------
 3669|  22.3k|            if (NULL != path_overrides->list[i]) {
  ------------------
  |  Branch (3669:17): [True: 22.3k, False: 0]
  ------------------
 3670|  22.3k|                if (manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER) {
  ------------------
  |  Branch (3670:21): [True: 22.3k, False: 0]
  ------------------
 3671|  22.3k|                    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "%s", path_overrides->list[i]);
 3672|  22.3k|                }
 3673|  22.3k|                vk_result = copy_data_file_info(inst, path_overrides->list[i], NULL, 0, &search_paths);
 3674|  22.3k|                if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3674:21): [True: 0, False: 22.3k]
  ------------------
 3675|      0|                    goto out;
 3676|      0|                }
 3677|  22.3k|            }
 3678|  22.3k|        }
 3679|  15.6k|    } else if (override_env != NULL) {
  ------------------
  |  Branch (3679:16): [True: 0, False: 15.6k]
  ------------------
 3680|      0|        vk_result = copy_data_file_info(inst, override_env, NULL, 0, &search_paths);
 3681|      0|        if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3681:13): [True: 0, False: 0]
  ------------------
 3682|      0|            goto out;
 3683|      0|        }
 3684|  15.6k|    } else {
 3685|       |        // Add any additional search paths defined in the additive environment variable
 3686|  15.6k|        if (NULL != additional_env) {
  ------------------
  |  Branch (3686:13): [True: 0, False: 15.6k]
  ------------------
 3687|      0|            vk_result = copy_data_file_info(inst, additional_env, NULL, 0, &search_paths);
 3688|      0|            if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3688:17): [True: 0, False: 0]
  ------------------
 3689|      0|                goto out;
 3690|      0|            }
 3691|      0|        }
 3692|       |
 3693|       |#if defined(_WIN32)
 3694|       |        if (NULL != package_path) {
 3695|       |            vk_result = copy_data_file_info(inst, package_path, NULL, 0, &search_paths);
 3696|       |            if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
 3697|       |                goto out;
 3698|       |            }
 3699|       |        }
 3700|       |#elif COMMON_UNIX_PLATFORMS
 3701|  15.6k|        bool search_outside_of_bundle = true;
 3702|       |
 3703|  15.6k|        rel_size = strlen(relative_location);
 3704|  15.6k|        if (rel_size > 0) {
  ------------------
  |  Branch (3704:13): [True: 15.6k, False: 0]
  ------------------
 3705|       |#if defined(__APPLE__)
 3706|       |            // Add the bundle's Resources dir to the beginning of the search path.
 3707|       |            // Looks for manifests in the bundle first, before any system directories.
 3708|       |            // This also appears to work unmodified for iOS, it finds the app bundle on the devices
 3709|       |            // file system. (RSW)
 3710|       |            CFBundleRef main_bundle = CFBundleGetMainBundle();
 3711|       |            if (NULL != main_bundle) {
 3712|       |                CFURLRef ref = CFBundleCopyResourcesDirectoryURL(main_bundle);
 3713|       |                if (NULL != ref) {
 3714|       |                    // Allocate large scratch buffer to hold the bundles path, the relative location inside the bundle, plus a path
 3715|       |                    // separator and null terminator. Since we are using a while loop, initialize length with half the intended size
 3716|       |                    size_t bundle_path_len = (MAXPATHLEN + rel_size + 2) / 2;
 3717|       |                    bool bundle_query_success = false;
 3718|       |                    uint32_t retry_count = 0;
 3719|       |                    while (!bundle_query_success && retry_count < 4) {
 3720|       |                        void *new_bundle_path = loader_instance_heap_realloc(
 3721|       |                            inst, bundle_path, bundle_path_len, bundle_path_len * 2, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3722|       |                        if (NULL == new_bundle_path) {
 3723|       |                            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3724|       |                                       "read_data_files_in_search_paths: Failed to allocate space for bundle path of length %d",
 3725|       |                                       (uint32_t)bundle_path_len * 2);
 3726|       |                            vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3727|       |                            goto out;
 3728|       |                        }
 3729|       |                        bundle_path = new_bundle_path;
 3730|       |                        bundle_path_len = bundle_path_len * 2;
 3731|       |                        memset(bundle_path, 0, bundle_path_len);
 3732|       |                        bundle_query_success = CFURLGetFileSystemRepresentation(ref, TRUE, (UInt8 *)bundle_path, bundle_path_len);
 3733|       |                        retry_count++;
 3734|       |                    }
 3735|       |
 3736|       |                    if (bundle_query_success) {
 3737|       |                        size_t cur_bundle_len = strlen(bundle_path);
 3738|       |
 3739|       |                        if (cur_bundle_len + rel_size + 2 > bundle_path_len) {
 3740|       |                            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3741|       |                                       "read_data_files_in_search_paths: bundle_path %s of size %d does not have enough space to "
 3742|       |                                       "append relative_path",
 3743|       |                                       bundle_path, (uint32_t)bundle_path_len);
 3744|       |                            vk_result = VK_ERROR_INITIALIZATION_FAILED;
 3745|       |                            goto out;
 3746|       |                        }
 3747|       |                        bundle_path[cur_bundle_len] = DIRECTORY_SYMBOL;
 3748|       |                        cur_bundle_len++;
 3749|       |                        memcpy(bundle_path + cur_bundle_len, relative_location, rel_size);
 3750|       |                        cur_bundle_len += rel_size;
 3751|       |                        bundle_path[cur_bundle_len] = '\0';
 3752|       |
 3753|       |                        vk_result = copy_data_file_info(inst, bundle_path, NULL, 0, &search_paths);
 3754|       |                        if (vk_result == VK_ERROR_OUT_OF_HOST_MEMORY) {
 3755|       |                            goto out;
 3756|       |                        }
 3757|       |                    }
 3758|       |                    CFRelease(ref);
 3759|       |                }
 3760|       |            }
 3761|       |
 3762|       |            if (NULL != search_only_in_bundle_env_var) {
 3763|       |                search_outside_of_bundle = false;
 3764|       |            }
 3765|       |#endif  // __APPLE__
 3766|  15.6k|            if (search_outside_of_bundle) {
  ------------------
  |  Branch (3766:17): [True: 15.6k, False: 0]
  ------------------
 3767|       |                // Only add the home folders if not NULL
 3768|  15.6k|                if (NULL != home_config_dir) {
  ------------------
  |  Branch (3768:21): [True: 15.6k, False: 0]
  ------------------
 3769|  15.6k|                    vk_result = copy_data_file_info(inst, home_config_dir, relative_location, rel_size, &search_paths);
 3770|  15.6k|                    if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3770:25): [True: 0, False: 15.6k]
  ------------------
 3771|      0|                        goto out;
 3772|      0|                    }
 3773|  15.6k|                }
 3774|  15.6k|                vk_result = copy_data_file_info(inst, xdg_config_dirs, relative_location, rel_size, &search_paths);
 3775|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3775:21): [True: 0, False: 15.6k]
  ------------------
 3776|      0|                    goto out;
 3777|      0|                }
 3778|  15.6k|                vk_result = copy_data_file_info(inst, SYSCONFDIR, relative_location, rel_size, &search_paths);
 3779|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3779:21): [True: 0, False: 15.6k]
  ------------------
 3780|      0|                    goto out;
 3781|      0|                }
 3782|  15.6k|#if defined(EXTRASYSCONFDIR)
 3783|  15.6k|                vk_result = copy_data_file_info(inst, EXTRASYSCONFDIR, relative_location, rel_size, &search_paths);
 3784|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3784:21): [True: 0, False: 15.6k]
  ------------------
 3785|      0|                    goto out;
 3786|      0|                }
 3787|  15.6k|#endif
 3788|       |
 3789|       |                // Only add the home folders if not NULL
 3790|  15.6k|                if (NULL != home_data_dir) {
  ------------------
  |  Branch (3790:21): [True: 15.6k, False: 0]
  ------------------
 3791|  15.6k|                    vk_result = copy_data_file_info(inst, home_data_dir, relative_location, rel_size, &search_paths);
 3792|  15.6k|                    if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3792:25): [True: 0, False: 15.6k]
  ------------------
 3793|      0|                        goto out;
 3794|      0|                    }
 3795|  15.6k|                }
 3796|  15.6k|                vk_result = copy_data_file_info(inst, xdg_data_dirs, relative_location, rel_size, &search_paths);
 3797|  15.6k|                if (VK_SUCCESS != vk_result) {
  ------------------
  |  Branch (3797:21): [True: 0, False: 15.6k]
  ------------------
 3798|      0|                    goto out;
 3799|      0|                }
 3800|  15.6k|            }
 3801|  15.6k|        }
 3802|       |#else
 3803|       |#warning read_data_files_in_search_paths unsupported platform
 3804|       |#endif
 3805|  15.6k|    }
 3806|       |
 3807|       |    // Print out the paths being searched if debugging is enabled
 3808|  16.8k|    uint32_t log_flags = 0;
 3809|       |
 3810|  16.8k|    if (manifest_type == LOADER_DATA_FILE_MANIFEST_DRIVER) {
  ------------------
  |  Branch (3810:9): [True: 838, False: 15.9k]
  ------------------
 3811|    838|        log_flags = VULKAN_LOADER_DRIVER_BIT;
 3812|    838|        loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Searching for driver manifest files");
 3813|  15.9k|    } else {
 3814|  15.9k|        log_flags = VULKAN_LOADER_LAYER_BIT;
 3815|  15.9k|        loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "Searching for %s layer manifest files",
 3816|  15.9k|                   manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER ? "explicit" : "implicit");
  ------------------
  |  Branch (3816:20): [True: 7.98k, False: 7.98k]
  ------------------
 3817|  15.9k|    }
 3818|  16.8k|    loader_log(inst, log_flags, 0, "   In following locations:");
 3819|       |
 3820|   148k|    for (size_t i = 0; i < search_paths.count; i++) {
  ------------------
  |  Branch (3820:24): [True: 131k, False: 16.8k]
  ------------------
 3821|   131k|        loader_log(inst, log_flags, 0, "      %s", search_paths.list[i]);
 3822|   131k|    }
 3823|       |
 3824|       |    // Now, parse the paths and add any manifest files found in them.
 3825|  16.8k|    vk_result = add_data_files(inst, &search_paths, out_files);
 3826|       |
 3827|  16.8k|    if (log_flags != 0 && out_files->count > 0) {
  ------------------
  |  Branch (3827:9): [True: 16.8k, False: 0]
  |  Branch (3827:27): [True: 9.43k, False: 7.38k]
  ------------------
 3828|  9.43k|        loader_log(inst, log_flags, 0, "   Found the following files:");
 3829|   115k|        for (uint32_t cur_file = 0; cur_file < out_files->count; ++cur_file) {
  ------------------
  |  Branch (3829:37): [True: 106k, False: 9.43k]
  ------------------
 3830|   106k|            loader_log(inst, log_flags, 0, "      %s", out_files->list[cur_file]);
 3831|   106k|        }
 3832|  9.43k|    } else {
 3833|  7.38k|        loader_log(inst, log_flags, 0, "   Found no files");
 3834|  7.38k|    }
 3835|       |
 3836|  16.8k|    if ((NULL != path_overrides && path_overrides->count > 0) || NULL != override_env) {
  ------------------
  |  Branch (3836:10): [True: 7.98k, False: 8.82k]
  |  Branch (3836:36): [True: 1.16k, False: 6.82k]
  |  Branch (3836:66): [True: 0, False: 15.6k]
  ------------------
 3837|  1.16k|        *override_active = true;
 3838|  15.6k|    } else {
 3839|  15.6k|        *override_active = false;
 3840|  15.6k|    }
 3841|       |
 3842|  16.8k|out:
 3843|       |
 3844|  16.8k|    loader_free_getenv(additional_env, inst);
 3845|  16.8k|    loader_free_getenv(override_env, inst);
 3846|       |#if defined(_WIN32)
 3847|       |    loader_instance_heap_free(inst, package_path);
 3848|       |#elif COMMON_UNIX_PLATFORMS
 3849|       |#if defined(__APPLE__)
 3850|       |    loader_instance_heap_free(inst, bundle_path);
 3851|       |    loader_free_getenv(search_only_in_bundle_env_var, inst);
 3852|       |#endif
 3853|  16.8k|    loader_free_getenv(xdg_config_home, inst);
 3854|  16.8k|    loader_free_getenv(xdg_config_dirs, inst);
 3855|  16.8k|    loader_free_getenv(xdg_data_home, inst);
 3856|  16.8k|    loader_free_getenv(xdg_data_dirs, inst);
 3857|  16.8k|    loader_free_getenv(xdg_data_home, inst);
 3858|  16.8k|    loader_free_getenv(home, inst);
 3859|  16.8k|    loader_instance_heap_free(inst, default_data_home);
 3860|  16.8k|    loader_instance_heap_free(inst, default_config_home);
 3861|       |#else
 3862|       |#warning read_data_files_in_search_paths unsupported platform
 3863|       |#endif
 3864|       |
 3865|  16.8k|    free_string_list(inst, &search_paths);
 3866|       |
 3867|  16.8k|    return vk_result;
 3868|  16.8k|}
loader_get_data_files:
 3894|  16.8k|                               const struct loader_string_list *path_overrides, struct loader_string_list *out_files) {
 3895|  16.8k|    VkResult res = VK_SUCCESS;
 3896|  16.8k|    bool override_active = false;
 3897|       |
 3898|       |    // Free and init the out_files information so there's no false data left from uninitialized variables.
 3899|  16.8k|    free_string_list(inst, out_files);
 3900|       |
 3901|  16.8k|    res = read_data_files_in_search_paths(inst, manifest_type, path_overrides, &override_active, out_files);
 3902|  16.8k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3902:9): [True: 0, False: 16.8k]
  ------------------
 3903|      0|        goto out;
 3904|      0|    }
 3905|       |
 3906|       |#if defined(_WIN32)
 3907|       |    // Read the registry if the override wasn't active.
 3908|       |    if (!override_active) {
 3909|       |        bool warn_if_not_present = false;
 3910|       |        char *registry_location = NULL;
 3911|       |
 3912|       |        switch (manifest_type) {
 3913|       |            default:
 3914|       |                goto out;
 3915|       |            case LOADER_DATA_FILE_MANIFEST_DRIVER:
 3916|       |                warn_if_not_present = true;
 3917|       |                registry_location = VK_DRIVERS_INFO_REGISTRY_LOC;
 3918|       |                break;
 3919|       |            case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER:
 3920|       |                registry_location = VK_ILAYERS_INFO_REGISTRY_LOC;
 3921|       |                break;
 3922|       |            case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER:
 3923|       |                warn_if_not_present = true;
 3924|       |                registry_location = VK_ELAYERS_INFO_REGISTRY_LOC;
 3925|       |                break;
 3926|       |        }
 3927|       |        VkResult tmp_res =
 3928|       |            windows_read_data_files_in_registry(inst, manifest_type, warn_if_not_present, registry_location, out_files);
 3929|       |        // Only return an error if there was an error this time, and no manifest files from before.
 3930|       |        if (VK_SUCCESS != tmp_res && out_files->count == 0) {
 3931|       |            res = tmp_res;
 3932|       |            goto out;
 3933|       |        }
 3934|       |    }
 3935|       |#endif
 3936|       |
 3937|  16.8k|out:
 3938|       |
 3939|  16.8k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3939:9): [True: 0, False: 16.8k]
  ------------------
 3940|      0|        free_string_list(inst, out_files);
 3941|      0|    }
 3942|       |
 3943|  16.8k|    return res;
 3944|  16.8k|}
loader_parse_icd_manifest:
 3954|    838|                                   bool *skipped_portability_drivers) {
 3955|    838|    VkResult res = VK_SUCCESS;
 3956|    838|    cJSON *icd_manifest_json = NULL;
 3957|       |
 3958|    838|    if (file_str == NULL) {
  ------------------
  |  Branch (3958:9): [True: 0, False: 838]
  ------------------
 3959|      0|        goto out;
 3960|      0|    }
 3961|       |
 3962|    838|    res = loader_get_json(inst, file_str, &icd_manifest_json);
 3963|    838|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (3963:9): [True: 0, False: 838]
  ------------------
 3964|      0|        goto out;
 3965|      0|    }
 3966|    838|    if (res != VK_SUCCESS || NULL == icd_manifest_json) {
  ------------------
  |  Branch (3966:9): [True: 0, False: 838]
  |  Branch (3966:30): [True: 0, False: 838]
  ------------------
 3967|      0|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 3968|      0|        goto out;
 3969|      0|    }
 3970|       |
 3971|    838|    cJSON *file_format_version_json = loader_cJSON_GetObjectItem(icd_manifest_json, "file_format_version");
 3972|    838|    if (file_format_version_json == NULL) {
  ------------------
  |  Branch (3972:9): [True: 0, False: 838]
  ------------------
 3973|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 3974|      0|                   "loader_parse_icd_manifest: ICD JSON %s does not have a \'file_format_version\' field. Skipping ICD JSON.",
 3975|      0|                   file_str);
 3976|      0|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 3977|      0|        goto out;
 3978|      0|    }
 3979|       |
 3980|    838|    char *file_vers_str = loader_cJSON_GetStringValue(file_format_version_json);
 3981|    838|    if (NULL == file_vers_str) {
  ------------------
  |  Branch (3981:9): [True: 0, False: 838]
  ------------------
 3982|       |        // Only reason the print can fail is if there was an allocation issue
 3983|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 3984|      0|                   "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'file_format_version\' field. Skipping ICD JSON",
 3985|      0|                   file_str);
 3986|      0|        goto out;
 3987|      0|    }
 3988|    838|    loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers_str);
 3989|       |
 3990|       |    // Get the version of the driver manifest
 3991|    838|    loader_api_version json_file_version = loader_make_full_version(loader_parse_version_string(file_vers_str));
 3992|       |
 3993|       |    // Loader only knows versions 1.0.0 and 1.0.1, anything above it is unknown
 3994|    838|    if (loader_check_version_meets_required(loader_combine_version(1, 0, 2), json_file_version)) {
  ------------------
  |  Branch (3994:9): [True: 79, False: 759]
  ------------------
 3995|     79|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 3996|     79|                   "loader_parse_icd_manifest: %s has unknown icd manifest file version %d.%d.%d. May cause errors.", file_str,
 3997|     79|                   json_file_version.major, json_file_version.minor, json_file_version.patch);
 3998|     79|    }
 3999|       |
 4000|    838|    cJSON *itemICD = loader_cJSON_GetObjectItem(icd_manifest_json, "ICD");
 4001|    838|    if (itemICD == NULL) {
  ------------------
  |  Branch (4001:9): [True: 25, False: 813]
  ------------------
 4002|       |        // Don't warn if this happens to be a layer manifest file
 4003|     25|        if (loader_cJSON_GetObjectItem(icd_manifest_json, "layer") == NULL &&
  ------------------
  |  Branch (4003:13): [True: 24, False: 1]
  ------------------
 4004|     24|            loader_cJSON_GetObjectItem(icd_manifest_json, "layers") == NULL) {
  ------------------
  |  Branch (4004:13): [True: 0, False: 24]
  ------------------
 4005|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4006|      0|                       "loader_parse_icd_manifest: Can not find \'ICD\' object in ICD JSON file %s. Skipping ICD JSON", file_str);
 4007|      0|        }
 4008|     25|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 4009|     25|        goto out;
 4010|     25|    }
 4011|       |
 4012|    813|    cJSON *library_path_json = loader_cJSON_GetObjectItem(itemICD, "library_path");
 4013|    813|    if (library_path_json == NULL) {
  ------------------
  |  Branch (4013:9): [True: 6, False: 807]
  ------------------
 4014|      6|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4015|      6|                   "loader_parse_icd_manifest: Failed to find \'library_path\' object in ICD JSON file %s. Skipping ICD JSON.",
 4016|      6|                   file_str);
 4017|      6|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 4018|      6|        goto out;
 4019|      6|    }
 4020|    813|    bool out_of_memory = false;
 4021|    807|    char *library_path = loader_cJSON_Print(library_path_json, &out_of_memory);
 4022|    807|    if (out_of_memory) {
  ------------------
  |  Branch (4022:9): [True: 0, False: 807]
  ------------------
 4023|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4024|      0|                   "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'library_path\' field. Skipping ICD JSON.", file_str);
 4025|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4026|      0|        goto out;
 4027|    807|    } else if (!library_path || strlen(library_path) == 0) {
  ------------------
  |  Branch (4027:16): [True: 0, False: 807]
  |  Branch (4027:33): [True: 1, False: 806]
  ------------------
 4028|      1|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4029|      1|                   "loader_parse_icd_manifest: ICD JSON %s \'library_path\' field is empty. Skipping ICD JSON.", file_str);
 4030|      1|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 4031|      1|        loader_instance_heap_free(inst, library_path);
 4032|      1|        goto out;
 4033|      1|    }
 4034|       |
 4035|       |    // Print out the paths being searched if debugging is enabled
 4036|    806|    loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0, "Searching for ICD drivers named %s", library_path);
 4037|       |    // This function takes ownership of library_path - so we don't need to clean it up
 4038|    806|    res = combine_manifest_directory_and_library_path(inst, library_path, file_str, &icd->full_library_path);
 4039|    806|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4039:9): [True: 0, False: 806]
  ------------------
 4040|      0|        goto out;
 4041|      0|    }
 4042|       |
 4043|    806|    cJSON *api_version_json = loader_cJSON_GetObjectItem(itemICD, "api_version");
 4044|    806|    if (api_version_json == NULL) {
  ------------------
  |  Branch (4044:9): [True: 748, False: 58]
  ------------------
 4045|    748|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4046|    748|                   "loader_parse_icd_manifest: ICD JSON %s does not have an \'api_version\' field. Skipping ICD JSON.", file_str);
 4047|    748|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 4048|    748|        goto out;
 4049|    748|    }
 4050|     58|    char *version_str = loader_cJSON_GetStringValue(api_version_json);
 4051|     58|    if (NULL == version_str) {
  ------------------
  |  Branch (4051:9): [True: 2, False: 56]
  ------------------
 4052|       |        // Only reason the print can fail is if there was an allocation issue
 4053|      2|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4054|      2|                   "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'api_version\' field. Skipping ICD JSON.", file_str);
 4055|       |
 4056|      2|        goto out;
 4057|      2|    }
 4058|     56|    icd->version = loader_parse_version_string(version_str);
 4059|       |
 4060|     56|    if (VK_API_VERSION_VARIANT(icd->version) != 0) {
  ------------------
  |  Branch (4060:9): [True: 25, False: 31]
  ------------------
 4061|     25|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4062|     25|                   "loader_parse_icd_manifest: Driver's ICD JSON %s \'api_version\' field contains a non-zero variant value of %d. "
 4063|     25|                   " Skipping ICD JSON.",
 4064|     25|                   file_str, VK_API_VERSION_VARIANT(icd->version));
 4065|     25|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 4066|     25|        goto out;
 4067|     25|    }
 4068|       |
 4069|       |    // Skip over ICD's which contain a true "is_portability_driver" value whenever the application doesn't enable
 4070|       |    // portability enumeration.
 4071|     31|    cJSON *is_portability_driver_json = loader_cJSON_GetObjectItem(itemICD, "is_portability_driver");
 4072|     31|    if (loader_cJSON_IsTrue(is_portability_driver_json) && inst && !inst->portability_enumeration_enabled) {
  ------------------
  |  Branch (4072:9): [True: 0, False: 31]
  |  Branch (4072:60): [True: 0, False: 0]
  |  Branch (4072:68): [True: 0, False: 0]
  ------------------
 4073|      0|        if (skipped_portability_drivers) {
  ------------------
  |  Branch (4073:13): [True: 0, False: 0]
  ------------------
 4074|      0|            *skipped_portability_drivers = true;
 4075|      0|        }
 4076|      0|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
 4077|      0|        goto out;
 4078|      0|    }
 4079|       |
 4080|     31|    char *library_arch_str = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(itemICD, "library_arch"));
 4081|     31|    if (library_arch_str != NULL) {
  ------------------
  |  Branch (4081:9): [True: 0, False: 31]
  ------------------
 4082|      0|        if ((strncmp(library_arch_str, "32", 2) == 0 && sizeof(void *) != 4) ||
  ------------------
  |  Branch (4082:14): [True: 0, False: 0]
  |  Branch (4082:57): [True: 0, Folded]
  ------------------
 4083|      0|            (strncmp(library_arch_str, "64", 2) == 0 && sizeof(void *) != 8)) {
  ------------------
  |  Branch (4083:14): [True: 0, False: 0]
  |  Branch (4083:57): [Folded, False: 0]
  ------------------
 4084|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 4085|      0|                       "loader_parse_icd_manifest: Driver library architecture doesn't match the current running "
 4086|      0|                       "architecture, skipping this driver");
 4087|      0|            res = VK_ERROR_INCOMPATIBLE_DRIVER;
 4088|      0|            goto out;
 4089|      0|        }
 4090|      0|    }
 4091|    838|out:
 4092|    838|    loader_cJSON_Delete(icd_manifest_json);
 4093|    838|    return res;
 4094|     31|}
loader_icd_scan:
 4111|    838|                         const VkInstanceCreateInfo *pCreateInfo, bool *skipped_portability_drivers) {
 4112|    838|    VkResult res = VK_SUCCESS;
 4113|    838|    struct loader_string_list manifest_files = {0};
 4114|    838|    struct loader_envvar_filter select_filter = {0};
 4115|    838|    struct loader_envvar_filter disable_filter = {0};
 4116|    838|    struct ICDManifestInfo *icd_details = NULL;
 4117|       |
 4118|       |    // Set up the ICD Trampoline list so elements can be written into it.
 4119|    838|    res = loader_init_scanned_icd_list(inst, icd_tramp_list);
 4120|    838|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (4120:9): [True: 0, False: 838]
  ------------------
 4121|      0|        return res;
 4122|      0|    }
 4123|       |
 4124|    838|    bool direct_driver_loading_exclusive_mode = false;
 4125|    838|    res = loader_scan_for_direct_drivers(inst, pCreateInfo, icd_tramp_list, &direct_driver_loading_exclusive_mode);
 4126|    838|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (4126:9): [True: 0, False: 838]
  ------------------
 4127|      0|        goto out;
 4128|      0|    }
 4129|    838|    if (direct_driver_loading_exclusive_mode) {
  ------------------
  |  Branch (4129:9): [True: 0, False: 838]
  ------------------
 4130|       |        // Make sure to jump over the system & env-var driver discovery mechanisms if exclusive mode is set, even if no drivers
 4131|       |        // were successfully found through the direct driver loading mechanism
 4132|      0|        goto out;
 4133|      0|    }
 4134|       |
 4135|    838|    if (loader_settings_should_use_driver_environment_variables(inst)) {
  ------------------
  |  Branch (4135:9): [True: 838, False: 0]
  ------------------
 4136|       |        // Parse the filter environment variables to determine if we have any special behavior
 4137|    838|        res = parse_generic_filter_environment_var(inst, VK_DRIVERS_SELECT_ENV_VAR, &select_filter);
  ------------------
  |  |  122|    838|#define VK_DRIVERS_SELECT_ENV_VAR "VK_LOADER_DRIVERS_SELECT"
  ------------------
 4138|    838|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4138:13): [True: 0, False: 838]
  ------------------
 4139|      0|            goto out;
 4140|      0|        }
 4141|    838|        res = parse_generic_filter_environment_var(inst, VK_DRIVERS_DISABLE_ENV_VAR, &disable_filter);
  ------------------
  |  |  123|    838|#define VK_DRIVERS_DISABLE_ENV_VAR "VK_LOADER_DRIVERS_DISABLE"
  ------------------
 4142|    838|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4142:13): [True: 0, False: 838]
  ------------------
 4143|      0|            goto out;
 4144|      0|        }
 4145|    838|    }
 4146|       |
 4147|       |    // Get a list of manifest files for ICDs
 4148|    838|    res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files);
 4149|    838|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4149:9): [True: 0, False: 838]
  ------------------
 4150|      0|        goto out;
 4151|      0|    }
 4152|       |
 4153|       |    // Add any drivers provided by the loader settings file
 4154|    838|    res = loader_settings_get_additional_driver_files(inst, &manifest_files);
 4155|    838|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4155:9): [True: 0, False: 838]
  ------------------
 4156|      0|        goto out;
 4157|      0|    }
 4158|       |
 4159|    838|    icd_details = loader_stack_alloc(sizeof(struct ICDManifestInfo) * manifest_files.count);
  ------------------
  |  |   42|    838|#define loader_stack_alloc(size) alloca(size)
  ------------------
 4160|    838|    if (NULL == icd_details) {
  ------------------
  |  Branch (4160:9): [True: 0, False: 838]
  ------------------
 4161|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4162|      0|        goto out;
 4163|      0|    }
 4164|    838|    memset(icd_details, 0, sizeof(struct ICDManifestInfo) * manifest_files.count);
 4165|       |
 4166|  1.67k|    for (uint32_t i = 0; i < manifest_files.count; i++) {
  ------------------
  |  Branch (4166:26): [True: 838, False: 837]
  ------------------
 4167|    838|        VkResult icd_res = VK_SUCCESS;
 4168|       |
 4169|    838|        icd_res = loader_parse_icd_manifest(inst, manifest_files.list[i], &icd_details[i], skipped_portability_drivers);
 4170|    838|        if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) {
  ------------------
  |  Branch (4170:13): [True: 0, False: 838]
  ------------------
 4171|      0|            res = icd_res;
 4172|      0|            goto out;
 4173|    838|        } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) {
  ------------------
  |  Branch (4173:20): [True: 805, False: 33]
  ------------------
 4174|    805|            continue;
 4175|    805|        }
 4176|       |
 4177|     33|        if (select_filter.count > 0 || disable_filter.count > 0) {
  ------------------
  |  Branch (4177:13): [True: 0, False: 33]
  |  Branch (4177:40): [True: 0, False: 33]
  ------------------
 4178|       |            // Get only the filename for comparing to the filters
 4179|      0|            char *just_filename_str = strrchr(manifest_files.list[i], DIRECTORY_SYMBOL);
  ------------------
  |  |  155|      0|#define DIRECTORY_SYMBOL '/'
  ------------------
 4180|       |
 4181|       |            // No directory symbol, just the filename
 4182|      0|            if (NULL == just_filename_str) {
  ------------------
  |  Branch (4182:17): [True: 0, False: 0]
  ------------------
 4183|      0|                just_filename_str = manifest_files.list[i];
 4184|      0|            } else {
 4185|      0|                just_filename_str++;
 4186|      0|            }
 4187|       |
 4188|      0|            bool name_matches_select =
 4189|      0|                (select_filter.count > 0 && check_name_matches_filter_environment_var(just_filename_str, &select_filter));
  ------------------
  |  Branch (4189:18): [True: 0, False: 0]
  |  Branch (4189:45): [True: 0, False: 0]
  ------------------
 4190|      0|            bool name_matches_disable =
 4191|      0|                (disable_filter.count > 0 && check_name_matches_filter_environment_var(just_filename_str, &disable_filter));
  ------------------
  |  Branch (4191:18): [True: 0, False: 0]
  |  Branch (4191:46): [True: 0, False: 0]
  ------------------
 4192|       |
 4193|      0|            if (name_matches_disable && !name_matches_select) {
  ------------------
  |  Branch (4193:17): [True: 0, False: 0]
  |  Branch (4193:41): [True: 0, False: 0]
  ------------------
 4194|      0|                loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4195|      0|                           "Driver \"%s\" ignored because it was disabled by env var \'%s\'", just_filename_str,
 4196|      0|                           VK_DRIVERS_DISABLE_ENV_VAR);
  ------------------
  |  |  123|      0|#define VK_DRIVERS_DISABLE_ENV_VAR "VK_LOADER_DRIVERS_DISABLE"
  ------------------
 4197|      0|                continue;
 4198|      0|            }
 4199|      0|            if (select_filter.count != 0 && !name_matches_select) {
  ------------------
  |  Branch (4199:17): [True: 0, False: 0]
  |  Branch (4199:45): [True: 0, False: 0]
  ------------------
 4200|      0|                loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4201|      0|                           "Driver \"%s\" ignored because not selected by env var \'%s\'", just_filename_str,
 4202|      0|                           VK_DRIVERS_SELECT_ENV_VAR);
  ------------------
  |  |  122|      0|#define VK_DRIVERS_SELECT_ENV_VAR "VK_LOADER_DRIVERS_SELECT"
  ------------------
 4203|      0|                continue;
 4204|      0|            }
 4205|      0|        }
 4206|       |
 4207|     33|        enum loader_layer_library_status lib_status;
 4208|     33|        icd_res =
 4209|     33|            loader_scanned_icd_add(inst, icd_tramp_list, icd_details[i].full_library_path, icd_details[i].version, &lib_status);
 4210|     33|        if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) {
  ------------------
  |  Branch (4210:13): [True: 1, False: 32]
  ------------------
 4211|      1|            res = icd_res;
 4212|      1|            goto out;
 4213|     32|        } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) {
  ------------------
  |  Branch (4213:20): [True: 32, False: 0]
  ------------------
 4214|     32|            switch (lib_status) {
  ------------------
  |  Branch (4214:21): [True: 32, False: 0]
  ------------------
 4215|      0|                case LOADER_LAYER_LIB_NOT_LOADED:
  ------------------
  |  Branch (4215:17): [True: 0, False: 32]
  ------------------
 4216|     30|                case LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD:
  ------------------
  |  Branch (4216:17): [True: 30, False: 2]
  ------------------
 4217|     30|                case LOADER_LAYER_LIB_ERROR_NEGOTIATE_INTERFACE_VERSION_FAILED:
  ------------------
  |  Branch (4217:17): [True: 0, False: 32]
  ------------------
 4218|     30|                case LOADER_LAYER_LIB_ERROR_UNABLE_TO_FIND_VK_GET_INSTANCE_PROC_ADDR:
  ------------------
  |  Branch (4218:17): [True: 0, False: 32]
  ------------------
 4219|     30|                    loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4220|     30|                               "loader_icd_scan: Failed loading library associated with ICD JSON %s. Ignoring this JSON",
 4221|     30|                               icd_details[i].full_library_path);
 4222|     30|                    break;
 4223|      2|                case LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE:
  ------------------
  |  Branch (4223:17): [True: 2, False: 30]
  ------------------
 4224|      2|                    loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Requested ICD %s was wrong bit-type. Ignoring this JSON",
 4225|      2|                               icd_details[i].full_library_path);
 4226|      2|                    break;
 4227|      0|                case LOADER_LAYER_LIB_SUCCESS_LOADED:
  ------------------
  |  Branch (4227:17): [True: 0, False: 32]
  ------------------
 4228|      0|                case LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY:
  ------------------
  |  Branch (4228:17): [True: 0, False: 32]
  ------------------
 4229|       |                    // Shouldn't be able to reach this but if it is, best to report a debug
 4230|      0|                    loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4231|      0|                               "Shouldn't reach this. A valid version of requested ICD %s was loaded but something bad "
 4232|      0|                               "happened afterwards.",
 4233|      0|                               icd_details[i].full_library_path);
 4234|      0|                    break;
 4235|     32|            }
 4236|     32|        }
 4237|     33|    }
 4238|       |
 4239|    838|out:
 4240|    838|    if (NULL != icd_details) {
  ------------------
  |  Branch (4240:9): [True: 838, False: 0]
  ------------------
 4241|       |        // Successfully got the icd_details structure, which means we need to free the paths contained within
 4242|  1.67k|        for (uint32_t i = 0; i < manifest_files.count; i++) {
  ------------------
  |  Branch (4242:30): [True: 838, False: 838]
  ------------------
 4243|    838|            loader_instance_heap_free(inst, icd_details[i].full_library_path);
 4244|    838|        }
 4245|    838|    }
 4246|    838|    free_string_list(inst, &manifest_files);
 4247|    838|    return res;
 4248|    838|}
loader_parse_instance_layers:
 4254|  15.9k|                                      const struct loader_string_list *path_overrides, struct loader_layer_list *instance_layers) {
 4255|  15.9k|    assert(manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER || manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER);
 4256|  15.9k|    VkResult res = VK_SUCCESS;
 4257|  15.9k|    struct loader_string_list manifest_files = {0};
 4258|       |
 4259|  15.9k|    res = loader_get_data_files(inst, manifest_type, path_overrides, &manifest_files);
 4260|  15.9k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4260:9): [True: 0, False: 15.9k]
  ------------------
 4261|      0|        goto out;
 4262|      0|    }
 4263|       |
 4264|   121k|    for (uint32_t i = 0; i < manifest_files.count; i++) {
  ------------------
  |  Branch (4264:26): [True: 105k, False: 15.9k]
  ------------------
 4265|   105k|        char *file_str = manifest_files.list[i];
 4266|   105k|        if (file_str == NULL) {
  ------------------
  |  Branch (4266:13): [True: 0, False: 105k]
  ------------------
 4267|      0|            continue;
 4268|      0|        }
 4269|       |
 4270|       |        // Parse file into JSON struct
 4271|   105k|        cJSON *json = NULL;
 4272|   105k|        VkResult local_res = loader_get_json(inst, file_str, &json);
 4273|   105k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (4273:13): [True: 0, False: 105k]
  ------------------
 4274|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4275|      0|            goto out;
 4276|   105k|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (4276:20): [True: 3.66k, False: 101k]
  |  Branch (4276:47): [True: 28.4k, False: 73.4k]
  ------------------
 4277|  32.1k|            continue;
 4278|  32.1k|        }
 4279|       |
 4280|  73.4k|        local_res = loader_add_layer_properties(inst, instance_layers, json,
 4281|  73.4k|                                                manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, file_str);
 4282|  73.4k|        loader_cJSON_Delete(json);
 4283|       |
 4284|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 4285|  73.4k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (4285:13): [True: 0, False: 73.4k]
  ------------------
 4286|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4287|      0|            goto out;
 4288|      0|        }
 4289|  73.4k|    }
 4290|  15.9k|out:
 4291|  15.9k|    free_string_list(inst, &manifest_files);
 4292|       |
 4293|  15.9k|    return res;
 4294|  15.9k|}
get_override_layer_override_paths:
 4299|  1.17k|                                           struct loader_string_list *override_paths) {
 4300|  1.17k|    if (prop->override_paths.count > 0) {
  ------------------
  |  Branch (4300:9): [True: 1.17k, False: 0]
  ------------------
 4301|   104k|        for (uint32_t j = 0; j < prop->override_paths.count; j++) {
  ------------------
  |  Branch (4301:30): [True: 103k, False: 1.17k]
  ------------------
 4302|   103k|            VkResult result = copy_data_file_info(inst, prop->override_paths.list[j], NULL, 0, override_paths);
 4303|   103k|            if (VK_SUCCESS != result) {
  ------------------
  |  Branch (4303:17): [True: 0, False: 103k]
  ------------------
 4304|      0|                return result;
 4305|      0|            }
 4306|   103k|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Override layer has override path %s",
 4307|   103k|                       prop->override_paths.list[j]);
 4308|   103k|        }
 4309|  1.17k|    }
 4310|  1.17k|    return VK_SUCCESS;
 4311|  1.17k|}
loader_remove_duplicate_layers:
 4313|  7.98k|void loader_remove_duplicate_layers(struct loader_instance *inst, struct loader_layer_list *layers) {
 4314|       |    // Remove duplicate layers (that share the same layerName)
 4315|  1.09M|    for (uint32_t i = 0; i < layers->count; ++i) {
  ------------------
  |  Branch (4315:26): [True: 1.08M, False: 7.98k]
  ------------------
 4316|  1.08M|        bool has_duplicate = false;
 4317|  1.08M|        uint32_t duplicate_index = 0;
 4318|  12.9M|        for (uint32_t j = i + 1; j < layers->count; ++j) {
  ------------------
  |  Branch (4318:34): [True: 12.9M, False: 6.46k]
  ------------------
 4319|  12.9M|            if (strcmp(layers->list[i].info.layerName, layers->list[j].info.layerName) == 0) {
  ------------------
  |  Branch (4319:17): [True: 1.08M, False: 11.9M]
  ------------------
 4320|  1.08M|                has_duplicate = true;
 4321|  1.08M|                duplicate_index = j;
 4322|  1.08M|                break;
 4323|  1.08M|            }
 4324|  12.9M|        }
 4325|  1.08M|        if (has_duplicate) {
  ------------------
  |  Branch (4325:13): [True: 1.08M, False: 6.46k]
  ------------------
 4326|  1.08M|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Removing layer %s (%s) because it is a duplicate of %s (%s)",
 4327|  1.08M|                       layers->list[duplicate_index].info.layerName, layers->list[duplicate_index].manifest_file_name,
 4328|  1.08M|                       layers->list[i].info.layerName, layers->list[i].manifest_file_name);
 4329|  1.08M|            loader_remove_layer_in_list(inst, layers, duplicate_index);
 4330|  1.08M|        }
 4331|  1.08M|    }
 4332|  7.98k|}
loader_scan_for_layers:
 4335|  8.37k|                                const struct loader_envvar_all_filters *filters) {
 4336|  8.37k|    VkResult res = VK_SUCCESS;
 4337|  8.37k|    struct loader_layer_list settings_layers = {0};
 4338|  8.37k|    struct loader_layer_list regular_instance_layers = {0};
 4339|  8.37k|    bool override_layer_valid = false;
 4340|  8.37k|    struct loader_string_list override_paths = {0};
 4341|       |
 4342|  8.37k|    bool should_search_for_other_layers = true;
 4343|  8.37k|    res = get_settings_layers(inst, &settings_layers, &should_search_for_other_layers);
 4344|  8.37k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4344:9): [True: 0, False: 8.37k]
  ------------------
 4345|      0|        goto out;
 4346|      0|    }
 4347|       |
 4348|       |    // If we should not look for layers using other mechanisms, assign settings_layers to instance_layers and jump to the
 4349|       |    // output
 4350|  8.37k|    if (!should_search_for_other_layers) {
  ------------------
  |  Branch (4350:9): [True: 384, False: 7.98k]
  ------------------
 4351|    384|        *instance_layers = settings_layers;
 4352|    384|        memset(&settings_layers, 0, sizeof(struct loader_layer_list));
 4353|    384|        goto out;
 4354|    384|    }
 4355|       |
 4356|  7.98k|    res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &regular_instance_layers);
 4357|  7.98k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4357:9): [True: 0, False: 7.98k]
  ------------------
 4358|      0|        goto out;
 4359|      0|    }
 4360|       |
 4361|       |    // Remove any extraneous override layers.
 4362|  7.98k|    remove_all_non_valid_override_layers(inst, &regular_instance_layers);
 4363|       |
 4364|       |    // Check to see if the override layer is present, and use it's override paths.
 4365|  46.0k|    for (uint32_t i = 0; i < regular_instance_layers.count; i++) {
  ------------------
  |  Branch (4365:26): [True: 39.1k, False: 6.81k]
  ------------------
 4366|  39.1k|        struct loader_layer_properties *prop = &regular_instance_layers.list[i];
 4367|  39.1k|        if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop) && prop->override_paths.count > 0) {
  ------------------
  |  Branch (4367:13): [True: 1.51k, False: 37.6k]
  |  Branch (4367:34): [True: 1.36k, False: 146]
  |  Branch (4367:91): [True: 1.17k, False: 198]
  ------------------
 4368|  1.17k|            res = get_override_layer_override_paths(inst, prop, &override_paths);
 4369|  1.17k|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4369:17): [True: 0, False: 1.17k]
  ------------------
 4370|      0|                goto out;
 4371|      0|            }
 4372|  1.17k|            break;
 4373|  1.17k|        }
 4374|  39.1k|    }
 4375|       |
 4376|       |    // Get a list of manifest files for explicit layers
 4377|  7.98k|    res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, &override_paths, &regular_instance_layers);
 4378|  7.98k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4378:9): [True: 0, False: 7.98k]
  ------------------
 4379|      0|        goto out;
 4380|      0|    }
 4381|       |
 4382|       |    // Verify any meta-layers in the list are valid and all the component layers are
 4383|       |    // actually present in the available layer list
 4384|  7.98k|    res = verify_all_meta_layers(inst, filters, &regular_instance_layers, &override_layer_valid);
 4385|  7.98k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (4385:9): [True: 0, False: 7.98k]
  ------------------
 4386|      0|        goto out;
 4387|      0|    }
 4388|       |
 4389|  7.98k|    if (override_layer_valid) {
  ------------------
  |  Branch (4389:9): [True: 1.36k, False: 6.62k]
  ------------------
 4390|  1.36k|        loader_remove_layers_in_blacklist(inst, &regular_instance_layers);
 4391|  1.36k|        if (NULL != inst) {
  ------------------
  |  Branch (4391:13): [True: 1.36k, False: 0]
  ------------------
 4392|  1.36k|            inst->override_layer_present = true;
 4393|  1.36k|        }
 4394|  1.36k|    }
 4395|       |
 4396|       |    // Remove disabled layers
 4397|  2.17M|    for (uint32_t i = 0; i < regular_instance_layers.count; ++i) {
  ------------------
  |  Branch (4397:26): [True: 2.16M, False: 7.98k]
  ------------------
 4398|  2.16M|        if (!loader_layer_is_available(inst, filters, &regular_instance_layers.list[i])) {
  ------------------
  |  Branch (4398:13): [True: 0, False: 2.16M]
  ------------------
 4399|      0|            loader_remove_layer_in_list(inst, &regular_instance_layers, i);
 4400|      0|            i--;
 4401|      0|        }
 4402|  2.16M|    }
 4403|       |
 4404|       |    // Make sure no layers have the same layerName
 4405|  7.98k|    loader_remove_duplicate_layers(inst, &regular_instance_layers);
 4406|       |
 4407|  7.98k|    res = combine_settings_layers_with_regular_layers(inst, &settings_layers, &regular_instance_layers, instance_layers);
 4408|       |
 4409|  8.37k|out:
 4410|  8.37k|    loader_delete_layer_list_and_properties(inst, &settings_layers);
 4411|  8.37k|    loader_delete_layer_list_and_properties(inst, &regular_instance_layers);
 4412|       |
 4413|  8.37k|    free_string_list(inst, &override_paths);
 4414|  8.37k|    return res;
 4415|  7.98k|}
loader_validate_layers:
 5637|  8.37k|                                const char *const *ppEnabledLayerNames, const struct loader_layer_list *list) {
 5638|  8.37k|    struct loader_layer_properties *prop;
 5639|       |
 5640|  8.37k|    if (layer_count > 0 && ppEnabledLayerNames == NULL) {
  ------------------
  |  Branch (5640:9): [True: 8.37k, False: 0]
  |  Branch (5640:28): [True: 0, False: 8.37k]
  ------------------
 5641|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5642|      0|                   "loader_validate_layers: ppEnabledLayerNames is NULL but enabledLayerCount is greater than zero");
 5643|      0|        return VK_ERROR_LAYER_NOT_PRESENT;
 5644|      0|    }
 5645|       |
 5646|  9.20k|    for (uint32_t i = 0; i < layer_count; i++) {
  ------------------
  |  Branch (5646:26): [True: 8.37k, False: 838]
  ------------------
 5647|  8.37k|        VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]);
 5648|  8.37k|        if (result != VK_STRING_ERROR_NONE) {
  ------------------
  |  Branch (5648:13): [True: 0, False: 8.37k]
  ------------------
 5649|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5650|      0|                       "loader_validate_layers: ppEnabledLayerNames contains string that is too long or is badly formed");
 5651|      0|            return VK_ERROR_LAYER_NOT_PRESENT;
 5652|      0|        }
 5653|       |
 5654|  8.37k|        prop = loader_find_layer_property(ppEnabledLayerNames[i], list);
 5655|  8.37k|        if (NULL == prop) {
  ------------------
  |  Branch (5655:13): [True: 7.53k, False: 839]
  ------------------
 5656|  7.53k|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5657|  7.53k|                       "loader_validate_layers: Layer %d does not exist in the list of available layers", i);
 5658|  7.53k|            return VK_ERROR_LAYER_NOT_PRESENT;
 5659|  7.53k|        }
 5660|    839|        if (inst->settings.settings_active && inst->settings.layer_configurations_active &&
  ------------------
  |  Branch (5660:13): [True: 6, False: 833]
  |  Branch (5660:47): [True: 2, False: 4]
  ------------------
 5661|      2|            prop->settings_control_value != LOADER_SETTINGS_LAYER_CONTROL_ON &&
  ------------------
  |  Branch (5661:13): [True: 2, False: 0]
  ------------------
 5662|      2|            prop->settings_control_value != LOADER_SETTINGS_LAYER_CONTROL_DEFAULT) {
  ------------------
  |  Branch (5662:13): [True: 1, False: 1]
  ------------------
 5663|      1|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5664|      1|                       "loader_validate_layers: Layer %d was explicitly prevented from being enabled by the loader settings file",
 5665|      1|                       i);
 5666|      1|            return VK_ERROR_LAYER_NOT_PRESENT;
 5667|      1|        }
 5668|    839|    }
 5669|    838|    return VK_SUCCESS;
 5670|  8.37k|}
vk_string_validate:
 7523|  8.37k|TEST_FUNCTION_EXPORT VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
 7524|  8.37k|    VkStringErrorFlags result = VK_STRING_ERROR_NONE;
 7525|  8.37k|    int num_char_bytes = 0;
 7526|  8.37k|    int i;
 7527|  8.37k|    int j;
 7528|       |
 7529|  8.37k|    if (utf8 == NULL) {
  ------------------
  |  Branch (7529:9): [True: 0, False: 8.37k]
  ------------------
 7530|      0|        return VK_STRING_ERROR_NULL_PTR;
 7531|      0|    }
 7532|       |
 7533|   234k|    for (i = 0; i <= max_length; i++) {
  ------------------
  |  Branch (7533:17): [True: 234k, False: 0]
  ------------------
 7534|   234k|        if (utf8[i] == 0) {
  ------------------
  |  Branch (7534:13): [True: 8.37k, False: 226k]
  ------------------
 7535|  8.37k|            break;
 7536|  8.37k|        }
 7537|   226k|        if (i == max_length) {
  ------------------
  |  Branch (7537:13): [True: 0, False: 226k]
  ------------------
 7538|      0|            result |= VK_STRING_ERROR_LENGTH;
 7539|      0|            break;
 7540|      0|        }
 7541|   226k|        if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) {
  ------------------
  |  Branch (7541:13): [True: 226k, False: 0]
  |  Branch (7541:34): [True: 226k, False: 0]
  ------------------
 7542|   226k|            num_char_bytes = 0;
 7543|   226k|        } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) {
  ------------------
  |  Branch (7543:20): [True: 0, False: 0]
  ------------------
 7544|      0|            num_char_bytes = 1;
 7545|      0|        } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) {
  ------------------
  |  Branch (7545:20): [True: 0, False: 0]
  ------------------
 7546|      0|            num_char_bytes = 2;
 7547|      0|        } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
  ------------------
  |  Branch (7547:20): [True: 0, False: 0]
  ------------------
 7548|      0|            num_char_bytes = 3;
 7549|      0|        } else {
 7550|      0|            result = VK_STRING_ERROR_BAD_DATA;
 7551|      0|        }
 7552|       |
 7553|       |        // Validate the following num_char_bytes of data
 7554|   226k|        for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
  ------------------
  |  Branch (7554:21): [True: 0, False: 226k]
  |  Branch (7554:45): [True: 0, False: 0]
  ------------------
 7555|      0|            if (++i == max_length) {
  ------------------
  |  Branch (7555:17): [True: 0, False: 0]
  ------------------
 7556|      0|                result |= VK_STRING_ERROR_LENGTH;
 7557|      0|                break;
 7558|      0|            }
 7559|      0|            if (utf8[i] == 0) {
  ------------------
  |  Branch (7559:17): [True: 0, False: 0]
  ------------------
 7560|       |                // The string terminated in the middle of a multi-byte character. Stop here so the
 7561|       |                // continuation-byte scan doesn't read past the terminator.
 7562|      0|                result |= VK_STRING_ERROR_BAD_DATA;
 7563|      0|                return result;
 7564|      0|            }
 7565|      0|            if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
  ------------------
  |  Branch (7565:17): [True: 0, False: 0]
  ------------------
 7566|      0|                result |= VK_STRING_ERROR_BAD_DATA;
 7567|      0|            }
 7568|      0|        }
 7569|   226k|    }
 7570|  8.37k|    return result;
 7571|  8.37k|}

loader_getenv:
   43|  29.8k|char *loader_getenv(const char *name, const struct loader_instance *inst) {
   44|  29.8k|    if (NULL == name) return NULL;
  ------------------
  |  Branch (44:9): [True: 0, False: 29.8k]
  ------------------
   45|       |    // No allocation of memory necessary for Linux, but we should at least touch
   46|       |    // the inst pointer to get rid of compiler warnings.
   47|  29.8k|    (void)inst;
   48|       |    // NOLINTNEXTLINE(concurrency-mt-unsafe) - there is no portable reentrant getenv; the loader never calls setenv concurrently
   49|  29.8k|    return getenv(name);
   50|  29.8k|}
loader_secure_getenv:
   52|   160k|char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
   53|       |#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
   54|       |    // Apple does not appear to have a secure getenv implementation.
   55|       |    // The main difference between secure getenv and getenv is that secure getenv
   56|       |    // returns NULL if the process is being run with elevated privileges by a normal user.
   57|       |    // The idea is to prevent the reading of malicious environment variables by a process
   58|       |    // that can do damage.
   59|       |    // This algorithm is derived from glibc code that sets an internal
   60|       |    // variable (__libc_enable_secure) if the process is running under setuid or setgid.
   61|       |    return is_high_integrity() ? NULL : loader_getenv(name, inst);
   62|       |#elif defined(__Fuchsia__)
   63|       |    return loader_getenv(name, inst);
   64|       |#else
   65|       |    // Linux
   66|   160k|    char *out;
   67|   160k|#if defined(HAVE_SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   68|   160k|    (void)inst;
   69|   160k|    out = secure_getenv(name);
   70|       |#elif defined(HAVE___SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   71|       |    (void)inst;
   72|       |    out = __secure_getenv(name);
   73|       |#else
   74|       |    out = loader_getenv(name, inst);
   75|       |#if !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   76|       |    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
   77|       |#endif
   78|       |#endif
   79|   160k|    return out;
   80|   160k|#endif
   81|   160k|}
loader_free_getenv:
   83|   154k|void loader_free_getenv(const char *val, const struct loader_instance *inst) {
   84|       |    // No freeing of memory necessary for Linux, but we should at least touch
   85|       |    // the val and inst pointers to get rid of compiler warnings.
   86|   154k|    (void)val;
   87|   154k|    (void)inst;
   88|   154k|}
determine_filter_type:
  193|  8.37k|                           size_t *new_length) {
  194|  8.37k|    size_t filter_length = strlen(filter_string);
  195|  8.37k|    bool star_begin = false;
  196|  8.37k|    bool star_end = false;
  197|  8.37k|    if ('~' == filter_string[0]) {
  ------------------
  |  Branch (197:9): [True: 0, False: 8.37k]
  ------------------
  198|       |        // One of the special identifiers like: ~all~, ~implicit~, or ~explicit~
  199|      0|        *filter_type = FILTER_STRING_SPECIAL;
  200|      0|        *new_start = filter_string;
  201|      0|        *new_length = filter_length;
  202|  8.37k|    } else {
  203|  8.37k|        if ('*' == filter_string[0]) {
  ------------------
  |  Branch (203:13): [True: 0, False: 8.37k]
  ------------------
  204|       |            // Only the * means everything
  205|      0|            if (filter_length == 1) {
  ------------------
  |  Branch (205:17): [True: 0, False: 0]
  ------------------
  206|      0|                *filter_type = FILTER_STRING_SPECIAL;
  207|      0|                *new_start = filter_string;
  208|      0|                *new_length = filter_length;
  209|      0|                return;
  210|      0|            }
  211|      0|            star_begin = true;
  212|      0|        }
  213|  8.37k|        if ('*' == filter_string[filter_length - 1]) {
  ------------------
  |  Branch (213:13): [True: 0, False: 8.37k]
  ------------------
  214|       |            // Not really valid, but just catch this case so if someone accidentally types "**" it will also mean everything
  215|      0|            if (star_begin && filter_length == 2) {
  ------------------
  |  Branch (215:17): [True: 0, False: 0]
  |  Branch (215:31): [True: 0, False: 0]
  ------------------
  216|      0|                *filter_type = FILTER_STRING_SPECIAL;
  217|      0|                *new_start = filter_string;
  218|      0|                *new_length = filter_length;
  219|      0|                return;
  220|      0|            }
  221|      0|            star_end = true;
  222|      0|        }
  223|  8.37k|        if (star_begin && star_end) {
  ------------------
  |  Branch (223:13): [True: 0, False: 8.37k]
  |  Branch (223:27): [True: 0, False: 0]
  ------------------
  224|      0|            *filter_type = FILTER_STRING_SUBSTRING;
  225|      0|            *new_start = &filter_string[1];
  226|      0|            *new_length = filter_length - 2;
  227|  8.37k|        } else if (star_begin) {
  ------------------
  |  Branch (227:20): [True: 0, False: 8.37k]
  ------------------
  228|      0|            *new_start = &filter_string[1];
  229|      0|            *new_length = filter_length - 1;
  230|      0|            *filter_type = FILTER_STRING_SUFFIX;
  231|  8.37k|        } else if (star_end) {
  ------------------
  |  Branch (231:20): [True: 0, False: 8.37k]
  ------------------
  232|      0|            *filter_type = FILTER_STRING_PREFIX;
  233|      0|            *new_start = filter_string;
  234|      0|            *new_length = filter_length - 1;
  235|  8.37k|        } else {
  236|  8.37k|            *filter_type = FILTER_STRING_FULLNAME;
  237|  8.37k|            *new_start = filter_string;
  238|  8.37k|            *new_length = filter_length;
  239|  8.37k|        }
  240|  8.37k|    }
  241|  8.37k|}
parse_generic_filter_environment_var:
  247|  18.4k|                                              struct loader_envvar_filter *filter_struct) {
  248|  18.4k|    VkResult result = VK_SUCCESS;
  249|  18.4k|    memset(filter_struct, 0, sizeof(struct loader_envvar_filter));
  250|  18.4k|    char *parsing_string = NULL;
  251|  18.4k|    char *env_var_value = loader_getenv(env_var_name, inst);
  252|  18.4k|    if (NULL == env_var_value) {
  ------------------
  |  Branch (252:9): [True: 10.0k, False: 8.37k]
  ------------------
  253|  10.0k|        return result;
  254|  10.0k|    }
  255|  8.37k|    const size_t env_var_len = strlen(env_var_value);
  256|  8.37k|    if (env_var_len == 0) {
  ------------------
  |  Branch (256:9): [True: 0, False: 8.37k]
  ------------------
  257|      0|        goto out;
  258|      0|    }
  259|       |    // Allocate a separate string since scan_for_next_comma modifies the original string
  260|  8.37k|    parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  261|  8.37k|    if (NULL == parsing_string) {
  ------------------
  |  Branch (261:9): [True: 0, False: 8.37k]
  ------------------
  262|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
  263|      0|                   "parse_generic_filter_environment_var: Failed to allocate space for parsing env var \'%s\'", env_var_name);
  264|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
  265|      0|        goto out;
  266|      0|    }
  267|       |
  268|  33.4k|    for (uint32_t iii = 0; iii < env_var_len; ++iii) {
  ------------------
  |  Branch (268:28): [True: 25.1k, False: 8.37k]
  ------------------
  269|       |        // NOLINTNEXTLINE(clang-analyzer-security.ArrayBound)
  270|  25.1k|        parsing_string[iii] = (char)tolower((unsigned char)env_var_value[iii]);
  ------------------
  |  Branch (270:37): [True: 0, False: 0]
  |  Branch (270:37): [True: 0, False: 0]
  |  Branch (270:37): [Folded, False: 25.1k]
  ------------------
  271|  25.1k|    }
  272|  8.37k|    parsing_string[env_var_len] = '\0';
  273|       |
  274|  8.37k|    char *context = NULL;
  275|  8.37k|    char *token = thread_safe_strtok(parsing_string, ",", &context);
  276|  16.7k|    while (NULL != token) {
  ------------------
  |  Branch (276:12): [True: 8.37k, False: 8.37k]
  ------------------
  277|  8.37k|        enum loader_filter_string_type cur_filter_type;
  278|  8.37k|        const char *actual_start;
  279|  8.37k|        size_t actual_len;
  280|  8.37k|        determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
  281|       |        // value holds at most VK_MAX_EXTENSION_NAME_SIZE - 1 chars plus the null terminator. Keep the stored length in sync
  282|       |        // with what actually fits so the matcher never walks past the buffer, and make sure it stays null terminated.
  283|  8.37k|        size_t stored_len = actual_len < VK_MAX_EXTENSION_NAME_SIZE - 1 ? actual_len : VK_MAX_EXTENSION_NAME_SIZE - 1;
  ------------------
  |  Branch (283:29): [True: 8.37k, False: 0]
  ------------------
  284|  8.37k|        loader_strncpy(filter_struct->filters[filter_struct->count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start, stored_len);
  285|  8.37k|        filter_struct->filters[filter_struct->count].value[stored_len] = '\0';
  286|  8.37k|        filter_struct->filters[filter_struct->count].length = stored_len;
  287|  8.37k|        filter_struct->filters[filter_struct->count++].type = cur_filter_type;
  288|  8.37k|        if (filter_struct->count >= MAX_ADDITIONAL_FILTERS) {
  ------------------
  |  |  530|  8.37k|#define MAX_ADDITIONAL_FILTERS 16
  ------------------
  |  Branch (288:13): [True: 0, False: 8.37k]
  ------------------
  289|      0|            break;
  290|      0|        }
  291|  8.37k|        token = thread_safe_strtok(NULL, ",", &context);
  292|  8.37k|    }
  293|       |
  294|  8.37k|out:
  295|       |
  296|  8.37k|    loader_instance_heap_free(inst, parsing_string);
  297|  8.37k|    loader_free_getenv(env_var_value, inst);
  298|  8.37k|    return result;
  299|  8.37k|}
parse_layers_disable_filter_environment_var:
  305|  8.37k|                                                     struct loader_envvar_disable_layers_filter *disable_struct) {
  306|  8.37k|    VkResult result = VK_SUCCESS;
  307|  8.37k|    memset(disable_struct, 0, sizeof(struct loader_envvar_disable_layers_filter));
  308|  8.37k|    char *parsing_string = NULL;
  309|  8.37k|    char *env_var_value = loader_getenv(VK_LAYERS_DISABLE_ENV_VAR, inst);
  ------------------
  |  |  120|  8.37k|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
  310|  8.37k|    if (NULL == env_var_value) {
  ------------------
  |  Branch (310:9): [True: 8.37k, False: 0]
  ------------------
  311|  8.37k|        goto out;
  312|  8.37k|    }
  313|      0|    const size_t env_var_len = strlen(env_var_value);
  314|      0|    if (env_var_len == 0) {
  ------------------
  |  Branch (314:9): [True: 0, False: 0]
  ------------------
  315|      0|        goto out;
  316|      0|    }
  317|       |    // Allocate a separate string since scan_for_next_comma modifies the original string
  318|      0|    parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  319|      0|    if (NULL == parsing_string) {
  ------------------
  |  Branch (319:9): [True: 0, False: 0]
  ------------------
  320|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
  321|      0|                   "parse_layers_disable_filter_environment_var: Failed to allocate space for parsing env var "
  322|      0|                   "\'VK_LAYERS_DISABLE_ENV_VAR\'");
  323|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
  324|      0|        goto out;
  325|      0|    }
  326|       |
  327|      0|    for (uint32_t iii = 0; iii < env_var_len; ++iii) {
  ------------------
  |  Branch (327:28): [True: 0, False: 0]
  ------------------
  328|       |        // Seems like a false positive - only occurred after changing loader_secure_getenv to loader_getenv
  329|       |        // NOLINTNEXTLINE(clang-analyzer-security.ArrayBound)
  330|      0|        parsing_string[iii] = (char)tolower((unsigned char)env_var_value[iii]);
  ------------------
  |  Branch (330:37): [True: 0, False: 0]
  |  Branch (330:37): [True: 0, False: 0]
  |  Branch (330:37): [Folded, False: 0]
  ------------------
  331|      0|    }
  332|      0|    parsing_string[env_var_len] = '\0';
  333|       |
  334|      0|    char *context = NULL;
  335|      0|    char *token = thread_safe_strtok(parsing_string, ",", &context);
  336|      0|    while (NULL != token) {
  ------------------
  |  Branch (336:12): [True: 0, False: 0]
  ------------------
  337|      0|        uint32_t cur_count = disable_struct->additional_filters.count;
  338|      0|        enum loader_filter_string_type cur_filter_type;
  339|      0|        const char *actual_start;
  340|      0|        size_t actual_len;
  341|      0|        determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
  342|      0|        if (cur_filter_type == FILTER_STRING_SPECIAL) {
  ------------------
  |  Branch (342:13): [True: 0, False: 0]
  ------------------
  343|      0|            if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, token) || !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, token) ||
  ------------------
  |  |  124|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
  ------------------
                          if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, token) || !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, token) ||
  ------------------
  |  |  125|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
  ------------------
  |  Branch (343:17): [True: 0, False: 0]
  |  Branch (343:71): [True: 0, False: 0]
  ------------------
  344|      0|                !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, token)) {
  ------------------
  |  |  126|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
  ------------------
  |  Branch (344:17): [True: 0, False: 0]
  ------------------
  345|      0|                disable_struct->disable_all = true;
  346|      0|            } else if (!strcmp(VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR, token)) {
  ------------------
  |  |  127|      0|#define VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR "~implicit~"
  ------------------
  |  Branch (346:24): [True: 0, False: 0]
  ------------------
  347|      0|                disable_struct->disable_all_implicit = true;
  348|      0|            } else if (!strcmp(VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR, token)) {
  ------------------
  |  |  128|      0|#define VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR "~explicit~"
  ------------------
  |  Branch (348:24): [True: 0, False: 0]
  ------------------
  349|      0|                disable_struct->disable_all_explicit = true;
  350|      0|            }
  351|      0|        } else {
  352|       |            // Keep the stored length in sync with what actually fits (value is VK_MAX_EXTENSION_NAME_SIZE bytes including
  353|       |            // the null terminator) so the matcher never reads past the buffer.
  354|      0|            size_t stored_len = actual_len < VK_MAX_EXTENSION_NAME_SIZE - 1 ? actual_len : VK_MAX_EXTENSION_NAME_SIZE - 1;
  ------------------
  |  Branch (354:33): [True: 0, False: 0]
  ------------------
  355|      0|            loader_strncpy(disable_struct->additional_filters.filters[cur_count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start,
  356|      0|                           stored_len);
  357|      0|            disable_struct->additional_filters.filters[cur_count].value[stored_len] = '\0';
  358|      0|            disable_struct->additional_filters.filters[cur_count].length = stored_len;
  359|      0|            disable_struct->additional_filters.filters[cur_count].type = cur_filter_type;
  360|      0|            disable_struct->additional_filters.count++;
  361|      0|            if (disable_struct->additional_filters.count >= MAX_ADDITIONAL_FILTERS) {
  ------------------
  |  |  530|      0|#define MAX_ADDITIONAL_FILTERS 16
  ------------------
  |  Branch (361:17): [True: 0, False: 0]
  ------------------
  362|      0|                break;
  363|      0|            }
  364|      0|        }
  365|      0|        token = thread_safe_strtok(NULL, ",", &context);
  366|      0|    }
  367|  8.37k|out:
  368|  8.37k|    loader_instance_heap_free(inst, parsing_string);
  369|  8.37k|    loader_free_getenv(env_var_value, inst);
  370|  8.37k|    return result;
  371|      0|}
parse_layer_environment_var_filters:
  374|  8.37k|VkResult parse_layer_environment_var_filters(const struct loader_instance *inst, struct loader_envvar_all_filters *layer_filters) {
  375|  8.37k|    VkResult res = parse_generic_filter_environment_var(inst, VK_LAYERS_ENABLE_ENV_VAR, &layer_filters->enable_filter);
  ------------------
  |  |  119|  8.37k|#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
  ------------------
  376|  8.37k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (376:9): [True: 0, False: 8.37k]
  ------------------
  377|      0|        return res;
  378|      0|    }
  379|  8.37k|    res = parse_layers_disable_filter_environment_var(inst, &layer_filters->disable_filter);
  380|  8.37k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (380:9): [True: 0, False: 8.37k]
  ------------------
  381|      0|        return res;
  382|      0|    }
  383|  8.37k|    res = parse_generic_filter_environment_var(inst, VK_LAYERS_ALLOW_ENV_VAR, &layer_filters->allow_filter);
  ------------------
  |  |  121|  8.37k|#define VK_LAYERS_ALLOW_ENV_VAR "VK_LOADER_LAYERS_ALLOW"
  ------------------
  384|  8.37k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (384:9): [True: 0, False: 8.37k]
  ------------------
  385|      0|        return res;
  386|      0|    }
  387|  8.37k|    return res;
  388|  8.37k|}
check_name_matches_filter_environment_var:
  409|  4.34M|bool check_name_matches_filter_environment_var(const char *name, const struct loader_envvar_filter *filter_struct) {
  410|  4.34M|    bool ret_value = false;
  411|  4.34M|    size_t name_len = strlen(name);
  412|       |    // Compare each filter against `name` directly. name_segment_matches_filter_value does a case-insensitive compare
  413|       |    // (filter values are already lowercased at parse time), so there's no need to make a lowercased copy of name first
  414|       |    // and no limit on how long name can be.
  415|  6.51M|    for (uint32_t filt = 0; filt < filter_struct->count; ++filt) {
  ------------------
  |  Branch (415:29): [True: 2.17M, False: 4.34M]
  ------------------
  416|  2.17M|        const struct loader_envvar_filter_value *filter = &filter_struct->filters[filt];
  417|       |        // The filter (with its wildcards stripped) is longer than the name, so it can't possibly match.
  418|  2.17M|        if (filter->length > name_len) {
  ------------------
  |  Branch (418:13): [True: 2.14M, False: 29.1k]
  ------------------
  419|  2.14M|            continue;
  420|  2.14M|        }
  421|  29.1k|        switch (filter->type) {
  ------------------
  |  Branch (421:17): [True: 29.1k, False: 0]
  ------------------
  422|      0|            case FILTER_STRING_SPECIAL:
  ------------------
  |  Branch (422:13): [True: 0, False: 29.1k]
  ------------------
  423|      0|                if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, filter->value) ||
  ------------------
  |  |  124|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
  ------------------
  |  Branch (423:21): [True: 0, False: 0]
  ------------------
  424|      0|                    !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, filter->value) ||
  ------------------
  |  |  125|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
  ------------------
  |  Branch (424:21): [True: 0, False: 0]
  ------------------
  425|      0|                    !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, filter->value)) {
  ------------------
  |  |  126|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
  ------------------
  |  Branch (425:21): [True: 0, False: 0]
  ------------------
  426|      0|                    ret_value = true;
  427|      0|                }
  428|      0|                break;
  429|       |
  430|      0|            case FILTER_STRING_SUBSTRING:
  ------------------
  |  Branch (430:13): [True: 0, False: 29.1k]
  ------------------
  431|       |                // Slide the filter along the name looking for a match, stopping as soon as one is found.
  432|      0|                for (size_t start = 0; start + filter->length <= name_len; ++start) {
  ------------------
  |  Branch (432:40): [True: 0, False: 0]
  ------------------
  433|      0|                    if (name_segment_matches_filter_value(name + start, filter->value, filter->length)) {
  ------------------
  |  Branch (433:25): [True: 0, False: 0]
  ------------------
  434|      0|                        ret_value = true;
  435|      0|                        break;
  436|      0|                    }
  437|      0|                }
  438|      0|                break;
  439|       |
  440|      0|            case FILTER_STRING_SUFFIX:
  ------------------
  |  Branch (440:13): [True: 0, False: 29.1k]
  ------------------
  441|      0|                ret_value = name_segment_matches_filter_value(name + name_len - filter->length, filter->value, filter->length);
  442|      0|                break;
  443|       |
  444|      0|            case FILTER_STRING_PREFIX:
  ------------------
  |  Branch (444:13): [True: 0, False: 29.1k]
  ------------------
  445|      0|                ret_value = name_segment_matches_filter_value(name, filter->value, filter->length);
  446|      0|                break;
  447|       |
  448|  29.1k|            case FILTER_STRING_FULLNAME:
  ------------------
  |  Branch (448:13): [True: 29.1k, False: 0]
  ------------------
  449|  29.1k|                ret_value = (name_len == filter->length) && name_segment_matches_filter_value(name, filter->value, filter->length);
  ------------------
  |  Branch (449:29): [True: 2.84k, False: 26.2k]
  |  Branch (449:61): [True: 448, False: 2.39k]
  ------------------
  450|  29.1k|                break;
  451|  29.1k|        }
  452|  29.1k|        if (ret_value) {
  ------------------
  |  Branch (452:13): [True: 448, False: 28.6k]
  ------------------
  453|    448|            break;
  454|    448|        }
  455|  29.1k|    }
  456|  4.34M|    return ret_value;
  457|  4.34M|}
loader_environment.c:name_segment_matches_filter_value:
  394|  2.84k|static bool name_segment_matches_filter_value(const char *name_segment, const char *lowercase_filter_value, size_t count) {
  395|  4.28k|    for (size_t iii = 0; iii < count; ++iii) {
  ------------------
  |  Branch (395:26): [True: 3.84k, False: 448]
  ------------------
  396|  3.84k|        if ((char)tolower((unsigned char)name_segment[iii]) != lowercase_filter_value[iii]) {
  ------------------
  |  Branch (396:13): [True: 2.39k, False: 1.44k]
  |  Branch (396:19): [True: 0, False: 0]
  |  Branch (396:19): [True: 0, False: 0]
  |  Branch (396:19): [Folded, False: 3.84k]
  ------------------
  397|  2.39k|            return false;
  398|  2.39k|        }
  399|  3.84k|    }
  400|    448|    return true;
  401|  2.84k|}

loader_get_json:
  164|   115k|TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
  165|   115k|    char *json_buf = NULL;
  166|   115k|    VkResult res = VK_SUCCESS;
  167|       |
  168|   115k|    assert(json != NULL);
  169|       |
  170|   115k|    size_t json_len = 0;
  171|   115k|    *json = NULL;
  172|   115k|    res = loader_read_entire_file(inst, filename, &json_len, &json_buf);
  173|   115k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (173:9): [True: 4.07k, False: 111k]
  ------------------
  174|  4.07k|        goto out;
  175|  4.07k|    }
  176|   115k|    bool out_of_memory = false;
  177|       |    // Parse text from file
  178|   111k|    *json = loader_cJSON_ParseWithLength(inst ? &inst->alloc_callbacks : NULL, json_buf, json_len, &out_of_memory);
  ------------------
  |  Branch (178:42): [True: 111k, False: 0]
  ------------------
  179|   111k|    if (out_of_memory) {
  ------------------
  |  Branch (179:9): [True: 0, False: 111k]
  ------------------
  180|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Out of Memory error occurred while parsing JSON file %s.",
  181|      0|                   filename);
  182|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  183|      0|        goto out;
  184|   111k|    } else if (*json == NULL) {
  ------------------
  |  Branch (184:16): [True: 29.4k, False: 82.0k]
  ------------------
  185|  29.4k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Invalid JSON file %s.", filename);
  186|  29.4k|        goto out;
  187|  29.4k|    }
  188|       |
  189|   115k|out:
  190|   115k|    loader_instance_heap_free(inst, json_buf);
  191|   115k|    if (res != VK_SUCCESS && *json != NULL) {
  ------------------
  |  Branch (191:9): [True: 4.07k, False: 111k]
  |  Branch (191:30): [True: 0, False: 4.07k]
  ------------------
  192|      0|        loader_cJSON_Delete(*json);
  193|      0|        *json = NULL;
  194|      0|    }
  195|       |
  196|   115k|    return res;
  197|   111k|}
loader_parse_json_string_to_existing_str:
  199|  8.17M|VkResult loader_parse_json_string_to_existing_str(cJSON *object, const char *key, size_t out_str_len, char *out_string) {
  200|  8.17M|    if (NULL == key) {
  ------------------
  |  Branch (200:9): [True: 0, False: 8.17M]
  ------------------
  201|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  202|      0|    }
  203|  8.17M|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  204|  8.17M|    if (NULL == item) {
  ------------------
  |  Branch (204:9): [True: 832k, False: 7.33M]
  ------------------
  205|   832k|        return VK_ERROR_INITIALIZATION_FAILED;
  206|   832k|    }
  207|       |
  208|  7.33M|    if (item->type != cJSON_String || item->valuestring == NULL) {
  ------------------
  |  |  101|  14.6M|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (208:9): [True: 4.73k, False: 7.33M]
  |  Branch (208:39): [True: 0, False: 7.33M]
  ------------------
  209|  4.73k|        return VK_ERROR_INITIALIZATION_FAILED;
  210|  4.73k|    }
  211|  7.33M|    bool out_of_memory = false;
  212|  7.33M|    bool success = loader_cJSON_PrintPreallocated(item, out_string, (int)out_str_len, cJSON_False);
  ------------------
  |  |   97|  7.33M|#define cJSON_False (1 << 0)
  ------------------
  213|  7.33M|    if (out_of_memory) {
  ------------------
  |  Branch (213:9): [True: 0, False: 7.33M]
  ------------------
  214|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  215|      0|    }
  216|  7.33M|    if (!success) {
  ------------------
  |  Branch (216:9): [True: 5.60k, False: 7.32M]
  ------------------
  217|  5.60k|        return VK_ERROR_INITIALIZATION_FAILED;
  218|  5.60k|    }
  219|  7.32M|    return VK_SUCCESS;
  220|  7.33M|}
loader_parse_json_string:
  222|  3.13M|VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string) {
  223|  3.13M|    if (NULL == key) {
  ------------------
  |  Branch (223:9): [True: 0, False: 3.13M]
  ------------------
  224|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  225|      0|    }
  226|       |
  227|  3.13M|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  228|  3.13M|    if (NULL == item || NULL == item->valuestring) {
  ------------------
  |  Branch (228:9): [True: 1.00M, False: 2.13M]
  |  Branch (228:25): [True: 1.61k, False: 2.13M]
  ------------------
  229|  1.00M|        return VK_ERROR_INITIALIZATION_FAILED;
  230|  1.00M|    }
  231|       |
  232|  3.13M|    bool out_of_memory = false;
  233|  2.13M|    char *str = loader_cJSON_Print(item, &out_of_memory);
  234|  2.13M|    if (out_of_memory || NULL == str) {
  ------------------
  |  Branch (234:9): [True: 0, False: 2.13M]
  |  Branch (234:26): [True: 0, False: 2.13M]
  ------------------
  235|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  236|      0|    }
  237|  2.13M|    if (NULL != out_string) {
  ------------------
  |  Branch (237:9): [True: 2.13M, False: 0]
  ------------------
  238|  2.13M|        *out_string = str;
  239|  2.13M|    }
  240|  2.13M|    return VK_SUCCESS;
  241|  2.13M|}
loader_parse_json_array_of_strings:
  243|  2.85M|                                            struct loader_string_list *string_list) {
  244|  2.85M|    if (NULL == key) {
  ------------------
  |  Branch (244:9): [True: 0, False: 2.85M]
  ------------------
  245|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  246|      0|    }
  247|  2.85M|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  248|  2.85M|    if (NULL == item) {
  ------------------
  |  Branch (248:9): [True: 2.41M, False: 437k]
  ------------------
  249|  2.41M|        return VK_ERROR_INITIALIZATION_FAILED;
  250|  2.41M|    }
  251|       |
  252|   437k|    uint32_t count = loader_cJSON_GetArraySize(item);
  253|   437k|    if (count == 0) {
  ------------------
  |  Branch (253:9): [True: 241k, False: 195k]
  ------------------
  254|   241k|        return VK_SUCCESS;
  255|   241k|    }
  256|       |
  257|   195k|    VkResult res = create_string_list(inst, count, string_list);
  258|   195k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (258:9): [True: 0, False: 195k]
  ------------------
  259|      0|        goto out;
  260|      0|    }
  261|   195k|    cJSON *element = NULL;
  262|  1.01M|    cJSON_ArrayForEach(element, item) {
  ------------------
  |  |  213|  1.19M|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 195k, False: 0]
  |  |  |  Branch (213:61): [True: 1.01M, False: 172k]
  |  |  ------------------
  ------------------
  263|  1.01M|        if (element->type != cJSON_String) {
  ------------------
  |  |  101|  1.01M|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (263:13): [True: 22.4k, False: 997k]
  ------------------
  264|  22.4k|            return VK_ERROR_INITIALIZATION_FAILED;
  265|  22.4k|        }
  266|  1.01M|        bool out_of_memory = false;
  267|   997k|        char *out_data = loader_cJSON_Print(element, &out_of_memory);
  268|   997k|        if (out_of_memory) {
  ------------------
  |  Branch (268:13): [True: 0, False: 997k]
  ------------------
  269|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  270|      0|            goto out;
  271|      0|        }
  272|   997k|        res = append_str_to_string_list(inst, string_list, out_data);
  273|   997k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (273:13): [True: 0, False: 997k]
  ------------------
  274|      0|            goto out;
  275|      0|        }
  276|   997k|    }
  277|   172k|out:
  278|   172k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY && NULL != string_list->list) {
  ------------------
  |  Branch (278:9): [True: 0, False: 172k]
  |  Branch (278:47): [True: 0, False: 0]
  ------------------
  279|      0|        free_string_list(inst, string_list);
  280|      0|    }
  281|       |
  282|   172k|    return res;
  283|   195k|}
loader_json.c:loader_read_entire_file:
  110|   115k|                                        char **out_buff) {
  111|   115k|    FILE *file = NULL;
  112|   115k|    struct stat stats = {0};
  113|   115k|    VkResult res = VK_SUCCESS;
  114|       |
  115|       |    // fprintf(stderr, "loader_get_json: Reading JSON file %s\n", filename);
  116|   115k|    file = fopen(filename, "rb");
  117|   115k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  118|   115k|    if (file == NULL) {
  ------------------
  |  Branch (118:9): [True: 4.06k, False: 111k]
  ------------------
  119|  4.06k|        create_callback_file(filename);
  120|  4.06k|        file = fopen(filename, "rb");
  121|  4.06k|    }
  122|   115k|#endif
  123|   115k|    if (NULL == file) {
  ------------------
  |  Branch (123:9): [True: 4.06k, False: 111k]
  ------------------
  124|  4.06k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
  125|  4.06k|        res = VK_ERROR_INITIALIZATION_FAILED;
  126|  4.06k|        goto out;
  127|  4.06k|    }
  128|   111k|    if (-1 == fstat(fileno(file), &stats)) {
  ------------------
  |  Branch (128:9): [True: 0, False: 111k]
  ------------------
  129|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read file size of JSON file %s", filename);
  130|      0|        res = VK_ERROR_INITIALIZATION_FAILED;
  131|      0|        goto out;
  132|      0|    }
  133|   111k|    *out_buff = (char *)loader_instance_heap_calloc(inst, stats.st_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  134|   111k|    if (NULL == *out_buff) {
  ------------------
  |  Branch (134:9): [True: 0, False: 111k]
  ------------------
  135|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to allocate memory to read JSON file %s", filename);
  136|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  137|      0|        goto out;
  138|      0|    }
  139|   111k|    if (stats.st_size != (long int)fread(*out_buff, sizeof(char), stats.st_size, file)) {
  ------------------
  |  Branch (139:9): [True: 6, False: 111k]
  ------------------
  140|      6|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read entire JSON file %s", filename);
  141|      6|        res = VK_ERROR_INITIALIZATION_FAILED;
  142|      6|        goto out;
  143|      6|    }
  144|   111k|    *out_len = stats.st_size + 1;
  145|       |    // out_buff was allocated with stats.st_size + 1 bytes above, and the fread check already verified the file's
  146|       |    // contents did not change size out from under us; this is the last valid byte.
  147|       |    // NOLINTNEXTLINE(clang-analyzer-security.ArrayBound)
  148|   111k|    (*out_buff)[stats.st_size] = '\0';
  149|       |
  150|   115k|out:
  151|   115k|    if (NULL != file) {
  ------------------
  |  Branch (151:9): [True: 111k, False: 4.06k]
  ------------------
  152|       |        // NOLINTNEXTLINE(cert-err33-c) - file was only opened for reading, nothing to flush; res already reflects any read failure
  153|   111k|        fclose(file);
  154|   111k|    }
  155|   115k|    return res;
  156|   111k|}

loader_init_global_debug_level:
   42|      2|void loader_init_global_debug_level(void) {
   43|      2|    char *env;
   44|      2|    char *orig;
   45|       |
   46|      2|    if (g_loader_debug > 0) return;
  ------------------
  |  Branch (46:9): [True: 0, False: 2]
  ------------------
   47|       |
   48|      2|    g_loader_debug = 0;
   49|       |
   50|       |    // Parse comma-separated debug options
   51|      2|    orig = env = loader_getenv("VK_LOADER_DEBUG", NULL);
   52|      2|    while (env) {
  ------------------
  |  Branch (52:12): [True: 0, False: 2]
  ------------------
   53|      0|        char *p = strchr(env, ',');
   54|      0|        size_t len;
   55|       |
   56|      0|        if (p) {
  ------------------
  |  Branch (56:13): [True: 0, False: 0]
  ------------------
   57|      0|            len = p - env;
   58|      0|        } else {
   59|      0|            len = strlen(env);
   60|      0|        }
   61|       |
   62|      0|        if (len > 0) {
  ------------------
  |  Branch (62:13): [True: 0, False: 0]
  ------------------
   63|      0|            if (strncmp(env, "all", len) == 0) {
  ------------------
  |  Branch (63:17): [True: 0, False: 0]
  ------------------
   64|      0|                g_loader_debug = ~0u;
   65|      0|            } else if (strncmp(env, "warn", len) == 0) {
  ------------------
  |  Branch (65:24): [True: 0, False: 0]
  ------------------
   66|      0|                g_loader_debug |= VULKAN_LOADER_WARN_BIT;
   67|      0|            } else if (strncmp(env, "info", len) == 0) {
  ------------------
  |  Branch (67:24): [True: 0, False: 0]
  ------------------
   68|      0|                g_loader_debug |= VULKAN_LOADER_INFO_BIT;
   69|      0|            } else if (strncmp(env, "perf", len) == 0) {
  ------------------
  |  Branch (69:24): [True: 0, False: 0]
  ------------------
   70|      0|                g_loader_debug |= VULKAN_LOADER_PERF_BIT;
   71|      0|            } else if (strncmp(env, "error", len) == 0) {
  ------------------
  |  Branch (71:24): [True: 0, False: 0]
  ------------------
   72|      0|                g_loader_debug |= VULKAN_LOADER_ERROR_BIT;
   73|      0|            } else if (strncmp(env, "debug", len) == 0) {
  ------------------
  |  Branch (73:24): [True: 0, False: 0]
  ------------------
   74|      0|                g_loader_debug |= VULKAN_LOADER_DEBUG_BIT;
   75|      0|            } else if (strncmp(env, "layer", len) == 0) {
  ------------------
  |  Branch (75:24): [True: 0, False: 0]
  ------------------
   76|      0|                g_loader_debug |= VULKAN_LOADER_LAYER_BIT;
   77|      0|            } else if (strncmp(env, "driver", len) == 0 || strncmp(env, "implem", len) == 0 || strncmp(env, "icd", len) == 0) {
  ------------------
  |  Branch (77:24): [True: 0, False: 0]
  |  Branch (77:60): [True: 0, False: 0]
  |  Branch (77:96): [True: 0, False: 0]
  ------------------
   78|      0|                g_loader_debug |= VULKAN_LOADER_DRIVER_BIT;
   79|      0|            }
   80|      0|        }
   81|       |
   82|      0|        if (!p) break;
  ------------------
  |  Branch (82:13): [True: 0, False: 0]
  ------------------
   83|       |
   84|      0|        env = p + 1;
   85|      0|    }
   86|       |
   87|       |    loader_free_getenv(orig, NULL);
   88|      2|}
generate_debug_flag_str:
   93|  1.24k|void generate_debug_flag_str(VkFlags msg_type, size_t cmd_line_size, char *cmd_line_msg) {
   94|  1.24k|    cmd_line_msg[0] = '\0';
   95|       |
   96|  1.24k|    if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (96:9): [True: 101, False: 1.14k]
  ------------------
   97|    101|        loader_strncat(cmd_line_msg, cmd_line_size, "ERROR", sizeof("ERROR"));
   98|    101|    }
   99|  1.24k|    if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (99:9): [True: 106, False: 1.14k]
  ------------------
  100|    106|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (100:13): [True: 91, False: 15]
  ------------------
  101|     91|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  102|     91|        }
  103|    106|        loader_strncat(cmd_line_msg, cmd_line_size, "WARNING", sizeof("WARNING"));
  104|    106|    }
  105|  1.24k|    if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (105:9): [True: 109, False: 1.13k]
  ------------------
  106|    109|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (106:13): [True: 94, False: 15]
  ------------------
  107|     94|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  108|     94|        }
  109|    109|        loader_strncat(cmd_line_msg, cmd_line_size, "INFO", sizeof("INFO"));
  110|    109|    }
  111|  1.24k|    if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (111:9): [True: 114, False: 1.13k]
  ------------------
  112|    114|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (112:13): [True: 94, False: 20]
  ------------------
  113|     94|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  114|     94|        }
  115|    114|        loader_strncat(cmd_line_msg, cmd_line_size, "DEBUG", sizeof("DEBUG"));
  116|    114|    }
  117|  1.24k|    if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (117:9): [True: 116, False: 1.13k]
  ------------------
  118|    116|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (118:13): [True: 102, False: 14]
  ------------------
  119|    102|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  120|    102|        }
  121|    116|        loader_strncat(cmd_line_msg, cmd_line_size, "PERF", sizeof("PERF"));
  122|    116|    }
  123|  1.24k|    if ((msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (123:9): [True: 115, False: 1.13k]
  ------------------
  124|    115|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (124:13): [True: 101, False: 14]
  ------------------
  125|    101|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  126|    101|        }
  127|    115|        loader_strncat(cmd_line_msg, cmd_line_size, "DRIVER", sizeof("DRIVER"));
  128|    115|    }
  129|  1.24k|    if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
  ------------------
  |  Branch (129:9): [True: 115, False: 1.13k]
  ------------------
  130|    115|        if (strlen(cmd_line_msg) > 0) {
  ------------------
  |  Branch (130:13): [True: 100, False: 15]
  ------------------
  131|    100|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  132|    100|        }
  133|    115|        loader_strncat(cmd_line_msg, cmd_line_size, "LAYER", sizeof("LAYER"));
  134|    115|    }
  135|       |
  136|  1.24k|#undef STRNCAT_TO_BUFFER
  137|  1.24k|}
loader_log:
  141|  10.4M|    loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...) {
  142|  10.4M|    (void)msg_code;
  143|  10.4M|    char msg[512] = {0};
  144|       |
  145|  10.4M|    va_list ap;
  146|  10.4M|    va_start(ap, format);
  147|  10.4M|    int ret = vsnprintf(msg, sizeof(msg), format, ap);
  148|  10.4M|    if ((ret >= (int)sizeof(msg)) || ret < 0) {
  ------------------
  |  Branch (148:9): [True: 8.15k, False: 10.4M]
  |  Branch (148:38): [True: 0, False: 10.4M]
  ------------------
  149|  8.15k|        msg[sizeof(msg) - 1] = '\0';
  150|  8.15k|    }
  151|  10.4M|    va_end(ap);
  152|       |
  153|  10.4M|    if (inst) {
  ------------------
  |  Branch (153:9): [True: 10.4M, False: 2]
  ------------------
  154|       |        // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) - external Vulkan enum, has no zero value we can add
  155|  10.4M|        VkDebugUtilsMessageSeverityFlagBitsEXT severity = 0;
  156|  10.4M|        VkDebugUtilsMessageTypeFlagsEXT type = 0;
  157|  10.4M|        VkDebugUtilsMessengerCallbackDataEXT callback_data = {0};
  158|  10.4M|        VkDebugUtilsObjectNameInfoEXT object_name = {0};
  159|       |
  160|       |        // NOLINTNEXTLINE(bugprone-branch-clone) - duplicated so combined bit calls (e.g. WARN_BIT|LAYER_BIT) match first branch
  161|  10.4M|        if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (161:13): [True: 884k, False: 9.55M]
  ------------------
  162|   884k|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
  163|  9.55M|        } else if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (163:20): [True: 8.65M, False: 896k]
  ------------------
  164|  8.65M|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
  165|  8.65M|        } else if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (165:20): [True: 60.3k, False: 836k]
  ------------------
  166|  60.3k|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  167|   836k|        } else if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (167:20): [True: 531k, False: 304k]
  ------------------
  168|   531k|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
  169|   531k|        } else if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0 || (msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (169:20): [True: 294k, False: 10.0k]
  |  Branch (169:65): [True: 10.0k, False: 0]
  ------------------
  170|       |            // Just driver or just layer bit should be treated as an info message in debug utils.
  171|   304k|            severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
  172|   304k|        }
  173|       |
  174|  10.4M|        if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (174:13): [True: 0, False: 10.4M]
  ------------------
  175|      0|            type = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
  176|  10.4M|        } else if ((msg_type & VULKAN_LOADER_VALIDATION_BIT) != 0) {
  ------------------
  |  Branch (176:20): [True: 0, False: 10.4M]
  ------------------
  177|       |            // For loader logging, if it's a validation message, we still want to also keep the general flag as well
  178|       |            // so messages of type validation can still be triggered for general message callbacks.
  179|      0|            type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
  180|  10.4M|        } else {
  181|  10.4M|            type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
  182|  10.4M|        }
  183|       |
  184|  10.4M|        callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
  185|  10.4M|        callback_data.pMessageIdName = "Loader Message";
  186|  10.4M|        callback_data.pMessage = msg;
  187|  10.4M|        callback_data.objectCount = 1;
  188|  10.4M|        callback_data.pObjects = &object_name;
  189|  10.4M|        object_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  190|  10.4M|        object_name.objectType = VK_OBJECT_TYPE_INSTANCE;
  191|  10.4M|        object_name.objectHandle = (uint64_t)(uintptr_t)inst;
  192|       |
  193|  10.4M|        util_SubmitDebugUtilsMessageEXT(inst, severity, type, &callback_data);
  194|  10.4M|    }
  195|       |
  196|       |    // Always log to stderr if this is a fatal error
  197|  10.4M|    if (0 == (msg_type & VULKAN_LOADER_FATAL_ERROR_BIT)) {
  ------------------
  |  Branch (197:9): [True: 10.4M, False: 0]
  ------------------
  198|  10.4M|        if (inst && inst->settings.settings_active && inst->settings.debug_level > 0) {
  ------------------
  |  Branch (198:13): [True: 10.4M, False: 2]
  |  Branch (198:21): [True: 1.69M, False: 8.74M]
  |  Branch (198:55): [True: 699k, False: 991k]
  ------------------
  199|       |            // Exit early if the current instance settings have some debugging options but do match the current msg_type
  200|   699k|            if (0 == (msg_type & inst->settings.debug_level)) {
  ------------------
  |  Branch (200:17): [True: 2.62k, False: 696k]
  ------------------
  201|  2.62k|                return;
  202|  2.62k|            }
  203|       |            // Check the global settings and if that doesn't say to skip, check the environment variable
  204|  9.73M|        } else if (0 == (msg_type & g_loader_debug)) {
  ------------------
  |  Branch (204:20): [True: 9.73M, False: 0]
  ------------------
  205|  9.73M|            return;
  206|  9.73M|        }
  207|  10.4M|    }
  208|       |
  209|       |#if defined(DEBUG)
  210|       |    int debug_flag_mask =
  211|       |        (int)(msg_type & (VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DEBUG_BIT));
  212|       |    assert((debug_flag_mask == 0 || debug_flag_mask == VULKAN_LOADER_ERROR_BIT || debug_flag_mask == VULKAN_LOADER_WARN_BIT ||
  213|       |            debug_flag_mask == VULKAN_LOADER_INFO_BIT || debug_flag_mask == VULKAN_LOADER_DEBUG_BIT) &&
  214|       |           "This log has more than one exclusive debug flags (error, warn, info, debug) set");
  215|       |#endif
  216|       |
  217|       |    // Only need enough space to create the filter description header for log messages
  218|       |    // Also use the same header for all output
  219|   696k|    char cmd_line_msg[64] = {0};
  220|   696k|    size_t cmd_line_size = sizeof(cmd_line_msg);
  221|       |
  222|   696k|    loader_strncat(cmd_line_msg, cmd_line_size, "[Vulkan Loader] ", sizeof("[Vulkan Loader] "));
  223|       |
  224|   696k|    bool need_separator = false;
  225|   696k|    if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
  ------------------
  |  Branch (225:9): [True: 3.07k, False: 693k]
  ------------------
  226|  3.07k|        loader_strncat(cmd_line_msg, cmd_line_size, "ERROR", sizeof("ERROR"));
  227|  3.07k|        need_separator = true;
  228|   693k|    } else if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
  ------------------
  |  Branch (228:16): [True: 644k, False: 49.1k]
  ------------------
  229|   644k|        loader_strncat(cmd_line_msg, cmd_line_size, "WARNING", sizeof("WARNING"));
  230|   644k|        need_separator = true;
  231|   644k|    } else if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
  ------------------
  |  Branch (231:16): [True: 25.1k, False: 23.9k]
  ------------------
  232|  25.1k|        loader_strncat(cmd_line_msg, cmd_line_size, "INFO", sizeof("INFO"));
  233|  25.1k|        need_separator = true;
  234|  25.1k|    } else if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
  ------------------
  |  Branch (234:16): [True: 10.9k, False: 13.0k]
  ------------------
  235|  10.9k|        loader_strncat(cmd_line_msg, cmd_line_size, "DEBUG", sizeof("DEBUG"));
  236|  10.9k|        need_separator = true;
  237|  10.9k|    }
  238|       |
  239|   696k|    if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
  ------------------
  |  Branch (239:9): [True: 0, False: 696k]
  ------------------
  240|      0|        if (need_separator) {
  ------------------
  |  Branch (240:13): [True: 0, False: 0]
  ------------------
  241|      0|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  242|      0|        }
  243|      0|        loader_strncat(cmd_line_msg, cmd_line_size, "PERF", sizeof("PERF"));
  244|   696k|    } else if ((msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
  ------------------
  |  Branch (244:16): [True: 58, False: 696k]
  ------------------
  245|     58|        if (need_separator) {
  ------------------
  |  Branch (245:13): [True: 10, False: 48]
  ------------------
  246|     10|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  247|     10|        }
  248|     58|        loader_strncat(cmd_line_msg, cmd_line_size, "DRIVER", sizeof("DRIVER"));
  249|   696k|    } else if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
  ------------------
  |  Branch (249:16): [True: 46.5k, False: 649k]
  ------------------
  250|  46.5k|        if (need_separator) {
  ------------------
  |  Branch (250:13): [True: 33.5k, False: 13.0k]
  ------------------
  251|  33.5k|            loader_strncat(cmd_line_msg, cmd_line_size, " | ", sizeof(" | "));
  252|  33.5k|        }
  253|  46.5k|        loader_strncat(cmd_line_msg, cmd_line_size, "LAYER", sizeof("LAYER"));
  254|  46.5k|    }
  255|       |
  256|   696k|    loader_strncat(cmd_line_msg, cmd_line_size, ": ", sizeof(": "));
  257|   696k|    size_t num_used = strlen(cmd_line_msg);
  258|       |
  259|       |    // Justifies the output to at least 29 spaces
  260|   696k|    if (num_used < 32) {
  ------------------
  |  Branch (260:9): [True: 682k, False: 13.4k]
  ------------------
  261|   682k|        const char space_buffer[] = "                                ";
  262|       |        // Only write (32 - num_used) spaces
  263|   682k|        loader_strncat(cmd_line_msg, cmd_line_size, space_buffer, sizeof(space_buffer) - 1 - num_used);
  264|   682k|    }
  265|       |    // Assert that we didn't write more than what is available in cmd_line_msg
  266|   696k|    assert(cmd_line_size > num_used);
  267|       |
  268|       |    // NOLINTBEGIN(cert-err33-c) - this is the logger itself; no sane recovery from a failed stderr write
  269|       |    //fputs(cmd_line_msg, stderr);
  270|       |    //fputs(msg, stderr);
  271|       |    //fputc('\n', stderr);
  272|       |    // NOLINTEND(cert-err33-c)
  273|       |#if defined(WIN32)
  274|       |    OutputDebugString(cmd_line_msg);
  275|       |    OutputDebugString(msg);
  276|       |    OutputDebugString("\n");
  277|       |#endif
  278|   696k|}

free_layer_configuration:
   41|   170k|void free_layer_configuration(const struct loader_instance* inst, loader_settings_layer_configuration* layer_configuration) {
   42|   170k|    loader_instance_heap_free(inst, layer_configuration->name);
   43|   170k|    loader_instance_heap_free(inst, layer_configuration->path);
   44|   170k|    memset(layer_configuration, 0, sizeof(loader_settings_layer_configuration));
   45|   170k|}
free_loader_settings:
   57|  8.37k|void free_loader_settings(const struct loader_instance* inst, loader_settings* settings) {
   58|  8.37k|    if (NULL != settings->layer_configurations) {
  ------------------
  |  Branch (58:9): [True: 957, False: 7.41k]
  ------------------
   59|   136k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (59:30): [True: 135k, False: 957]
  ------------------
   60|   135k|            free_layer_configuration(inst, &settings->layer_configurations[i]);
   61|   135k|        }
   62|    957|        loader_instance_heap_free(inst, settings->layer_configurations);
   63|    957|    }
   64|  8.37k|    if (NULL != settings->additional_drivers) {
  ------------------
  |  Branch (64:9): [True: 0, False: 8.37k]
  ------------------
   65|      0|        for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (65:30): [True: 0, False: 0]
  ------------------
   66|      0|            free_driver_configuration(inst, &settings->additional_drivers[i]);
   67|      0|        }
   68|      0|        loader_instance_heap_free(inst, settings->additional_drivers);
   69|      0|    }
   70|  8.37k|    if (NULL != settings->device_configurations) {
  ------------------
  |  Branch (70:9): [True: 0, False: 8.37k]
  ------------------
   71|      0|        for (uint32_t i = 0; i < settings->device_configuration_count; i++) {
  ------------------
  |  Branch (71:30): [True: 0, False: 0]
  ------------------
   72|      0|            free_device_configuration(inst, &settings->device_configurations[i]);
   73|      0|        }
   74|      0|        loader_instance_heap_free(inst, settings->device_configurations);
   75|      0|    }
   76|  8.37k|    loader_instance_heap_free(inst, settings->settings_file_path);
   77|  8.37k|    memset(settings, 0, sizeof(loader_settings));
   78|  8.37k|}
parse_control_string:
   80|   137k|loader_settings_layer_control parse_control_string(char* control_string) {
   81|   137k|    loader_settings_layer_control layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   82|   137k|    if (strcmp(control_string, "auto") == 0)
  ------------------
  |  Branch (82:9): [True: 492, False: 136k]
  ------------------
   83|    492|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   84|   136k|    else if (strcmp(control_string, "on") == 0)
  ------------------
  |  Branch (84:14): [True: 450, False: 136k]
  ------------------
   85|    450|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_ON;
   86|   136k|    else if (strcmp(control_string, "off") == 0)
  ------------------
  |  Branch (86:14): [True: 15.5k, False: 120k]
  ------------------
   87|  15.5k|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_OFF;
   88|   120k|    else if (strcmp(control_string, "unordered_layer_location") == 0)
  ------------------
  |  Branch (88:14): [True: 115k, False: 4.97k]
  ------------------
   89|   115k|        layer_control = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
   90|   137k|    return layer_control;
   91|   137k|}
loader_settings_layer_control_to_string:
   93|   135k|const char* loader_settings_layer_control_to_string(loader_settings_layer_control control) {
   94|   135k|    switch (control) {
   95|  4.60k|        case LOADER_SETTINGS_LAYER_CONTROL_DEFAULT:
  ------------------
  |  Branch (95:9): [True: 4.60k, False: 130k]
  ------------------
   96|  4.60k|            return "auto";
   97|    256|        case LOADER_SETTINGS_LAYER_CONTROL_ON:
  ------------------
  |  Branch (97:9): [True: 256, False: 135k]
  ------------------
   98|    256|            return "on";
   99|  15.3k|        case LOADER_SETTINGS_LAYER_CONTROL_OFF:
  ------------------
  |  Branch (99:9): [True: 15.3k, False: 120k]
  ------------------
  100|  15.3k|            return "off";
  101|   115k|        case LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION:
  ------------------
  |  Branch (101:9): [True: 115k, False: 20.1k]
  ------------------
  102|   115k|            return "unordered_layer_location";
  103|      0|        default:
  ------------------
  |  Branch (103:9): [True: 0, False: 135k]
  ------------------
  104|      0|            return "UNKNOWN_LAYER_CONTROl";
  105|   135k|    }
  106|   135k|}
parse_log_filters_from_strings:
  108|    555|uint32_t parse_log_filters_from_strings(struct loader_string_list* log_filters) {
  109|    555|    uint32_t filters = 0;
  110|   541k|    for (uint32_t i = 0; i < log_filters->count; i++) {
  ------------------
  |  Branch (110:26): [True: 540k, False: 555]
  ------------------
  111|   540k|        if (strcmp(log_filters->list[i], "all") == 0)
  ------------------
  |  Branch (111:13): [True: 24.3k, False: 516k]
  ------------------
  112|  24.3k|            filters |= VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_PERF_BIT | VULKAN_LOADER_ERROR_BIT |
  113|  24.3k|                       VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT | VULKAN_LOADER_VALIDATION_BIT;
  114|   516k|        else if (strcmp(log_filters->list[i], "info") == 0)
  ------------------
  |  Branch (114:18): [True: 6.79k, False: 509k]
  ------------------
  115|  6.79k|            filters |= VULKAN_LOADER_INFO_BIT;
  116|   509k|        else if (strcmp(log_filters->list[i], "warn") == 0)
  ------------------
  |  Branch (116:18): [True: 880, False: 508k]
  ------------------
  117|    880|            filters |= VULKAN_LOADER_WARN_BIT;
  118|   508k|        else if (strcmp(log_filters->list[i], "perf") == 0)
  ------------------
  |  Branch (118:18): [True: 1.36k, False: 507k]
  ------------------
  119|  1.36k|            filters |= VULKAN_LOADER_PERF_BIT;
  120|   507k|        else if (strcmp(log_filters->list[i], "error") == 0)
  ------------------
  |  Branch (120:18): [True: 220, False: 507k]
  ------------------
  121|    220|            filters |= VULKAN_LOADER_ERROR_BIT;
  122|   507k|        else if (strcmp(log_filters->list[i], "debug") == 0)
  ------------------
  |  Branch (122:18): [True: 1.41k, False: 505k]
  ------------------
  123|  1.41k|            filters |= VULKAN_LOADER_DEBUG_BIT;
  124|   505k|        else if (strcmp(log_filters->list[i], "layer") == 0)
  ------------------
  |  Branch (124:18): [True: 7.96k, False: 497k]
  ------------------
  125|  7.96k|            filters |= VULKAN_LOADER_LAYER_BIT;
  126|   497k|        else if (strcmp(log_filters->list[i], "driver") == 0)
  ------------------
  |  Branch (126:18): [True: 1.52k, False: 496k]
  ------------------
  127|  1.52k|            filters |= VULKAN_LOADER_DRIVER_BIT;
  128|   496k|        else if (strcmp(log_filters->list[i], "validation") == 0)
  ------------------
  |  Branch (128:18): [True: 281, False: 495k]
  ------------------
  129|    281|            filters |= VULKAN_LOADER_VALIDATION_BIT;
  130|   540k|    }
  131|    555|    return filters;
  132|    555|}
parse_layer_configuration:
  147|   137k|                                   loader_settings_layer_configuration* layer_configuration) {
  148|   137k|    char* control_string = NULL;
  149|   137k|    VkResult res = loader_parse_json_string(layer_configuration_json, "control", &control_string);
  150|   137k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (150:9): [True: 32, False: 137k]
  ------------------
  151|     32|        goto out;
  152|     32|    }
  153|   137k|    layer_configuration->control = parse_control_string(control_string);
  154|   137k|    loader_instance_heap_free(inst, control_string);
  155|       |
  156|       |    // If that is the only value - do no further parsing
  157|   137k|    if (layer_configuration->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (157:9): [True: 115k, False: 21.4k]
  ------------------
  158|   115k|        goto out;
  159|   115k|    }
  160|       |
  161|  21.4k|    res = loader_parse_json_string(layer_configuration_json, "name", &(layer_configuration->name));
  162|  21.4k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (162:9): [True: 229, False: 21.2k]
  ------------------
  163|    229|        goto out;
  164|    229|    }
  165|       |
  166|  21.2k|    res = loader_parse_json_string(layer_configuration_json, "path", &(layer_configuration->path));
  167|  21.2k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (167:9): [True: 11, False: 21.1k]
  ------------------
  168|     11|        goto out;
  169|     11|    }
  170|       |
  171|  21.1k|    cJSON* treat_as_implicit_manifest = loader_cJSON_GetObjectItem(layer_configuration_json, "treat_as_implicit_manifest");
  172|  21.1k|    if (treat_as_implicit_manifest && treat_as_implicit_manifest->type == cJSON_True) {
  ------------------
  |  |   98|    402|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (172:9): [True: 402, False: 20.7k]
  |  Branch (172:39): [True: 205, False: 197]
  ------------------
  173|    205|        layer_configuration->treat_as_implicit_manifest = true;
  174|    205|    }
  175|   137k|out:
  176|   137k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (176:9): [True: 272, False: 136k]
  ------------------
  177|    272|        free_layer_configuration(inst, layer_configuration);
  178|    272|    }
  179|   137k|    return res;
  180|  21.1k|}
parse_layer_configurations:
  182|  1.92k|VkResult parse_layer_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  183|  1.92k|    VkResult res = VK_SUCCESS;
  184|       |
  185|  1.92k|    cJSON* layer_configurations = loader_cJSON_GetObjectItem(settings_object, "layers");
  186|       |    // If the layers object isn't present, return early with success to allow the settings file to still apply
  187|  1.92k|    if (NULL == layer_configurations) {
  ------------------
  |  Branch (187:9): [True: 581, False: 1.34k]
  ------------------
  188|    581|        return VK_SUCCESS;
  189|    581|    }
  190|       |
  191|  1.34k|    uint32_t layer_configurations_count = loader_cJSON_GetArraySize(layer_configurations);
  192|  1.34k|    if (layer_configurations_count == 0) {
  ------------------
  |  Branch (192:9): [True: 105, False: 1.24k]
  ------------------
  193|    105|        loader_settings->layer_configurations_active = true;
  194|    105|        return VK_SUCCESS;
  195|    105|    }
  196|       |
  197|  1.24k|    loader_settings->layer_configuration_count = layer_configurations_count;
  198|       |
  199|  1.24k|    loader_settings->layer_configurations = loader_instance_heap_calloc(
  200|  1.24k|        inst, sizeof(loader_settings_layer_configuration) * layer_configurations_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  201|  1.24k|    if (NULL == loader_settings->layer_configurations) {
  ------------------
  |  Branch (201:9): [True: 0, False: 1.24k]
  ------------------
  202|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  203|      0|        goto out;
  204|      0|    }
  205|       |
  206|  1.24k|    cJSON* layer = NULL;
  207|  1.24k|    size_t i = 0;
  208|   137k|    cJSON_ArrayForEach(layer, layer_configurations) {
  ------------------
  |  |  213|   138k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 1.24k, False: 0]
  |  |  |  Branch (213:61): [True: 137k, False: 957]
  |  |  ------------------
  ------------------
  209|   137k|        if (layer->type != cJSON_Object) {
  ------------------
  |  |  103|   137k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (209:13): [True: 12, False: 137k]
  ------------------
  210|     12|            res = VK_ERROR_INITIALIZATION_FAILED;
  211|     12|            goto out;
  212|     12|        }
  213|   137k|        res = parse_layer_configuration(inst, layer, &(loader_settings->layer_configurations[i++]));
  214|   137k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (214:13): [True: 272, False: 136k]
  ------------------
  215|    272|            goto out;
  216|    272|        }
  217|   137k|    }
  218|    957|    loader_settings->layer_configurations_active = true;
  219|  1.24k|out:
  220|  1.24k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (220:9): [True: 284, False: 957]
  ------------------
  221|    284|        if (loader_settings->layer_configurations) {
  ------------------
  |  Branch (221:13): [True: 284, False: 0]
  ------------------
  222|  34.9k|            for (size_t index = 0; index < loader_settings->layer_configuration_count; index++) {
  ------------------
  |  Branch (222:36): [True: 34.6k, False: 284]
  ------------------
  223|  34.6k|                free_layer_configuration(inst, &(loader_settings->layer_configurations[index]));
  224|  34.6k|            }
  225|    284|            loader_settings->layer_configuration_count = 0;
  226|    284|            loader_instance_heap_free(inst, loader_settings->layer_configurations);
  227|    284|            loader_settings->layer_configurations = NULL;
  228|    284|        }
  229|    284|    }
  230|       |
  231|  1.24k|    return res;
  232|    957|}
parse_additional_drivers:
  248|  1.92k|VkResult parse_additional_drivers(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  249|  1.92k|    VkResult res = VK_SUCCESS;
  250|       |
  251|  1.92k|    cJSON* additional_drivers_use_exclusively_json =
  252|  1.92k|        loader_cJSON_GetObjectItem(settings_object, "additional_drivers_use_exclusively");
  253|  1.92k|    if (additional_drivers_use_exclusively_json && additional_drivers_use_exclusively_json->type == cJSON_True) {
  ------------------
  |  |   98|      0|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (253:9): [True: 0, False: 1.92k]
  |  Branch (253:52): [True: 0, False: 0]
  ------------------
  254|      0|        loader_settings->additional_drivers_use_exclusively = true;
  255|      0|    }
  256|       |
  257|  1.92k|    cJSON* additional_drivers_json = loader_cJSON_GetObjectItem(settings_object, "additional_drivers");
  258|  1.92k|    if (NULL == additional_drivers_json) {
  ------------------
  |  Branch (258:9): [True: 1.92k, False: 0]
  ------------------
  259|  1.92k|        return VK_SUCCESS;
  260|  1.92k|    }
  261|       |
  262|      0|    uint32_t additional_driver_count = loader_cJSON_GetArraySize(additional_drivers_json);
  263|      0|    if (additional_driver_count == 0) {
  ------------------
  |  Branch (263:9): [True: 0, False: 0]
  ------------------
  264|      0|        return VK_SUCCESS;
  265|      0|    }
  266|       |
  267|      0|    loader_settings->additional_driver_count = additional_driver_count;
  268|       |
  269|      0|    loader_settings->additional_drivers = loader_instance_heap_calloc(
  270|      0|        inst, sizeof(loader_settings_driver_configuration) * additional_driver_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  271|      0|    if (NULL == loader_settings->additional_drivers) {
  ------------------
  |  Branch (271:9): [True: 0, False: 0]
  ------------------
  272|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  273|      0|        goto out;
  274|      0|    }
  275|       |
  276|      0|    cJSON* driver = NULL;
  277|      0|    size_t i = 0;
  278|      0|    cJSON_ArrayForEach(driver, additional_drivers_json) {
  ------------------
  |  |  213|      0|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 0, False: 0]
  |  |  |  Branch (213:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  279|      0|        if (driver->type != cJSON_Object) {
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (279:13): [True: 0, False: 0]
  ------------------
  280|      0|            res = VK_ERROR_INITIALIZATION_FAILED;
  281|      0|            goto out;
  282|      0|        }
  283|      0|        res = parse_additional_driver(inst, driver, &(loader_settings->additional_drivers[i++]));
  284|      0|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (284:13): [True: 0, False: 0]
  ------------------
  285|      0|            goto out;
  286|      0|        }
  287|      0|    }
  288|      0|out:
  289|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (289:9): [True: 0, False: 0]
  ------------------
  290|      0|        if (loader_settings->additional_drivers) {
  ------------------
  |  Branch (290:13): [True: 0, False: 0]
  ------------------
  291|      0|            for (size_t index = 0; index < loader_settings->additional_driver_count; index++) {
  ------------------
  |  Branch (291:36): [True: 0, False: 0]
  ------------------
  292|      0|                free_driver_configuration(inst, &(loader_settings->additional_drivers[index]));
  293|      0|            }
  294|      0|            loader_settings->additional_driver_count = 0;
  295|      0|            loader_instance_heap_free(inst, loader_settings->additional_drivers);
  296|       |            loader_settings->additional_drivers = NULL;
  297|      0|        }
  298|      0|    }
  299|      0|    return res;
  300|      0|}
parse_device_configurations:
  377|  1.92k|VkResult parse_device_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  378|  1.92k|    VkResult res = VK_SUCCESS;
  379|       |
  380|  1.92k|    cJSON* device_configurations = loader_cJSON_GetObjectItem(settings_object, "device_configurations");
  381|  1.92k|    if (NULL == device_configurations) {
  ------------------
  |  Branch (381:9): [True: 1.92k, False: 0]
  ------------------
  382|  1.92k|        return VK_SUCCESS;
  383|  1.92k|    }
  384|       |
  385|      0|    uint32_t device_configuration_count = loader_cJSON_GetArraySize(device_configurations);
  386|      0|    if (device_configuration_count == 0) {
  ------------------
  |  Branch (386:9): [True: 0, False: 0]
  ------------------
  387|      0|        loader_settings->device_configurations_active = true;
  388|      0|        return VK_SUCCESS;
  389|      0|    }
  390|       |
  391|      0|    loader_settings->device_configuration_count = device_configuration_count;
  392|       |
  393|      0|    loader_settings->device_configurations = loader_instance_heap_calloc(
  394|      0|        inst, sizeof(loader_settings_device_configuration) * device_configuration_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  395|      0|    if (NULL == loader_settings->device_configurations) {
  ------------------
  |  Branch (395:9): [True: 0, False: 0]
  ------------------
  396|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  397|      0|        goto out;
  398|      0|    }
  399|       |
  400|      0|    cJSON* device = NULL;
  401|      0|    size_t i = 0;
  402|      0|    cJSON_ArrayForEach(device, device_configurations) {
  ------------------
  |  |  213|      0|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 0, False: 0]
  |  |  |  Branch (213:61): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  403|      0|        if (device->type != cJSON_Object) {
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (403:13): [True: 0, False: 0]
  ------------------
  404|      0|            res = VK_ERROR_INITIALIZATION_FAILED;
  405|      0|            goto out;
  406|      0|        }
  407|      0|        res = parse_device_configuration(inst, device, &(loader_settings->device_configurations[i]));
  408|      0|        if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (408:13): [True: 0, False: 0]
  ------------------
  409|      0|            goto out;
  410|      0|        } else if (res != VK_SUCCESS) {
  ------------------
  |  Branch (410:20): [True: 0, False: 0]
  ------------------
  411|       |            // Skip a malformed entry rather than discarding every device configuration in the file
  412|      0|            res = VK_SUCCESS;
  413|      0|            continue;
  414|      0|        }
  415|      0|        i++;
  416|      0|    }
  417|       |    // Only the first i entries were successfully parsed; the trailing entries are unpopulated
  418|      0|    loader_settings->device_configuration_count = (uint32_t)i;
  419|      0|    loader_settings->device_configurations_active = true;
  420|      0|out:
  421|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (421:9): [True: 0, False: 0]
  ------------------
  422|      0|        if (loader_settings->device_configurations) {
  ------------------
  |  Branch (422:13): [True: 0, False: 0]
  ------------------
  423|      0|            for (size_t index = 0; index < loader_settings->device_configuration_count; index++) {
  ------------------
  |  Branch (423:36): [True: 0, False: 0]
  ------------------
  424|      0|                free_device_configuration(inst, &(loader_settings->device_configurations[index]));
  425|      0|            }
  426|      0|            loader_settings->device_configuration_count = 0;
  427|      0|            loader_instance_heap_free(inst, loader_settings->device_configurations);
  428|       |            loader_settings->device_configurations = NULL;
  429|      0|        }
  430|      0|    }
  431|      0|    return res;
  432|      0|}
check_if_settings_path_exists:
  439|  35.2k|                                                            const char* suffix, char** settings_file_path) {
  440|  35.2k|    if (NULL == base || NULL == suffix) {
  ------------------
  |  Branch (440:9): [True: 16.7k, False: 18.4k]
  |  Branch (440:25): [True: 0, False: 18.4k]
  ------------------
  441|  16.7k|        return VK_ERROR_INITIALIZATION_FAILED;
  442|  16.7k|    }
  443|       |
  444|  18.4k|    size_t base_len = strlen(base);
  445|  18.4k|    size_t suffix_len = strlen(suffix);
  446|       |
  447|  18.4k|    uint32_t start = 0;
  448|  18.4k|    uint32_t stop = 0;
  449|  29.4k|    while (base[start] != '\0' && start < base_len) {
  ------------------
  |  Branch (449:12): [True: 18.8k, False: 10.5k]
  |  Branch (449:35): [True: 18.8k, False: 0]
  ------------------
  450|       |        // Skip any path separators preceding this segment so they don't end up in the constructed path
  451|  19.3k|        while (base[start] != '\0' && start < base_len && base[start] == PATH_SEPARATOR) {
  ------------------
  |  |  154|  19.3k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (451:16): [True: 19.3k, False: 0]
  |  Branch (451:39): [True: 19.3k, False: 0]
  |  Branch (451:59): [True: 430, False: 18.8k]
  ------------------
  452|    430|            start++;
  453|    430|        }
  454|  18.8k|        stop = start;
  455|   108k|        while (base[stop] != '\0' && stop < base_len && base[stop] != PATH_SEPARATOR) {
  ------------------
  |  |  154|  89.7k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (455:16): [True: 89.7k, False: 18.4k]
  |  Branch (455:38): [True: 89.7k, False: 0]
  |  Branch (455:57): [True: 89.3k, False: 430]
  ------------------
  456|  89.3k|            stop++;
  457|  89.3k|        }
  458|       |
  459|  18.8k|        size_t segment_len = (stop - start);
  460|  18.8k|        if (segment_len == 0) {
  ------------------
  |  Branch (460:13): [True: 0, False: 18.8k]
  ------------------
  461|       |            // only path separators remained - no more segments
  462|      0|            break;
  463|      0|        }
  464|  18.8k|        size_t path_len = segment_len + suffix_len + 1;
  465|  18.8k|        *settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  466|  18.8k|        if (NULL == *settings_file_path) {
  ------------------
  |  Branch (466:13): [True: 0, False: 18.8k]
  ------------------
  467|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  468|      0|        }
  469|  18.8k|        loader_strncpy(*settings_file_path, path_len, base + start, segment_len);
  470|  18.8k|        loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
  471|       |
  472|  18.8k|        if (loader_platform_file_exists(*settings_file_path)) {
  ------------------
  |  Branch (472:13): [True: 7.94k, False: 10.9k]
  ------------------
  473|  7.94k|            return VK_SUCCESS;
  474|  7.94k|        }
  475|  10.9k|        loader_instance_heap_free(inst, *settings_file_path);
  476|  10.9k|        *settings_file_path = NULL;
  477|  10.9k|        start = stop;
  478|  10.9k|    }
  479|       |
  480|  10.5k|    return VK_ERROR_INITIALIZATION_FAILED;
  481|  18.4k|}
get_unix_settings_path:
  484|  8.37k|VkResult get_unix_settings_path(const struct loader_instance* inst, char** settings_file_path) {
  485|       |    // First, get XDG env-vars we use. Don't need to worry about free'ing because on linux getenv is non-allocating
  486|  8.37k|    char* xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
  487|  8.37k|    char* xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
  488|  8.37k|    char* xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
  489|  8.37k|    char* xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
  490|       |
  491|       |    // Use fallback directories for xdg_config_dirs and xdg_data_dirs if they are NULL.
  492|  8.37k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  493|  8.37k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (493:9): [True: 8.37k, False: 0]
  |  Branch (493:36): [True: 0, False: 0]
  ------------------
  494|  8.37k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
  495|  8.37k|    }
  496|  8.37k|#endif
  497|       |
  498|  8.37k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  499|  8.37k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (499:9): [True: 8.37k, False: 0]
  |  Branch (499:34): [True: 0, False: 0]
  ------------------
  500|  8.37k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
  501|  8.37k|    }
  502|  8.37k|#endif
  503|       |
  504|  8.37k|    VkResult res = check_if_settings_path_exists(
  505|  8.37k|        inst, xdg_config_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  145|  8.37k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  506|  8.37k|    if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (506:9): [True: 0, False: 8.37k]
  |  Branch (506:30): [True: 0, False: 8.37k]
  ------------------
  507|      0|        return res;
  508|      0|    }
  509|       |
  510|  8.37k|    res = check_if_settings_path_exists(inst, xdg_data_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|  8.37k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  511|  8.37k|                                        settings_file_path);
  512|  8.37k|    if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (512:9): [True: 0, False: 8.37k]
  |  Branch (512:30): [True: 0, False: 8.37k]
  ------------------
  513|      0|        return res;
  514|      0|    }
  515|       |
  516|       |    // Check home if either xdg_config_home or xdg_data_home wasn't set
  517|  8.37k|    char* home = loader_secure_getenv("HOME", inst);
  518|  8.37k|    if (home != NULL) {
  ------------------
  |  Branch (518:9): [True: 8.37k, False: 0]
  ------------------
  519|  8.37k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (519:13): [True: 8.37k, False: 0]
  |  Branch (519:40): [True: 0, False: 0]
  ------------------
  520|  8.37k|            res = check_if_settings_path_exists(
  521|  8.37k|                inst, home, "/.config/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  145|  8.37k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  522|  8.37k|            if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (522:17): [True: 0, False: 8.37k]
  |  Branch (522:38): [True: 0, False: 8.37k]
  ------------------
  523|      0|                return res;
  524|      0|            }
  525|  8.37k|        }
  526|  8.37k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (526:13): [True: 8.37k, False: 0]
  |  Branch (526:38): [True: 0, False: 0]
  ------------------
  527|  8.37k|            res = check_if_settings_path_exists(
  528|  8.37k|                inst, home, "/.local/share/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  145|  8.37k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  529|  8.37k|            if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (529:17): [True: 7.94k, False: 430]
  |  Branch (529:38): [True: 0, False: 430]
  ------------------
  530|  7.94k|                return res;
  531|  7.94k|            }
  532|  8.37k|        }
  533|  8.37k|    }
  534|       |
  535|    430|    res = check_if_settings_path_exists(inst, xdg_config_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    430|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  536|    430|                                        settings_file_path);
  537|    430|    if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (537:9): [True: 0, False: 430]
  |  Branch (537:30): [True: 0, False: 430]
  ------------------
  538|      0|        return res;
  539|      0|    }
  540|       |
  541|    430|    res = check_if_settings_path_exists(inst, SYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    430|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  542|    430|                                        settings_file_path);
  543|    430|    if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (543:9): [True: 0, False: 430]
  |  Branch (543:30): [True: 0, False: 430]
  ------------------
  544|      0|        return res;
  545|      0|    }
  546|    430|#if defined(EXTRASYSCONFDIR)
  547|       |
  548|    430|    res = check_if_settings_path_exists(inst, EXTRASYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    430|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  549|    430|                                        settings_file_path);
  550|    430|    if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (550:9): [True: 0, False: 430]
  |  Branch (550:30): [True: 0, False: 430]
  ------------------
  551|      0|        return res;
  552|      0|    }
  553|    430|#endif
  554|    430|    res = check_if_settings_path_exists(inst, xdg_data_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  145|    430|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  555|    430|                                        settings_file_path);
  556|    430|    if (res == VK_SUCCESS || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (556:9): [True: 0, False: 430]
  |  Branch (556:30): [True: 0, False: 430]
  ------------------
  557|      0|        return res;
  558|      0|    }
  559|       |
  560|    430|    return VK_ERROR_INITIALIZATION_FAILED;
  561|    430|}
log_settings:
  620|  1.24k|void log_settings(const struct loader_instance* inst, loader_settings* settings) {
  621|  1.24k|    if (settings == NULL) {
  ------------------
  |  Branch (621:9): [True: 0, False: 1.24k]
  ------------------
  622|      0|        return;
  623|      0|    }
  624|  1.24k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Using layer configurations found in loader settings from %s",
  625|  1.24k|               settings->settings_file_path);
  626|       |
  627|  1.24k|    char cmd_line_msg[64] = {0};
  628|  1.24k|    size_t cmd_line_size = sizeof(cmd_line_msg);
  629|       |
  630|  1.24k|    cmd_line_msg[0] = '\0';
  631|       |
  632|  1.24k|    generate_debug_flag_str(settings->debug_level, cmd_line_size, cmd_line_msg);
  633|  1.24k|    if (strlen(cmd_line_msg)) {
  ------------------
  |  Branch (633:9): [True: 194, False: 1.05k]
  ------------------
  634|    194|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Loader Settings Filters for Logging to Standard Error: %s", cmd_line_msg);
  635|    194|    }
  636|  1.24k|    if (settings->layer_configurations_active) {
  ------------------
  |  Branch (636:9): [True: 1.06k, False: 184]
  ------------------
  637|  1.06k|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Configurations count = %d", settings->layer_configuration_count);
  638|   136k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (638:30): [True: 135k, False: 1.06k]
  ------------------
  639|   135k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Layer Configuration [%d] ----", i);
  640|   135k|            if (settings->layer_configurations[i].control != LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (640:17): [True: 20.1k, False: 115k]
  ------------------
  641|  20.1k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Name: %s", settings->layer_configurations[i].name);
  642|  20.1k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->layer_configurations[i].path);
  643|  20.1k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Type: %s",
  644|  20.1k|                           settings->layer_configurations[i].treat_as_implicit_manifest ? "Implicit" : "Explicit");
  ------------------
  |  Branch (644:28): [True: 200, False: 19.9k]
  ------------------
  645|  20.1k|            }
  646|   135k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Control: %s",
  647|   135k|                       loader_settings_layer_control_to_string(settings->layer_configurations[i].control));
  648|   135k|        }
  649|  1.06k|    }
  650|  1.24k|    if (settings->additional_driver_count > 0) {
  ------------------
  |  Branch (650:9): [True: 0, False: 1.24k]
  ------------------
  651|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  652|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Use Additional Drivers Exclusively = %s",
  653|      0|                   settings->additional_drivers_use_exclusively ? "true" : "false");
  ------------------
  |  Branch (653:20): [True: 0, False: 0]
  ------------------
  654|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Additional Driver Configurations count = %d",
  655|      0|                   settings->additional_driver_count);
  656|      0|        for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (656:30): [True: 0, False: 0]
  ------------------
  657|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Driver Configuration [%d] ----", i);
  658|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->additional_drivers[i].path);
  659|      0|        }
  660|      0|    }
  661|  1.24k|    if (settings->device_configurations_active) {
  ------------------
  |  Branch (661:9): [True: 0, False: 1.24k]
  ------------------
  662|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  663|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Device Configurations count = %d", settings->device_configuration_count);
  664|      0|        for (uint32_t i = 0; i < settings->device_configuration_count; i++) {
  ------------------
  |  Branch (664:30): [True: 0, False: 0]
  ------------------
  665|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Device Configuration [%d] ----", i);
  666|      0|            char device_uuid_str[UUID_STR_LEN] = {0};
  667|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].deviceUUID, device_uuid_str);
  668|      0|            char driver_uuid_str[UUID_STR_LEN] = {0};
  669|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].driverUUID, driver_uuid_str);
  670|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceUUID: %s", device_uuid_str);
  671|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverUUID: %s", driver_uuid_str);
  672|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverVersion: %u", settings->device_configurations[i].driverVersion);
  673|      0|            if ('\0' != settings->device_configurations[i].deviceName[0]) {
  ------------------
  |  Branch (673:17): [True: 0, False: 0]
  ------------------
  674|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceName: %s", settings->device_configurations[i].deviceName);
  675|      0|            }
  676|      0|            if ('\0' != settings->device_configurations[i].driverName[0]) {
  ------------------
  |  Branch (676:17): [True: 0, False: 0]
  ------------------
  677|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverName: %s", settings->device_configurations[i].driverName);
  678|      0|            }
  679|      0|        }
  680|      0|    }
  681|  1.24k|    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------");
  682|  1.24k|}
get_loader_settings:
  687|  8.37k|VkResult get_loader_settings(const struct loader_instance* inst, loader_settings* loader_settings) {
  688|  8.37k|    VkResult res = VK_SUCCESS;
  689|  8.37k|    cJSON* json = NULL;
  690|  8.37k|    char* file_format_version_string = NULL;
  691|  8.37k|    char* settings_file_path = NULL;
  692|       |#if defined(WIN32)
  693|       |    res = windows_get_loader_settings_file_path(inst, &settings_file_path);
  694|       |    if (res != VK_SUCCESS) {
  695|       |        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  696|       |                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  697|       |        goto out;
  698|       |    }
  699|       |
  700|       |#elif COMMON_UNIX_PLATFORMS
  701|       |    res = get_unix_settings_path(inst, &settings_file_path);
  702|  8.37k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (702:9): [True: 430, False: 7.94k]
  ------------------
  703|    430|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  704|    430|                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  705|    430|        goto out;
  706|    430|    }
  707|       |#else
  708|       |#warning "Unsupported platform - must specify platform specific location for vk_loader_settings.json"
  709|       |#endif
  710|       |
  711|  7.94k|    res = loader_get_json(inst, settings_file_path, &json);
  712|       |    // Make sure sure the top level json value is an object
  713|  7.94k|    if (res != VK_SUCCESS || NULL == json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  7.43k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (713:9): [True: 11, False: 7.93k]
  |  Branch (713:30): [True: 494, False: 7.43k]
  |  Branch (713:46): [True: 107, False: 7.32k]
  ------------------
  714|    612|        goto out;
  715|    612|    }
  716|       |
  717|  7.32k|    res = loader_parse_json_string(json, "file_format_version", &file_format_version_string);
  718|  7.32k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (718:9): [True: 10, False: 7.31k]
  ------------------
  719|     10|        if (res != VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (719:13): [True: 10, False: 0]
  ------------------
  720|     10|            loader_log(
  721|     10|                inst, VULKAN_LOADER_DEBUG_BIT, 0,
  722|     10|                "Loader settings file from %s missing required field file_format_version - no loader settings will be active",
  723|     10|                settings_file_path);
  724|     10|        }
  725|     10|        goto out;
  726|     10|    }
  727|       |
  728|       |    // Because the file may contain either a "settings_array" or a single "settings" object, we need to create a cJSON so that we
  729|       |    // can iterate on both cases with common code
  730|  7.31k|    cJSON settings_iter_parent = {0};
  731|       |
  732|  7.31k|    cJSON* settings_array = loader_cJSON_GetObjectItem(json, "settings_array");
  733|  7.31k|    cJSON* single_settings_object = loader_cJSON_GetObjectItem(json, "settings");
  734|  7.31k|    if (NULL != settings_array) {
  ------------------
  |  Branch (734:9): [True: 2.04k, False: 5.27k]
  ------------------
  735|  2.04k|        memcpy(&settings_iter_parent, settings_array, sizeof(cJSON));
  736|  5.27k|    } else if (NULL != single_settings_object) {
  ------------------
  |  Branch (736:16): [True: 92, False: 5.18k]
  ------------------
  737|     92|        settings_iter_parent.child = single_settings_object;
  738|  5.18k|    } else {
  739|  5.18k|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  740|  5.18k|                   "Loader settings file from %s missing required settings objects: Either one of the \"settings\" or "
  741|  5.18k|                   "\"settings_array\" objects must be present - no loader settings will be active",
  742|  5.18k|                   settings_file_path);
  743|  5.18k|        res = VK_ERROR_INITIALIZATION_FAILED;
  744|  5.18k|        goto out;
  745|  5.18k|    }
  746|       |
  747|       |    // Corresponds to the settings object that has no app keys
  748|  2.13k|    cJSON* global_settings = NULL;
  749|       |    // Corresponds to the settings object which has a matching app key
  750|  2.13k|    cJSON* settings_to_use = NULL;
  751|       |
  752|  2.13k|    char current_process_path[1024];
  753|  2.13k|    bool valid_exe_path = NULL != loader_platform_executable_path(current_process_path, 1024);
  754|       |
  755|  2.13k|    cJSON* settings_object_iter = NULL;
  756|  2.71k|    cJSON_ArrayForEach(settings_object_iter, &settings_iter_parent) {
  ------------------
  |  |  213|  4.83k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 2.13k, Folded]
  |  |  |  Branch (213:61): [True: 2.71k, False: 2.12k]
  |  |  ------------------
  ------------------
  757|  2.71k|        if (settings_object_iter->type != cJSON_Object) {
  ------------------
  |  |  103|  2.71k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (757:13): [True: 18, False: 2.69k]
  ------------------
  758|     18|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  759|     18|                       "Loader settings file from %s has a settings element that is not an object", settings_file_path);
  760|     18|            break;
  761|     18|        }
  762|       |
  763|  2.69k|        cJSON* app_keys = loader_cJSON_GetObjectItem(settings_object_iter, "app_keys");
  764|  2.69k|        if (NULL == app_keys) {
  ------------------
  |  Branch (764:13): [True: 2.14k, False: 554]
  ------------------
  765|       |            // use the first 'global' settings that has no app keys as the global one
  766|  2.14k|            if (global_settings == NULL) {
  ------------------
  |  Branch (766:17): [True: 1.92k, False: 217]
  ------------------
  767|  1.92k|                global_settings = settings_object_iter;
  768|  1.92k|            }
  769|  2.14k|            continue;
  770|  2.14k|        }
  771|       |        // No sense iterating if we couldn't get the executable path
  772|    554|        if (!valid_exe_path) {
  ------------------
  |  Branch (772:13): [True: 0, False: 554]
  ------------------
  773|      0|            break;
  774|      0|        }
  775|    554|        cJSON* app_key = NULL;
  776|  1.11k|        cJSON_ArrayForEach(app_key, app_keys) {
  ------------------
  |  |  213|  1.67k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 554, False: 0]
  |  |  |  Branch (213:61): [True: 1.11k, False: 554]
  |  |  ------------------
  ------------------
  777|  1.11k|            char* app_key_str = loader_cJSON_GetStringValue(app_key);
  778|  1.11k|            if (app_key_str && strcmp(current_process_path, app_key_str) == 0) {
  ------------------
  |  Branch (778:17): [True: 521, False: 596]
  |  Branch (778:32): [True: 0, False: 521]
  ------------------
  779|      0|                settings_to_use = settings_object_iter;
  780|      0|                break;
  781|      0|            }
  782|  1.11k|        }
  783|       |
  784|       |        // Break if we have found a matching current_process_path
  785|    554|        if (NULL != settings_to_use) {
  ------------------
  |  Branch (785:13): [True: 0, False: 554]
  ------------------
  786|      0|            break;
  787|      0|        }
  788|    554|    }
  789|       |
  790|       |    // No app specific settings match - either use global settings or exit
  791|  2.13k|    if (settings_to_use == NULL) {
  ------------------
  |  Branch (791:9): [True: 2.13k, False: 0]
  ------------------
  792|  2.13k|        if (global_settings == NULL) {
  ------------------
  |  Branch (792:13): [True: 211, False: 1.92k]
  ------------------
  793|    211|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  794|    211|                       "Loader settings file from %s missing global settings and none of the app specific settings matched the "
  795|    211|                       "current application - no loader settings will be active",
  796|    211|                       settings_file_path);
  797|    211|            goto out;  // No global settings were found - exit
  798|  1.92k|        } else {
  799|  1.92k|            settings_to_use = global_settings;  // Global settings are present - use it
  800|  1.92k|        }
  801|  2.13k|    }
  802|       |
  803|       |    // optional
  804|  1.92k|    cJSON* stderr_filter = loader_cJSON_GetObjectItem(settings_to_use, "stderr_log");
  805|  1.92k|    if (NULL != stderr_filter) {
  ------------------
  |  Branch (805:9): [True: 555, False: 1.37k]
  ------------------
  806|    555|        struct loader_string_list stderr_log = {0};
  807|    555|        VkResult stderr_log_result = VK_SUCCESS;
  808|    555|        stderr_log_result = loader_parse_json_array_of_strings(inst, settings_to_use, "stderr_log", &stderr_log);
  809|    555|        if (VK_ERROR_OUT_OF_HOST_MEMORY == stderr_log_result) {
  ------------------
  |  Branch (809:13): [True: 0, False: 555]
  ------------------
  810|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  811|      0|            goto out;
  812|      0|        }
  813|       |        // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) - 0xFF is a valid bitwise-OR of all flags (the "all" filter)
  814|    555|        loader_settings->debug_level = parse_log_filters_from_strings(&stderr_log);
  815|    555|        free_string_list(inst, &stderr_log);
  816|    555|    }
  817|       |
  818|       |    // optional
  819|  1.92k|    cJSON* logs_to_use = loader_cJSON_GetObjectItem(settings_to_use, "log_locations");
  820|  1.92k|    if (NULL != logs_to_use) {
  ------------------
  |  Branch (820:9): [True: 43, False: 1.88k]
  ------------------
  821|     43|        cJSON* log_element = NULL;
  822|    856|        cJSON_ArrayForEach(log_element, logs_to_use) {
  ------------------
  |  |  213|    899|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 43, False: 0]
  |  |  |  Branch (213:61): [True: 856, False: 43]
  |  |  ------------------
  ------------------
  823|       |            // bool is_valid = true;
  824|    856|            struct loader_string_list log_destinations = {0};
  825|    856|            VkResult parse_dest_res = loader_parse_json_array_of_strings(inst, log_element, "destinations", &log_destinations);
  826|    856|            if (parse_dest_res != VK_SUCCESS) {
  ------------------
  |  Branch (826:17): [True: 797, False: 59]
  ------------------
  827|       |                // is_valid = false;
  828|    797|            }
  829|    856|            free_string_list(inst, &log_destinations);
  830|    856|            struct loader_string_list log_filters = {0};
  831|    856|            VkResult parse_filters_res = loader_parse_json_array_of_strings(inst, log_element, "filters", &log_filters);
  832|    856|            if (parse_filters_res != VK_SUCCESS) {
  ------------------
  |  Branch (832:17): [True: 601, False: 255]
  ------------------
  833|       |                // is_valid = false;
  834|    601|            }
  835|    856|            free_string_list(inst, &log_filters);
  836|    856|        }
  837|     43|    }
  838|       |
  839|  1.92k|    VkResult layer_configurations_res = parse_layer_configurations(inst, settings_to_use, loader_settings);
  840|  1.92k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == layer_configurations_res) {
  ------------------
  |  Branch (840:9): [True: 0, False: 1.92k]
  ------------------
  841|      0|        res = layer_configurations_res;
  842|      0|        goto out;
  843|      0|    }
  844|       |
  845|       |    // Determine if there exists a layer configuration indicating where to put layers not contained in the settings file
  846|       |    // LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION
  847|  19.5k|    for (uint32_t i = 0; i < loader_settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (847:26): [True: 18.2k, False: 1.24k]
  ------------------
  848|  18.2k|        if (loader_settings->layer_configurations[i].control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (848:13): [True: 678, False: 17.6k]
  ------------------
  849|    678|            loader_settings->has_unordered_layer_location = true;
  850|    678|            break;
  851|    678|        }
  852|  18.2k|    }
  853|       |
  854|  1.92k|    VkResult additional_drivers_res = parse_additional_drivers(inst, settings_to_use, loader_settings);
  855|  1.92k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == additional_drivers_res) {
  ------------------
  |  Branch (855:9): [True: 0, False: 1.92k]
  ------------------
  856|      0|        res = additional_drivers_res;
  857|      0|        goto out;
  858|      0|    }
  859|       |
  860|  1.92k|    VkResult device_configurations_res = parse_device_configurations(inst, settings_to_use, loader_settings);
  861|  1.92k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == device_configurations_res) {
  ------------------
  |  Branch (861:9): [True: 0, False: 1.92k]
  ------------------
  862|      0|        res = device_configurations_res;
  863|      0|        goto out;
  864|      0|    }
  865|       |
  866|       |    // Only consider the settings active if there is at least one "setting" active.
  867|       |    // Those are either logging, layers, additional_drivers, or device_configurations.
  868|  1.92k|    if (loader_settings->debug_level != 0 || loader_settings->layer_configurations_active ||
  ------------------
  |  Branch (868:9): [True: 203, False: 1.72k]
  |  Branch (868:46): [True: 1.04k, False: 681]
  ------------------
  869|  1.24k|        loader_settings->additional_driver_count != 0 || loader_settings->device_configurations_active) {
  ------------------
  |  Branch (869:9): [True: 0, False: 681]
  |  Branch (869:58): [True: 0, False: 681]
  ------------------
  870|  1.24k|        loader_settings->settings_file_path = settings_file_path;
  871|  1.24k|        settings_file_path = NULL;
  872|  1.24k|        loader_settings->settings_active = true;
  873|  1.24k|    } else {
  874|    681|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  875|    681|                   "vk_loader_settings.json file found at \"%s\" but did not contain any valid settings.", settings_file_path);
  876|    681|    }
  877|  8.37k|out:
  878|  8.37k|    if (NULL != json) {
  ------------------
  |  Branch (878:9): [True: 7.43k, False: 935]
  ------------------
  879|  7.43k|        loader_cJSON_Delete(json);
  880|  7.43k|    }
  881|       |
  882|  8.37k|    loader_instance_heap_free(inst, settings_file_path);
  883|       |
  884|  8.37k|    loader_instance_heap_free(inst, file_format_version_string);
  885|  8.37k|    return res;
  886|  1.92k|}
init_global_loader_settings:
  907|      2|void init_global_loader_settings(void) {
  908|      2|    loader_platform_thread_create_mutex(&global_loader_settings_lock);
  909|       |    // Free out the global settings in case the process was loaded & unloaded
  910|       |    free_loader_settings(NULL, &global_loader_settings);
  911|      2|}
get_current_settings_and_lock:
  927|  10.8k|const loader_settings* get_current_settings_and_lock(const struct loader_instance* inst) {
  928|  10.8k|    if (inst) {
  ------------------
  |  Branch (928:9): [True: 10.8k, False: 0]
  ------------------
  929|  10.8k|        return &inst->settings;
  930|  10.8k|    }
  931|      0|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  932|      0|    return &global_loader_settings;
  933|  10.8k|}
release_current_settings_lock:
  935|  10.8k|void release_current_settings_lock(const struct loader_instance* inst) {
  936|  10.8k|    if (inst == NULL) {
  ------------------
  |  Branch (936:9): [True: 0, False: 10.8k]
  ------------------
  937|      0|        loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  938|      0|    }
  939|  10.8k|}
get_settings_layers:
  942|  8.37k|                                                  bool* should_search_for_other_layers) {
  943|  8.37k|    VkResult res = VK_SUCCESS;
  944|  8.37k|    *should_search_for_other_layers = true;  // default to true
  945|       |
  946|  8.37k|    const loader_settings* settings = get_current_settings_and_lock(inst);
  947|       |
  948|  8.37k|    if (NULL == settings || !settings->settings_active || !settings->layer_configurations_active) {
  ------------------
  |  Branch (948:9): [True: 0, False: 8.37k]
  |  Branch (948:29): [True: 7.12k, False: 1.24k]
  |  Branch (948:59): [True: 184, False: 1.06k]
  ------------------
  949|  7.30k|        goto out;
  950|  7.30k|    }
  951|       |
  952|       |    // Assume the list doesn't contain LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION at first
  953|  1.06k|    *should_search_for_other_layers = false;
  954|       |
  955|   136k|    for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (955:26): [True: 135k, False: 1.06k]
  ------------------
  956|   135k|        loader_settings_layer_configuration* layer_config = &settings->layer_configurations[i];
  957|       |
  958|       |        // If we encountered a layer that should be forced off, we add it to the settings_layers list but only
  959|       |        // with the data required to compare it with layers not in the settings file (aka name and manifest path)
  960|   135k|        if (layer_config->control == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (960:13): [True: 15.3k, False: 120k]
  ------------------
  961|  15.3k|            struct loader_layer_properties props = {0};
  962|  15.3k|            props.settings_control_value = LOADER_SETTINGS_LAYER_CONTROL_OFF;
  963|  15.3k|            loader_strncpy(props.info.layerName, VK_MAX_EXTENSION_NAME_SIZE, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE);
  964|  15.3k|            props.info.layerName[VK_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
  965|  15.3k|            res = loader_copy_to_new_str(inst, layer_config->path, &props.manifest_file_name);
  966|  15.3k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (966:17): [True: 0, False: 15.3k]
  ------------------
  967|      0|                goto out;
  968|      0|            }
  969|  15.3k|            res = loader_append_layer_property(inst, settings_layers, &props);
  970|  15.3k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (970:17): [True: 0, False: 15.3k]
  ------------------
  971|      0|                loader_free_layer_properties(inst, &props);
  972|      0|                goto out;
  973|      0|            }
  974|  15.3k|            continue;
  975|  15.3k|        }
  976|       |
  977|       |        // The special layer location that indicates where unordered layers should go only should have the
  978|       |        // settings_control_value set - everything else should be NULL
  979|   120k|        if (layer_config->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (979:13): [True: 115k, False: 4.85k]
  ------------------
  980|   115k|            struct loader_layer_properties props = {0};
  981|   115k|            props.settings_control_value = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
  982|   115k|            res = loader_append_layer_property(inst, settings_layers, &props);
  983|   115k|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (983:17): [True: 0, False: 115k]
  ------------------
  984|      0|                loader_free_layer_properties(inst, &props);
  985|      0|                goto out;
  986|      0|            }
  987|   115k|            *should_search_for_other_layers = true;
  988|   115k|            continue;
  989|   115k|        }
  990|       |
  991|  4.85k|        if (layer_config->path == NULL) {
  ------------------
  |  Branch (991:13): [True: 0, False: 4.85k]
  ------------------
  992|      0|            continue;
  993|      0|        }
  994|       |
  995|  4.85k|        if (!is_json(layer_config->path, strlen(layer_config->path))) {
  ------------------
  |  Branch (995:13): [True: 3.76k, False: 1.09k]
  ------------------
  996|  3.76k|            continue;
  997|  3.76k|        }
  998|       |
  999|  1.09k|        cJSON* json = NULL;
 1000|  1.09k|        VkResult local_res = loader_get_json(inst, layer_config->path, &json);
 1001|  1.09k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (1001:13): [True: 0, False: 1.09k]
  ------------------
 1002|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1003|      0|            goto out;
 1004|  1.09k|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (1004:20): [True: 398, False: 697]
  |  Branch (1004:47): [True: 462, False: 235]
  ------------------
 1005|    860|            continue;
 1006|    860|        }
 1007|       |
 1008|       |        // Makes it possible to know if a new layer was added or not, since the only return value is VkResult
 1009|    235|        uint32_t count_before_adding = settings_layers->count;
 1010|       |
 1011|    235|        local_res =
 1012|    235|            loader_add_layer_properties(inst, settings_layers, json, layer_config->treat_as_implicit_manifest, layer_config->path);
 1013|    235|        loader_cJSON_Delete(json);
 1014|       |
 1015|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 1016|    235|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (1016:13): [True: 0, False: 235]
  ------------------
 1017|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1018|      0|            goto out;
 1019|    235|        } else if (local_res != VK_SUCCESS || count_before_adding == settings_layers->count) {
  ------------------
  |  Branch (1019:20): [True: 194, False: 41]
  |  Branch (1019:47): [True: 0, False: 41]
  ------------------
 1020|       |            // Indicates something was wrong with the layer, can't add it to the list
 1021|    194|            continue;
 1022|    194|        }
 1023|       |
 1024|     94|        for (uint32_t j = count_before_adding; j < settings_layers->count; j++) {
  ------------------
  |  Branch (1024:48): [True: 53, False: 41]
  ------------------
 1025|     53|            struct loader_layer_properties* newly_added_layer = &settings_layers->list[j];
 1026|     53|            newly_added_layer->settings_control_value = layer_config->control;
 1027|       |            // If the manifest file found has a name that differs from the one in the settings, remove this layer from
 1028|       |            // consideration
 1029|     53|            if (strncmp(newly_added_layer->info.layerName, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE) != 0) {
  ------------------
  |  Branch (1029:17): [True: 35, False: 18]
  ------------------
 1030|     35|                loader_remove_layer_in_list(inst, settings_layers, j);
 1031|     35|                j--;
 1032|     35|                continue;
 1033|     35|            }
 1034|     53|            bool should_remove = false;
 1035|       |            // Make sure the layer isn't already in the list
 1036|    507|            for (uint32_t k = 0; k < j; k++) {
  ------------------
  |  Branch (1036:34): [True: 493, False: 14]
  ------------------
 1037|    493|                if (0 == strncmp(settings_layers->list[k].info.layerName, newly_added_layer->info.layerName,
  ------------------
  |  Branch (1037:21): [True: 379, False: 114]
  ------------------
 1038|    493|                                 VK_MAX_EXTENSION_NAME_SIZE)) {
 1039|    379|                    if (0 == (newly_added_layer->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) &&
  ------------------
  |  Branch (1039:25): [True: 378, False: 1]
  ------------------
 1040|    378|                        settings_layers->list[k].lib_name != NULL && newly_added_layer->lib_name != NULL &&
  ------------------
  |  Branch (1040:25): [True: 344, False: 34]
  |  Branch (1040:70): [True: 344, False: 0]
  ------------------
 1041|    344|                        strcmp(settings_layers->list[k].lib_name, newly_added_layer->lib_name) == 0) {
  ------------------
  |  Branch (1041:25): [True: 4, False: 340]
  ------------------
 1042|      4|                        should_remove = true;
 1043|      4|                        break;
 1044|      4|                    }
 1045|    379|                }
 1046|    493|            }
 1047|     18|            if (should_remove) {
  ------------------
  |  Branch (1047:17): [True: 4, False: 14]
  ------------------
 1048|      4|                loader_remove_layer_in_list(inst, settings_layers, j);
 1049|      4|                j--;
 1050|      4|            }
 1051|     18|        }
 1052|     41|    }
 1053|       |
 1054|  8.37k|out:
 1055|  8.37k|    release_current_settings_lock(inst);
 1056|  8.37k|    return res;
 1057|  1.06k|}
check_if_layer_is_in_list:
 1068|   200k|                               bool consider_lib_path) {
 1069|       |    // If the layer is a meta layer, just check against the name
 1070|   262M|    for (uint32_t i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (1070:26): [True: 262M, False: 139k]
  ------------------
 1071|   262M|        if (0 == strncmp(layer_list->list[i].info.layerName, layer_property->info.layerName, VK_MAX_EXTENSION_NAME_SIZE)) {
  ------------------
  |  Branch (1071:13): [True: 260M, False: 2.01M]
  ------------------
 1072|   260M|            if (layer_list->list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (1072:17): [True: 5.04k, False: 260M]
  ------------------
 1073|  5.04k|                return true;
 1074|  5.04k|            }
 1075|   260M|            if (VK_LAYER_TYPE_FLAG_META_LAYER == (layer_property->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
  ------------------
  |  Branch (1075:17): [True: 23.7k, False: 260M]
  ------------------
 1076|  23.7k|                return true;
 1077|  23.7k|            }
 1078|   260M|            if (!consider_lib_path) {
  ------------------
  |  Branch (1078:17): [True: 31.1k, False: 260M]
  ------------------
 1079|  31.1k|                return true;
 1080|  31.1k|            }
 1081|   260M|            if (layer_list->list[i].lib_name && layer_property->lib_name) {
  ------------------
  |  Branch (1081:17): [True: 554, False: 260M]
  |  Branch (1081:49): [True: 234, False: 320]
  ------------------
 1082|    234|                return strcmp(layer_list->list[i].lib_name, layer_property->lib_name) == 0;
 1083|    234|            }
 1084|   260M|        }
 1085|   262M|    }
 1086|   139k|    return false;
 1087|   200k|}
combine_settings_layers_with_regular_layers:
 1091|  7.98k|                                                     struct loader_layer_list* output_layers) {
 1092|  7.98k|    VkResult res = VK_SUCCESS;
 1093|  7.98k|    bool has_unordered_layer_location = false;
 1094|  7.98k|    uint32_t unordered_layer_location_index = 0;
 1095|       |    // Location to put layers that aren't known to the settings file
 1096|       |    // Find it here so we dont have to pass in a loader_settings struct
 1097|  13.6k|    for (uint32_t i = 0; i < settings_layers->count; i++) {
  ------------------
  |  Branch (1097:26): [True: 6.31k, False: 7.30k]
  ------------------
 1098|  6.31k|        if (settings_layers->list[i].settings_control_value == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (1098:13): [True: 678, False: 5.63k]
  ------------------
 1099|    678|            has_unordered_layer_location = true;
 1100|    678|            unordered_layer_location_index = i;
 1101|    678|            break;
 1102|    678|        }
 1103|  6.31k|    }
 1104|       |
 1105|  7.98k|    if (settings_layers->count == 0 && regular_layers->count == 0) {
  ------------------
  |  Branch (1105:9): [True: 7.30k, False: 678]
  |  Branch (1105:40): [True: 3.62k, False: 3.68k]
  ------------------
 1106|       |        // No layers to combine
 1107|  3.62k|        goto out;
 1108|  4.35k|    } else if (settings_layers->count == 0) {
  ------------------
  |  Branch (1108:16): [True: 3.68k, False: 678]
  ------------------
 1109|       |        // No settings layers - just copy regular to output_layers - memset regular layers to prevent double frees
 1110|  3.68k|        *output_layers = *regular_layers;
 1111|  3.68k|        memset(regular_layers, 0, sizeof(struct loader_layer_list));
 1112|  3.68k|        goto out;
 1113|  3.68k|    } else if (regular_layers->count == 0 || !has_unordered_layer_location) {
  ------------------
  |  Branch (1113:16): [True: 62, False: 616]
  |  Branch (1113:46): [True: 0, False: 616]
  ------------------
 1114|       |        // No regular layers or has_unordered_layer_location is false - just copy settings to output_layers -
 1115|       |        // memset settings layers to prevent double frees
 1116|     62|        *output_layers = *settings_layers;
 1117|     62|        memset(settings_layers, 0, sizeof(struct loader_layer_list));
 1118|     62|        goto out;
 1119|     62|    }
 1120|       |
 1121|    616|    res = loader_init_generic_list(inst, (struct loader_generic_list*)output_layers,
 1122|    616|                                   (settings_layers->count + regular_layers->count) * sizeof(struct loader_layer_properties));
 1123|    616|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1123:9): [True: 0, False: 616]
  ------------------
 1124|      0|        goto out;
 1125|      0|    }
 1126|       |
 1127|       |    // Insert the settings layers into output_layers up to unordered_layer_index
 1128|  5.75k|    for (uint32_t i = 0; i < unordered_layer_location_index; i++) {
  ------------------
  |  Branch (1128:26): [True: 5.14k, False: 616]
  ------------------
 1129|  5.14k|        if (!check_if_layer_is_in_list(output_layers, &settings_layers->list[i], true)) {
  ------------------
  |  Branch (1129:13): [True: 1.16k, False: 3.98k]
  ------------------
 1130|  1.16k|            res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
 1131|  1.16k|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1131:17): [True: 0, False: 1.16k]
  ------------------
 1132|      0|                goto out;
 1133|      0|            }
 1134|  1.16k|        }
 1135|  5.14k|    }
 1136|       |
 1137|  56.3k|    for (uint32_t i = 0; i < regular_layers->count; i++) {
  ------------------
  |  Branch (1137:26): [True: 55.7k, False: 616]
  ------------------
 1138|       |        // Check if its already been put in the output_layers list as well as the remaining settings_layers
 1139|  55.7k|        bool regular_layer_is_ordered = check_if_layer_is_in_list(output_layers, &regular_layers->list[i], false) ||
  ------------------
  |  Branch (1139:41): [True: 9.42k, False: 46.3k]
  ------------------
 1140|  46.3k|                                        check_if_layer_is_in_list(settings_layers, &regular_layers->list[i], false);
  ------------------
  |  Branch (1140:41): [True: 45.3k, False: 955]
  ------------------
 1141|       |        // If it isn't found, add it
 1142|  55.7k|        if (!regular_layer_is_ordered) {
  ------------------
  |  Branch (1142:13): [True: 955, False: 54.7k]
  ------------------
 1143|    955|            res = loader_append_layer_property(inst, output_layers, &regular_layers->list[i]);
 1144|    955|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1144:17): [True: 0, False: 955]
  ------------------
 1145|      0|                goto out;
 1146|      0|            }
 1147|  54.7k|        } else {
 1148|       |            // layer is already ordered and can be safely freed
 1149|  54.7k|            loader_free_layer_properties(inst, &regular_layers->list[i]);
 1150|  54.7k|        }
 1151|  55.7k|    }
 1152|       |
 1153|       |    // Insert the rest of the settings layers into combined_layers from  unordered_layer_index to the end
 1154|       |    // start at one after the unordered_layer_index
 1155|  93.4k|    for (uint32_t i = unordered_layer_location_index + 1; i < settings_layers->count; i++) {
  ------------------
  |  Branch (1155:59): [True: 92.8k, False: 616]
  ------------------
 1156|  92.8k|        if (!check_if_layer_is_in_list(output_layers, &settings_layers->list[i], true)) {
  ------------------
  |  Branch (1156:13): [True: 91.6k, False: 1.19k]
  ------------------
 1157|  91.6k|            res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
 1158|  91.6k|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1158:17): [True: 0, False: 91.6k]
  ------------------
 1159|      0|                goto out;
 1160|      0|            }
 1161|  91.6k|        }
 1162|  92.8k|    }
 1163|       |
 1164|  7.98k|out:
 1165|  7.98k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (1165:9): [True: 0, False: 7.98k]
  ------------------
 1166|      0|        loader_delete_layer_list_and_properties(inst, output_layers);
 1167|      0|    }
 1168|       |
 1169|  7.98k|    return res;
 1170|    616|}
loader_settings_get_additional_driver_files:
 1283|    838|VkResult loader_settings_get_additional_driver_files(const struct loader_instance* inst, struct loader_string_list* out_files) {
 1284|    838|    VkResult res = VK_SUCCESS;
 1285|       |
 1286|    838|    const loader_settings* settings = get_current_settings_and_lock(inst);
 1287|       |
 1288|    838|    if (NULL == settings || !settings->settings_active) {
  ------------------
  |  Branch (1288:9): [True: 0, False: 838]
  |  Branch (1288:29): [True: 833, False: 5]
  ------------------
 1289|    833|        goto out;
 1290|    833|    }
 1291|       |
 1292|      5|    if (settings->additional_drivers_use_exclusively) {
  ------------------
  |  Branch (1292:9): [True: 0, False: 5]
  ------------------
 1293|      0|        free_string_list(inst, out_files);
 1294|      0|    }
 1295|       |
 1296|      5|    for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (1296:26): [True: 0, False: 5]
  ------------------
 1297|      0|        res = prepend_if_manifest_file(inst, settings->additional_drivers[i].path, out_files);
 1298|      0|    }
 1299|       |
 1300|    838|out:
 1301|    838|    release_current_settings_lock(inst);
 1302|    838|    return res;
 1303|      5|}
loader_settings_should_use_driver_environment_variables:
 1305|  1.67k|bool loader_settings_should_use_driver_environment_variables(const struct loader_instance* inst) {
 1306|  1.67k|    bool should_use = true;
 1307|  1.67k|    const loader_settings* settings = get_current_settings_and_lock(inst);
 1308|  1.67k|    if (NULL == settings || !settings->settings_active) {
  ------------------
  |  Branch (1308:9): [True: 0, False: 1.67k]
  |  Branch (1308:29): [True: 1.66k, False: 10]
  ------------------
 1309|  1.66k|        goto out;
 1310|  1.66k|    }
 1311|     10|    if (settings->device_configurations_active) {
  ------------------
  |  Branch (1311:9): [True: 0, False: 10]
  ------------------
 1312|      0|        should_use = false;
 1313|      0|    }
 1314|  1.67k|out:
 1315|  1.67k|    release_current_settings_lock(inst);
 1316|  1.67k|    return should_use;
 1317|     10|}

vkCreateInstance:
  522|  8.37k|                                                              const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
  523|  8.37k|    struct loader_instance *ptr_instance = NULL;
  524|  8.37k|    VkInstance created_instance = VK_NULL_HANDLE;
  525|  8.37k|    VkResult res = VK_ERROR_INITIALIZATION_FAILED;
  526|  8.37k|    VkInstanceCreateInfo ici = {0};
  527|  8.37k|    bool portability_enumeration_flag_bit_set = false;
  528|  8.37k|    bool portability_enumeration_extension_enabled = false;
  529|  8.37k|    struct loader_envvar_all_filters layer_filters = {0};
  530|       |
  531|  8.37k|    LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
  532|       |
  533|  8.37k|    if (pCreateInfo == NULL) {
  ------------------
  |  Branch (533:9): [True: 0, False: 8.37k]
  ------------------
  534|      0|        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
  535|      0|                   "vkCreateInstance: \'pCreateInfo\' is NULL (VUID-vkCreateInstance-pCreateInfo-parameter)");
  536|      0|        goto out;
  537|      0|    }
  538|  8.37k|    ici = *pCreateInfo;
  539|       |
  540|  8.37k|    if (pInstance == NULL) {
  ------------------
  |  Branch (540:9): [True: 0, False: 8.37k]
  ------------------
  541|      0|        loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
  542|      0|                   "vkCreateInstance \'pInstance\' not valid (VUID-vkCreateInstance-pInstance-parameter)");
  543|      0|        goto out;
  544|      0|    }
  545|       |
  546|  8.37k|    ptr_instance =
  547|  8.37k|        (struct loader_instance *)loader_calloc(pAllocator, sizeof(struct loader_instance), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  548|       |
  549|  8.37k|    if (ptr_instance == NULL) {
  ------------------
  |  Branch (549:9): [True: 0, False: 8.37k]
  ------------------
  550|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  551|      0|        goto out;
  552|      0|    }
  553|       |
  554|  8.37k|    loader_platform_thread_lock_mutex(&loader_lock);
  555|  8.37k|    if (pAllocator) {
  ------------------
  |  Branch (555:9): [True: 0, False: 8.37k]
  ------------------
  556|      0|        ptr_instance->alloc_callbacks = *pAllocator;
  557|      0|    }
  558|  8.37k|    ptr_instance->magic = LOADER_MAGIC_NUMBER;
  ------------------
  |  |  329|  8.37k|#define LOADER_MAGIC_NUMBER 0x10ADED010110ADEDUL
  ------------------
  559|       |
  560|       |    // Save the application version
  561|  8.37k|    if (NULL == pCreateInfo->pApplicationInfo || 0 == pCreateInfo->pApplicationInfo->apiVersion) {
  ------------------
  |  Branch (561:9): [True: 0, False: 8.37k]
  |  Branch (561:50): [True: 0, False: 8.37k]
  ------------------
  562|      0|        ptr_instance->app_api_version = LOADER_VERSION_1_0_0;
  ------------------
  |  |  266|      0|#define LOADER_VERSION_1_0_0 loader_combine_version(1, 0, 0)
  ------------------
  563|  8.37k|    } else {
  564|  8.37k|        ptr_instance->app_api_version = loader_make_version(pCreateInfo->pApplicationInfo->apiVersion);
  565|  8.37k|    }
  566|       |
  567|       |    // Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures
  568|       |    // and setup a callback(s) for each one found.
  569|       |
  570|       |    // Handle cases of VK_EXT_debug_utils
  571|       |    // Setup the temporary messenger(s) here to catch early issues:
  572|  8.37k|    res = util_CreateDebugUtilsMessengers(ptr_instance, pCreateInfo->pNext, pAllocator);
  573|  8.37k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (573:9): [True: 0, False: 8.37k]
  ------------------
  574|       |        // Failure of setting up one or more of the messenger.
  575|      0|        goto out;
  576|      0|    }
  577|       |
  578|       |    // Handle cases of VK_EXT_debug_report
  579|       |    // Setup the temporary callback(s) here to catch early issues:
  580|  8.37k|    res = util_CreateDebugReportCallbacks(ptr_instance, pCreateInfo->pNext, pAllocator);
  581|  8.37k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (581:9): [True: 0, False: 8.37k]
  ------------------
  582|       |        // Failure of setting up one or more of the callback.
  583|      0|        goto out;
  584|      0|    }
  585|       |
  586|  8.37k|    loader_log_instance_create_info(ptr_instance, pCreateInfo);
  587|       |
  588|  8.37k|    VkResult settings_file_res = get_loader_settings(ptr_instance, &ptr_instance->settings);
  589|  8.37k|    if (settings_file_res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (589:9): [True: 0, False: 8.37k]
  ------------------
  590|      0|        res = settings_file_res;
  591|      0|        goto out;
  592|      0|    }
  593|  8.37k|    if (ptr_instance->settings.settings_active) {
  ------------------
  |  Branch (593:9): [True: 1.24k, False: 7.12k]
  ------------------
  594|  1.24k|        log_settings(ptr_instance, &ptr_instance->settings);
  595|  1.24k|    }
  596|       |
  597|       |    // Providing an apiVersion less than VK_API_VERSION_1_0 but greater than zero prevents the validation layers from starting
  598|  8.37k|    if (pCreateInfo->pApplicationInfo && pCreateInfo->pApplicationInfo->apiVersion != 0u &&
  ------------------
  |  Branch (598:9): [True: 8.37k, False: 0]
  |  Branch (598:42): [True: 8.37k, False: 0]
  ------------------
  599|  8.37k|        pCreateInfo->pApplicationInfo->apiVersion < VK_API_VERSION_1_0) {
  ------------------
  |  Branch (599:9): [True: 0, False: 8.37k]
  ------------------
  600|      0|        loader_log(ptr_instance, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
  601|      0|                   "VkInstanceCreateInfo::pApplicationInfo::apiVersion has value of %u which is not permitted. If apiVersion is "
  602|      0|                   "not 0, then it must be "
  603|      0|                   "greater than or equal to the value of VK_API_VERSION_1_0 [VUID-VkApplicationInfo-apiVersion]",
  604|      0|                   pCreateInfo->pApplicationInfo->apiVersion);
  605|      0|    }
  606|       |
  607|       |    // Check the VkInstanceCreateInfoFlags wether to allow the portability enumeration flag
  608|  8.37k|    if ((pCreateInfo->flags & VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR) == 1) {
  ------------------
  |  Branch (608:9): [True: 0, False: 8.37k]
  ------------------
  609|      0|        portability_enumeration_flag_bit_set = true;
  610|      0|    }
  611|       |    // Make sure the portability extension extension has been enabled before enabling portability driver enumeration
  612|  8.37k|    if (pCreateInfo->ppEnabledExtensionNames) {
  ------------------
  |  Branch (612:9): [True: 0, False: 8.37k]
  ------------------
  613|      0|        for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
  ------------------
  |  Branch (613:30): [True: 0, False: 0]
  ------------------
  614|      0|            if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) {
  ------------------
  |  Branch (614:17): [True: 0, False: 0]
  ------------------
  615|      0|                portability_enumeration_extension_enabled = true;
  616|      0|                if (portability_enumeration_flag_bit_set) {
  ------------------
  |  Branch (616:21): [True: 0, False: 0]
  ------------------
  617|      0|                    ptr_instance->portability_enumeration_enabled = true;
  618|      0|                    loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
  619|      0|                               "Portability enumeration bit was set, enumerating portability drivers.");
  620|      0|                }
  621|      0|                break;
  622|      0|            }
  623|      0|        }
  624|      0|    }
  625|       |
  626|       |    // Make sure the application provided API version has the correct variant
  627|  8.37k|    if (NULL != pCreateInfo->pApplicationInfo) {
  ------------------
  |  Branch (627:9): [True: 8.37k, False: 0]
  ------------------
  628|  8.37k|        uint32_t variant_version = VK_API_VERSION_VARIANT(pCreateInfo->pApplicationInfo->apiVersion);
  629|  8.37k|        const uint32_t expected_variant = 0;
  630|  8.37k|        if (expected_variant != variant_version) {
  ------------------
  |  Branch (630:13): [True: 0, False: 8.37k]
  ------------------
  631|      0|            loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT, 0,
  632|      0|                       "vkCreateInstance: The API Variant specified in pCreateInfo->pApplicationInfo.apiVersion is %d instead of "
  633|      0|                       "the expected value of %d.",
  634|      0|                       variant_version, expected_variant);
  635|      0|        }
  636|  8.37k|    }
  637|       |
  638|  8.37k|    res = parse_layer_environment_var_filters(ptr_instance, &layer_filters);
  639|  8.37k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (639:9): [True: 0, False: 8.37k]
  ------------------
  640|      0|        goto out;
  641|      0|    }
  642|       |
  643|       |    // Due to implicit layers need to get layer list even if
  644|       |    // enabledLayerCount == 0 and VK_INSTANCE_LAYERS is unset. For now always
  645|       |    // get layer list via loader_scan_for_layers().
  646|  8.37k|    memset(&ptr_instance->instance_layer_list, 0, sizeof(ptr_instance->instance_layer_list));
  647|  8.37k|    res = loader_scan_for_layers(ptr_instance, &ptr_instance->instance_layer_list, &layer_filters);
  648|  8.37k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (648:9): [True: 0, False: 8.37k]
  ------------------
  649|      0|        goto out;
  650|      0|    }
  651|       |
  652|       |    // Validate the app requested layers to be enabled
  653|  8.37k|    if (pCreateInfo->enabledLayerCount > 0) {
  ------------------
  |  Branch (653:9): [True: 8.37k, False: 0]
  ------------------
  654|  8.37k|        res = loader_validate_layers(ptr_instance, pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames,
  655|  8.37k|                                     &ptr_instance->instance_layer_list);
  656|  8.37k|        if (res != VK_SUCCESS) {
  ------------------
  |  Branch (656:13): [True: 7.53k, False: 838]
  ------------------
  657|  7.53k|            goto out;
  658|  7.53k|        }
  659|  8.37k|    }
  660|       |
  661|       |    // Scan/discover all System and Environment Variable ICD libraries
  662|  8.37k|    bool skipped_portability_drivers = false;
  663|    838|    res = loader_icd_scan(ptr_instance, &ptr_instance->icd_tramp_list, pCreateInfo, &skipped_portability_drivers);
  664|    838|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (664:9): [True: 1, False: 837]
  ------------------
  665|      1|        goto out;
  666|      1|    }
  667|       |
  668|    837|    if (ptr_instance->icd_tramp_list.count == 0) {
  ------------------
  |  Branch (668:9): [True: 837, False: 0]
  ------------------
  669|       |        // No drivers found
  670|    837|        if (skipped_portability_drivers) {
  ------------------
  |  Branch (670:13): [True: 0, False: 837]
  ------------------
  671|      0|            if (portability_enumeration_extension_enabled && !portability_enumeration_flag_bit_set) {
  ------------------
  |  Branch (671:17): [True: 0, False: 0]
  |  Branch (671:62): [True: 0, False: 0]
  ------------------
  672|      0|                loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
  673|      0|                           "vkCreateInstance: Found drivers that contain devices which support the portability subset, but "
  674|      0|                           "the instance does not enumerate portability drivers! Applications that wish to enumerate portability "
  675|      0|                           "drivers must set the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo "
  676|      0|                           "flags.");
  677|      0|            } else if (portability_enumeration_flag_bit_set && !portability_enumeration_extension_enabled) {
  ------------------
  |  Branch (677:24): [True: 0, False: 0]
  |  Branch (677:64): [True: 0, False: 0]
  ------------------
  678|      0|                loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
  679|      0|                           "VkInstanceCreateInfo: If flags has the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit set, the "
  680|      0|                           "list of enabled extensions in ppEnabledExtensionNames must contain VK_KHR_portability_enumeration "
  681|      0|                           "[VUID-VkInstanceCreateInfo-flags-06559 ]"
  682|      0|                           "Applications that wish to enumerate portability drivers must enable the VK_KHR_portability_enumeration "
  683|      0|                           "instance extension.");
  684|      0|            } else {
  685|      0|                loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
  686|      0|                           "vkCreateInstance: Found drivers that contain devices which support the portability subset, but "
  687|      0|                           "the instance does not enumerate portability drivers! Applications that wish to enumerate portability "
  688|      0|                           "drivers must set the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo "
  689|      0|                           "flags and enable the VK_KHR_portability_enumeration instance extension.");
  690|      0|            }
  691|      0|        }
  692|    837|        loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, "vkCreateInstance: Found no drivers!");
  693|    837|        res = VK_ERROR_INCOMPATIBLE_DRIVER;
  694|    837|        goto out;
  695|    837|    }
  696|       |
  697|       |    // Get extensions from all ICD's, merge so no duplicates, then validate
  698|      0|    res = loader_get_icd_loader_instance_extensions(ptr_instance, &ptr_instance->icd_tramp_list, &ptr_instance->ext_list);
  699|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (699:9): [True: 0, False: 0]
  ------------------
  700|      0|        goto out;
  701|      0|    }
  702|       |
  703|      0|    ptr_instance->disp = loader_instance_heap_alloc(ptr_instance, sizeof(struct loader_instance_dispatch_table),
  704|      0|                                                    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  705|      0|    if (ptr_instance->disp == NULL) {
  ------------------
  |  Branch (705:9): [True: 0, False: 0]
  ------------------
  706|      0|        loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT, 0,
  707|      0|                   "vkCreateInstance:  Failed to allocate Loader's full Instance dispatch table.");
  708|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  709|      0|        goto out;
  710|      0|    }
  711|      0|    memcpy(&ptr_instance->disp->layer_inst_disp, &instance_disp, sizeof(instance_disp));
  712|       |
  713|      0|    ptr_instance->next = loader.instances;
  714|      0|    loader.instances = ptr_instance;
  715|       |
  716|       |    // Activate any layers on instance chain
  717|      0|    res = loader_enable_instance_layers(ptr_instance, &ici, &layer_filters);
  718|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (718:9): [True: 0, False: 0]
  ------------------
  719|      0|        goto out;
  720|      0|    }
  721|       |
  722|      0|    res = loader_validate_instance_extensions(ptr_instance, &ptr_instance->ext_list, &ptr_instance->instance_layer_list,
  723|      0|                                              &ptr_instance->expanded_activated_layer_list, &ici);
  724|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (724:9): [True: 0, False: 0]
  ------------------
  725|      0|        goto out;
  726|      0|    }
  727|       |
  728|      0|    created_instance = (VkInstance)ptr_instance;
  729|      0|    res = loader_create_instance_chain(&ici, pAllocator, ptr_instance, &created_instance);
  730|       |
  731|      0|    if (VK_SUCCESS == res) {
  ------------------
  |  Branch (731:9): [True: 0, False: 0]
  ------------------
  732|       |        // Check for enabled extensions here to setup the loader structures so the loader knows what extensions
  733|       |        // it needs to worry about.
  734|       |        // We do it in the terminator and again above the layers here since we may think different extensions
  735|       |        // are enabled than what's down in the terminator.
  736|       |        // This is why we don't clear inside of these function calls.
  737|       |        // The clearing should actually be handled by the overall memset of the pInstance structure above.
  738|      0|        fill_out_enabled_instance_extensions(ici.enabledExtensionCount, ici.ppEnabledExtensionNames,
  739|      0|                                             &ptr_instance->enabled_extensions);
  740|       |
  741|      0|        *pInstance = (VkInstance)ptr_instance;
  742|       |
  743|       |        // Finally have the layers in place and everyone has seen
  744|       |        // the CreateInstance command go by. This allows the layer's
  745|       |        // GetInstanceProcAddr functions to return valid extension functions
  746|       |        // if enabled.
  747|      0|        loader_activate_instance_layer_extensions(ptr_instance, created_instance);
  748|      0|        ptr_instance->instance_finished_creation = true;
  749|      0|    } else if (VK_ERROR_EXTENSION_NOT_PRESENT == res && !ptr_instance->create_terminator_invalid_extension) {
  ------------------
  |  Branch (749:16): [True: 0, False: 0]
  |  Branch (749:57): [True: 0, False: 0]
  ------------------
  750|      0|        loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT, 0,
  751|      0|                   "vkCreateInstance: Layer returning invalid extension error not triggered by ICD/Loader (Policy #LLP_LAYER_17).");
  752|      0|    }
  753|       |
  754|  8.37k|out:
  755|       |
  756|  8.37k|    if (NULL != ptr_instance) {
  ------------------
  |  Branch (756:9): [True: 8.37k, False: 0]
  ------------------
  757|  8.37k|        if (res != VK_SUCCESS) {
  ------------------
  |  Branch (757:13): [True: 8.37k, False: 0]
  ------------------
  758|       |            // error path, should clean everything up
  759|  8.37k|            if (loader.instances == ptr_instance) {
  ------------------
  |  Branch (759:17): [True: 0, False: 8.37k]
  ------------------
  760|      0|                loader.instances = ptr_instance->next;
  761|      0|            }
  762|       |
  763|  8.37k|            free_loader_settings(ptr_instance, &ptr_instance->settings);
  764|       |
  765|  8.37k|            loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->surfaces_list);
  766|  8.37k|            loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->debug_utils_messengers_list);
  767|  8.37k|            loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->debug_report_callbacks_list);
  768|       |
  769|  8.37k|            loader_instance_heap_free(ptr_instance, ptr_instance->disp);
  770|       |            // Remove any created VK_EXT_debug_report or VK_EXT_debug_utils items
  771|  8.37k|            destroy_debug_callbacks_chain(ptr_instance, pAllocator);
  772|       |
  773|  8.37k|            loader_destroy_pointer_layer_list(ptr_instance, &ptr_instance->expanded_activated_layer_list);
  774|       |
  775|  8.37k|            loader_delete_layer_list_and_properties(ptr_instance, &ptr_instance->instance_layer_list);
  776|  8.37k|            loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list);
  777|       |
  778|       |            // Free any icd_terms that were created.
  779|       |            // If an OOM occurs from a layer, terminator_CreateInstance won't be reached where this kind of
  780|       |            // cleanup normally occurs
  781|  8.37k|            struct loader_icd_term *icd_term = NULL;
  782|  8.37k|            while (NULL != ptr_instance->icd_terms) {
  ------------------
  |  Branch (782:20): [True: 0, False: 8.37k]
  ------------------
  783|      0|                icd_term = ptr_instance->icd_terms;
  784|       |                // Call destroy Instance on each driver in case we successfully called down the chain but failed on
  785|       |                // our way back out of it.
  786|      0|                if (icd_term->instance) {
  ------------------
  |  Branch (786:21): [True: 0, False: 0]
  ------------------
  787|      0|                    loader_icd_close_objects(ptr_instance, icd_term);
  788|      0|                    icd_term->dispatch.DestroyInstance(icd_term->instance, pAllocator);
  789|      0|                }
  790|      0|                icd_term->instance = VK_NULL_HANDLE;
  791|      0|                ptr_instance->icd_terms = icd_term->next;
  792|      0|                loader_icd_destroy(ptr_instance, icd_term, pAllocator);
  793|      0|            }
  794|       |
  795|  8.37k|            loader_clear_scanned_icd_list(ptr_instance, &ptr_instance->icd_tramp_list);
  796|  8.37k|            free_string_list(ptr_instance, &ptr_instance->enabled_layer_names);
  797|       |
  798|  8.37k|            loader_instance_heap_free(ptr_instance, ptr_instance);
  799|  8.37k|        } else {
  800|       |            // success path, swap out created debug callbacks out so they aren't used until instance destruction
  801|      0|            loader_remove_instance_only_debug_funcs(ptr_instance);
  802|      0|        }
  803|       |        // Only unlock when ptr_instance isn't NULL, as if it is, the above code didn't make it to when loader_lock was locked.
  804|  8.37k|        loader_platform_thread_unlock_mutex(&loader_lock);
  805|  8.37k|    }
  806|       |
  807|  8.37k|    return res;
  808|      0|}
trampoline.c:loader_log_instance_create_info:
  480|  8.37k|static void loader_log_instance_create_info(const struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo) {
  481|  8.37k|    const VkApplicationInfo *app_info = pCreateInfo->pApplicationInfo;
  482|  8.37k|    const char *app_name = (app_info && app_info->pApplicationName) ? app_info->pApplicationName : "";
  ------------------
  |  Branch (482:29): [True: 8.37k, False: 0]
  |  Branch (482:41): [True: 8.37k, False: 0]
  ------------------
  483|  8.37k|    const char *engine_name = (app_info && app_info->pEngineName) ? app_info->pEngineName : "";
  ------------------
  |  Branch (483:32): [True: 8.37k, False: 0]
  |  Branch (483:44): [True: 8.37k, False: 0]
  ------------------
  484|  8.37k|    uint32_t app_version = app_info ? app_info->applicationVersion : 0;
  ------------------
  |  Branch (484:28): [True: 8.37k, False: 0]
  ------------------
  485|  8.37k|    uint32_t engine_version = app_info ? app_info->engineVersion : 0;
  ------------------
  |  Branch (485:31): [True: 8.37k, False: 0]
  ------------------
  486|  8.37k|    uint32_t api_version = app_info ? app_info->apiVersion : 0;
  ------------------
  |  Branch (486:28): [True: 8.37k, False: 0]
  ------------------
  487|       |
  488|  8.37k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  489|  8.37k|               "vkCreateInstance: applicationName: \"%s\", applicationVersion: %u, engineName: \"%s\", engineVersion: %u, "
  490|  8.37k|               "apiVersion: %u.%u.%u",
  491|  8.37k|               app_name, app_version, engine_name, engine_version, VK_API_VERSION_MAJOR(api_version),
  492|  8.37k|               VK_API_VERSION_MINOR(api_version), VK_API_VERSION_PATCH(api_version));
  493|       |
  494|       |    // Guard the name arrays: this runs before the loader validates pCreateInfo, so the count may be non-zero with a null
  495|       |    // array (see the null-pointer tests).
  496|  8.37k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  497|  8.37k|               "vkCreateInstance: Requested %u instance layer(s):", pCreateInfo->enabledLayerCount);
  498|  8.37k|    if (pCreateInfo->ppEnabledLayerNames) {
  ------------------
  |  Branch (498:9): [True: 8.37k, False: 0]
  ------------------
  499|  16.7k|        for (uint32_t i = 0; i < pCreateInfo->enabledLayerCount; ++i) {
  ------------------
  |  Branch (499:30): [True: 8.37k, False: 8.37k]
  ------------------
  500|  8.37k|            if (pCreateInfo->ppEnabledLayerNames[i]) {
  ------------------
  |  Branch (500:17): [True: 8.37k, False: 0]
  ------------------
  501|  8.37k|                loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "   %s", pCreateInfo->ppEnabledLayerNames[i]);
  502|  8.37k|            } else {
  503|      0|                loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "   <NULL>");
  504|      0|            }
  505|  8.37k|        }
  506|  8.37k|    }
  507|       |
  508|  8.37k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  509|  8.37k|               "vkCreateInstance: Requested %u instance extension(s):", pCreateInfo->enabledExtensionCount);
  510|  8.37k|    if (pCreateInfo->ppEnabledExtensionNames) {
  ------------------
  |  Branch (510:9): [True: 0, False: 8.37k]
  ------------------
  511|      0|        for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; ++i) {
  ------------------
  |  Branch (511:30): [True: 0, False: 0]
  ------------------
  512|      0|            if (pCreateInfo->ppEnabledExtensionNames[i]) {
  ------------------
  |  Branch (512:17): [True: 0, False: 0]
  ------------------
  513|      0|                loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "   %s", pCreateInfo->ppEnabledExtensionNames[i]);
  514|      0|            } else {
  515|      0|                loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "   <NULL>");
  516|      0|            }
  517|      0|        }
  518|      0|    }
  519|  8.37k|}

trampoline.c:loader_platform_thread_lock_mutex:
  456|  8.37k|static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
trampoline.c:loader_platform_thread_unlock_mutex:
  457|  8.37k|static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
debug_utils.c:loader_platform_thread_lock_mutex:
  456|  10.4M|static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
debug_utils.c:loader_platform_thread_unlock_mutex:
  457|  10.4M|static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
loader.c:loader_platform_open_library_error:
  422|     33|static inline const char *loader_platform_open_library_error(const char *libPath) {
  423|     33|    (void)libPath;
  424|       |#if defined(__Fuchsia__)
  425|       |    return dlerror_fuchsia();
  426|       |#else
  427|       |    // NOLINTNEXTLINE(concurrency-mt-unsafe) - dlerror has no reentrant variant; the message is used immediately, not retained
  428|     33|    return dlerror();
  429|     33|#endif
  430|     33|}
loader.c:loader_strncpy:
  467|  5.54M|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  468|  5.54M|    (void)dest_sz;
  469|  5.54M|    return strncpy(dest, src, count);
  470|  5.54M|}
loader.c:thread_safe_strtok:
  460|  3.94M|static inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
loader.c:loader_platform_open_library:
  417|     33|static inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
  418|       |    return dlopen(libPath, LOADER_DLOPEN_MODE);
  ------------------
  |  |  407|     33|#define LOADER_DLOPEN_MODE (RTLD_LAZY | RTLD_LOCAL)
  ------------------
  419|     33|}
loader.c:loader_platform_thread_create_mutex:
  450|      4|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  451|      4|    pthread_mutexattr_t attr;
  452|      4|    pthread_mutexattr_init(&attr);
  453|      4|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  454|      4|    pthread_mutex_init(pMutex, &attr);
  455|      4|}
loader.c:loader_platform_is_path_absolute:
  296|  1.94M|static inline bool loader_platform_is_path_absolute(const char *path) {
  297|  1.94M|    if (path[0] == '/') return true;
  ------------------
  |  Branch (297:9): [True: 1.88M, False: 56.8k]
  ------------------
  298|  56.8k|    return false;
  299|  1.94M|}
loader.c:loader_platform_is_path:
  252|   138k|static inline bool loader_platform_is_path(const char *path) { return strchr(path, DIRECTORY_SYMBOL) != NULL; }
  ------------------
  |  |  155|   138k|#define DIRECTORY_SYMBOL '/'
  ------------------
loader.c:loader_platform_file_exists:
  289|   137k|static inline bool loader_platform_file_exists(const char *path) {
  290|   137k|    if (access(path, F_OK)) return false;
  ------------------
  |  Branch (290:9): [True: 2.69k, False: 134k]
  ------------------
  291|   134k|    return true;
  292|   137k|}
loader.c:loader_platform_executable_path:
  307|  7.98k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  308|  7.98k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  309|  7.98k|    if (count == -1) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 7.98k]
  ------------------
  310|  7.98k|    if (count == 0) return NULL;
  ------------------
  |  Branch (310:9): [True: 0, False: 7.98k]
  ------------------
  311|       |    // readlink does not append a null terminator and returns up to size bytes, so a target of size or more
  312|       |    // would leave no room for the terminator and buffer[count] would write past the end.
  313|  7.98k|    if ((size_t)count >= size) return NULL;
  ------------------
  |  Branch (313:9): [True: 0, False: 7.98k]
  ------------------
  314|  7.98k|    buffer[count] = '\0';
  315|  7.98k|    return buffer;
  316|  7.98k|}
loader_environment.c:thread_safe_strtok:
  460|  16.7k|static inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
loader_environment.c:loader_strncpy:
  467|  8.37k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  468|  8.37k|    (void)dest_sz;
  469|  8.37k|    return strncpy(dest, src, count);
  470|  8.37k|}
log.c:loader_strncat:
  463|  2.84M|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  464|  2.84M|    (void)dest_sz;
  465|  2.84M|    return strncat(dest, src, count);
  466|  2.84M|}
settings.c:loader_strncpy:
  467|  34.2k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  468|  34.2k|    (void)dest_sz;
  469|  34.2k|    return strncpy(dest, src, count);
  470|  34.2k|}
settings.c:loader_strncat:
  463|  18.8k|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  464|  18.8k|    (void)dest_sz;
  465|  18.8k|    return strncat(dest, src, count);
  466|  18.8k|}
settings.c:loader_platform_file_exists:
  289|  18.8k|static inline bool loader_platform_file_exists(const char *path) {
  290|  18.8k|    if (access(path, F_OK)) return false;
  ------------------
  |  Branch (290:9): [True: 10.9k, False: 7.94k]
  ------------------
  291|  7.94k|    return true;
  292|  18.8k|}
settings.c:loader_platform_executable_path:
  307|  2.13k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  308|  2.13k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  309|  2.13k|    if (count == -1) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 2.13k]
  ------------------
  310|  2.13k|    if (count == 0) return NULL;
  ------------------
  |  Branch (310:9): [True: 0, False: 2.13k]
  ------------------
  311|       |    // readlink does not append a null terminator and returns up to size bytes, so a target of size or more
  312|       |    // would leave no room for the terminator and buffer[count] would write past the end.
  313|  2.13k|    if ((size_t)count >= size) return NULL;
  ------------------
  |  Branch (313:9): [True: 0, False: 2.13k]
  ------------------
  314|  2.13k|    buffer[count] = '\0';
  315|  2.13k|    return buffer;
  316|  2.13k|}
settings.c:loader_platform_thread_create_mutex:
  450|      2|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  451|      2|    pthread_mutexattr_t attr;
  452|      2|    pthread_mutexattr_init(&attr);
  453|      2|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  454|      2|    pthread_mutex_init(pMutex, &attr);
  455|      2|}

wsi_unsupported_instance_extension:
  288|   310k|bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop) {
  289|       |#if !defined(VK_USE_PLATFORM_WAYLAND_KHR)
  290|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_wayland_surface")) return true;
  291|       |#endif  // VK_USE_PLATFORM_WAYLAND_KHR
  292|       |#if !defined(VK_USE_PLATFORM_XCB_KHR)
  293|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xcb_surface")) return true;
  294|       |#endif  // VK_USE_PLATFORM_XCB_KHR
  295|       |#if !defined(VK_USE_PLATFORM_XLIB_KHR)
  296|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xlib_surface")) return true;
  297|       |#endif  // VK_USE_PLATFORM_XLIB_KHR
  298|   310k|#if !defined(VK_USE_PLATFORM_DIRECTFB_EXT)
  299|   310k|    if (!strcmp(ext_prop->extensionName, "VK_EXT_directfb_surface")) return true;
  ------------------
  |  Branch (299:9): [True: 248, False: 310k]
  ------------------
  300|   310k|#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
  301|   310k|#if !defined(VK_USE_PLATFORM_SCREEN_QNX)
  302|   310k|    if (!strcmp(ext_prop->extensionName, "VK_QNX_screen_surface")) return true;
  ------------------
  |  Branch (302:9): [True: 208, False: 310k]
  ------------------
  303|   310k|#endif  // VK_USE_PLATFORM_SCREEN_QNX
  304|       |
  305|   310k|    return false;
  306|   310k|}

