fuzz_init:
   25|  6.52k|void fuzz_init(const uint8_t *data, size_t size) {
   26|  6.52k|    global_fuzz_data = (uint8_t *)data;
   27|  6.52k|    global_size = size;
   28|       |    
   29|  6.52k|    callback1 = NULL;
   30|  6.52k|    callback2 = NULL;
   31|  6.52k|    callback3 = NULL;
   32|       |    callback4 = NULL;
   33|  6.52k|}
create_callback_file:
   36|  5.23k|void create_callback_file(const char *filename) {
   37|  5.23k|  fprintf(stderr, "create_callback_file: Creating file %s\n", filename);
   38|  5.23k|  FILE *fp = fopen(filename, "wb");
   39|  5.23k|  if (!fp) {
  ------------------
  |  Branch (39:7): [True: 176, False: 5.06k]
  ------------------
   40|    176|    return;
   41|    176|  }
   42|  5.06k|  fwrite(global_fuzz_data, global_size, 1, fp);
   43|  5.06k|  fclose(fp);
   44|       |
   45|  5.06k|  if (callback1 == NULL) {
  ------------------
  |  Branch (45:7): [True: 2.26k, False: 2.80k]
  ------------------
   46|  2.26k|    callback1 = strdup(filename);
   47|  2.80k|  } else if (callback2 == NULL) {
  ------------------
  |  Branch (47:14): [True: 1.25k, False: 1.54k]
  ------------------
   48|  1.25k|    callback2 = strdup(filename);
   49|  1.54k|  } else if (callback3 == NULL) {
  ------------------
  |  Branch (49:14): [True: 767, False: 780]
  ------------------
   50|    767|    callback3 = strdup(filename);
   51|    780|  } else if (callback4 == NULL) {
  ------------------
  |  Branch (51:14): [True: 419, False: 361]
  ------------------
   52|    419|    callback4 = strdup(filename);
   53|    419|  } else {
   54|       |    fprintf(stderr, "create_callback_file: Too many callbacks created, ignoring %s\n", filename);
   55|    361|  }
   56|  5.06k|}
fuzz_cleanup:
   62|  6.52k|void fuzz_cleanup() {
   63|  6.52k|  if (callback1) {
  ------------------
  |  Branch (63:7): [True: 2.26k, False: 4.26k]
  ------------------
   64|  2.26k| unlink(callback1);    
   65|  2.26k|    free(callback1);
   66|       |   
   67|  2.26k|    callback1 = NULL;
   68|  2.26k|  }
   69|  6.52k|  if (callback2) {
  ------------------
  |  Branch (69:7): [True: 1.25k, False: 5.26k]
  ------------------
   70|  1.25k| unlink(callback2);    
   71|  1.25k|    free(callback2);
   72|  1.25k|    callback2 = NULL;
   73|  1.25k|  }
   74|  6.52k|  if (callback3) {
  ------------------
  |  Branch (74:7): [True: 767, False: 5.75k]
  ------------------
   75|    767| unlink(callback3);      
   76|    767|    free(callback3);
   77|    767|    callback3 = NULL;
   78|    767|  }
   79|  6.52k|  if (callback4) {
  ------------------
  |  Branch (79:7): [True: 419, False: 6.10k]
  ------------------
   80|    419|     unlink(callback4);
   81|    419|    free(callback4);
   82|       |    callback4 = NULL;
   83|    419|  }
   84|  6.52k|}

LLVMFuzzerInitialize:
   22|      2|int LLVMFuzzerInitialize(int *argc, char ***argv) {
   23|      2|  setenv("HOME", "/tmp", 1);
   24|      2|  system("mkdir -p $HOME/.local/share/vulkan/implicit_layer.d");
   25|      2|  system("mkdir -p $HOME/.local/share/vulkan/loader_settings.d");
   26|      2|  system("mkdir -p $HOME/.local/share/vulkan/icd.d");
   27|      2|  return 0;
   28|      2|}
create_config_file:
   33|  19.5k|int create_config_file(const char* config_path, const char* config_filename, const uint8_t* data, size_t size) {
   34|  19.5k|  char filename[512];
   35|  19.5k|  char path[256];
   36|       |  // char command[256];
   37|       |
   38|  19.5k|  sprintf(path, "%s/%s", getenv("HOME"), config_path);
   39|       |  //sprintf(command, "mkdir -p %s", path);
   40|       |
   41|       |  //system(command);
   42|       |
   43|  19.5k|  sprintf(filename, "%s/%s", path, config_filename);
   44|       |
   45|  19.5k|  FILE *fp = fopen(filename, "wb");
   46|  19.5k|  if (!fp) {
  ------------------
  |  Branch (46:7): [True: 0, False: 19.5k]
  ------------------
   47|      0|    return 1;
   48|      0|  }
   49|  19.5k|  fwrite(data, size, 1, fp);
   50|  19.5k|  fclose(fp);
   51|       |
   52|  19.5k|  return 0;
   53|  19.5k|}
remove_config_file:
   58|  19.5k|void remove_config_file(const char* config_path, const char* config_filename) {
   59|  19.5k|  char filename[512];
   60|  19.5k|  sprintf(filename, "%s/%s/%s", getenv("HOME"), config_path, config_filename);
   61|  19.5k|  unlink(filename);
   62|  19.5k|}
LLVMFuzzerTestOneInput:
   67|  6.54k|int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   68|  6.54k|  if (size < 3*sizeof(size_t)) {
  ------------------
  |  Branch (68:7): [True: 8, False: 6.54k]
  ------------------
   69|      8|    return 0;
   70|      8|  }
   71|       |
   72|       |  // Split the loaders into two different parts so the files
   73|       |  // are independently seeded with fuzz data.
   74|  6.54k|  size_t first_size = (*(size_t*)data) % 40000;
   75|  6.54k|  size_t second_size = (*(size_t*)(data + sizeof(size_t))) % 40000;
   76|  6.54k|  size_t third_size = (*(size_t*)(data + 2*sizeof(size_t))) % 40000;
   77|       |
   78|  6.54k|  data += 3*sizeof(size_t); // Move past the first two integers
   79|  6.54k|  size -= 3*sizeof(size_t); // Adjust size to account for the first two integers
   80|  6.54k|  size_t total_size_needed = first_size + second_size + third_size;
   81|  6.54k|  if (size <= total_size_needed) {
  ------------------
  |  Branch (81:7): [True: 18, False: 6.52k]
  ------------------
   82|     18|    return 0;
   83|     18|  }
   84|  6.52k|  int result = create_config_file(".local/share/vulkan/implicit_layer.d", "complex_layer.json", data, first_size);
   85|  6.52k|  if (result) {
  ------------------
  |  Branch (85:7): [True: 0, False: 6.52k]
  ------------------
   86|      0|    return 0;
   87|      0|  }
   88|       |
   89|  6.52k|  data += first_size;
   90|  6.52k|  size -= first_size;
   91|  6.52k|  result = create_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json", data, second_size);
   92|  6.52k|  if (result) {
  ------------------
  |  Branch (92:7): [True: 0, False: 6.52k]
  ------------------
   93|      0|    return 0;
   94|      0|  }
   95|       |
   96|  6.52k|  data += second_size;
   97|  6.52k|  size -= second_size;
   98|  6.52k|  result = create_config_file(".local/share/vulkan/loader_settings.d", "icd_test.json", data, third_size);
   99|  6.52k|  if (result) {
  ------------------
  |  Branch (99:7): [True: 0, False: 6.52k]
  ------------------
  100|      0|    return 0;
  101|      0|  }
  102|  6.52k|  data += third_size;
  103|  6.52k|  size -= third_size;
  104|       |
  105|  6.52k|  fuzz_init(data, size);
  106|       |
  107|  6.52k|  setenv("VK_LOADER_LAYERS_ENABLE", "all", 1);
  108|       |
  109|       |
  110|  6.52k|  VkInstance inst = {0};
  111|  6.52k|  char *instance_layers[] = {
  112|  6.52k|    "VK_LAYER_KHRONOS_validation",
  113|  6.52k|    "VK_LAYER_test_layer_1",
  114|  6.52k|    "VK_LAYER_test_layer_2"
  115|  6.52k|  };
  116|  6.52k|  const VkApplicationInfo app = {
  117|  6.52k|      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
  118|  6.52k|      .pNext = NULL,
  119|  6.52k|      .pApplicationName = "TEST_APP",
  120|  6.52k|      .applicationVersion = 0,
  121|  6.52k|      .pEngineName = "TEST_ENGINE",
  122|  6.52k|      .engineVersion = 0,
  123|  6.52k|      .apiVersion = VK_API_VERSION_1_0,
  ------------------
  |  |   92|  6.52k|#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)// Patch version should always be set to 0
  |  |  ------------------
  |  |  |  |   63|  6.52k|    ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch)))
  |  |  ------------------
  ------------------
  124|  6.52k|  };
  125|  6.52k|  VkInstanceCreateInfo inst_info = {
  126|  6.52k|      .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
  127|  6.52k|      .pNext = NULL,
  128|  6.52k|      .pApplicationInfo = &app,
  129|  6.52k|      .enabledLayerCount = 1,
  130|  6.52k|      .ppEnabledLayerNames = (const char *const *)instance_layers,
  131|  6.52k|      .enabledExtensionCount = 0,
  132|  6.52k|      .ppEnabledExtensionNames = NULL,
  133|  6.52k|  };
  134|  6.52k|  VkResult err = vkCreateInstance(&inst_info, NULL, &inst);
  135|  6.52k|  if (err != VK_SUCCESS) {
  ------------------
  |  Branch (135:7): [True: 6.52k, False: 0]
  ------------------
  136|  6.52k|    goto out;
  137|  6.52k|  }
  138|      0|  else {
  139|       |
  140|      0|  }
  141|       |
  142|      0|  vkDestroyInstance(inst, NULL);
  143|       |
  144|  6.52k|out:
  145|       |  // Clean up config files
  146|  6.52k|  remove_config_file(".local/share/vulkan/implicit_layer.d", "complex_layer.json");
  147|  6.52k|  remove_config_file(".local/share/vulkan/loader_settings.d", "vk_loader_settings.json");
  148|  6.52k|  remove_config_file(".local/share/vulkan/icd.d", "icd_test.json");
  149|       |
  150|       |
  151|  6.52k|  fuzz_cleanup();
  152|       |
  153|  6.52k|  return 0;
  154|      0|}

loader_alloc:
   34|  10.0k|void *loader_alloc(const VkAllocationCallbacks *pAllocator, size_t size, VkSystemAllocationScope allocation_scope) {
   35|  10.0k|    void *pMemory = NULL;
   36|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   37|       |    {
   38|       |#else
   39|  10.0k|    if (pAllocator && pAllocator->pfnAllocation) {
  ------------------
  |  Branch (39:9): [True: 10.0k, False: 0]
  |  Branch (39:23): [True: 0, False: 10.0k]
  ------------------
   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|  10.0k|    } else {
   44|  10.0k|#endif
   45|  10.0k|        pMemory = malloc(size);
   46|  10.0k|    }
   47|       |
   48|  10.0k|    return pMemory;
   49|  10.0k|}
loader_calloc:
   51|  4.69M|void *loader_calloc(const VkAllocationCallbacks *pAllocator, size_t size, VkSystemAllocationScope allocation_scope) {
   52|  4.69M|    void *pMemory = NULL;
   53|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   54|       |    {
   55|       |#else
   56|  4.69M|    if (pAllocator && pAllocator->pfnAllocation) {
  ------------------
  |  Branch (56:9): [True: 4.69M, False: 6.52k]
  |  Branch (56:23): [True: 0, False: 4.69M]
  ------------------
   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|  4.69M|    } else {
   64|  4.69M|#endif
   65|  4.69M|        pMemory = calloc(1, size);
   66|  4.69M|    }
   67|       |
   68|  4.69M|    return pMemory;
   69|  4.69M|}
loader_free:
   71|  9.97M|void loader_free(const VkAllocationCallbacks *pAllocator, void *pMemory) {
   72|  9.97M|    if (pMemory != NULL) {
  ------------------
  |  Branch (72:9): [True: 4.70M, False: 5.26M]
  ------------------
   73|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   74|       |        {
   75|       |#else
   76|  4.70M|        if (pAllocator && pAllocator->pfnFree) {
  ------------------
  |  Branch (76:13): [True: 4.70M, False: 0]
  |  Branch (76:27): [True: 0, False: 4.70M]
  ------------------
   77|      0|            pAllocator->pfnFree(pAllocator->pUserData, pMemory);
   78|  4.70M|        } else {
   79|  4.70M|#endif
   80|  4.70M|            free(pMemory);
   81|  4.70M|        }
   82|  4.70M|    }
   83|  9.97M|}
loader_realloc:
   86|   127k|                     VkSystemAllocationScope allocation_scope) {
   87|   127k|    void *pNewMem = NULL;
   88|   127k|    if (pMemory == NULL || orig_size == 0) {
  ------------------
  |  Branch (88:9): [True: 0, False: 127k]
  |  Branch (88:28): [True: 0, False: 127k]
  ------------------
   89|      0|        pNewMem = loader_alloc(pAllocator, size, allocation_scope);
   90|   127k|    } else if (size == 0) {
  ------------------
  |  Branch (90:16): [True: 0, False: 127k]
  ------------------
   91|      0|        loader_free(pAllocator, pMemory);
   92|       |#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
   93|       |#else
   94|   127k|    } else if (pAllocator && pAllocator->pfnReallocation) {
  ------------------
  |  Branch (94:16): [True: 127k, False: 0]
  |  Branch (94:30): [True: 0, False: 127k]
  ------------------
   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|   127k|    } else {
  100|   127k|        pNewMem = realloc(pMemory, size);
  101|       |        // Clear out the newly allocated memory
  102|   127k|        if (size > orig_size) {
  ------------------
  |  Branch (102:13): [True: 1.63k, False: 125k]
  ------------------
  103|  1.63k|            memset((uint8_t *)pNewMem + orig_size, 0, size - orig_size);
  104|  1.63k|        }
  105|   127k|    }
  106|   127k|    return pNewMem;
  107|   127k|}
loader_instance_heap_alloc:
  109|  10.0k|void *loader_instance_heap_alloc(const struct loader_instance *inst, size_t size, VkSystemAllocationScope allocation_scope) {
  110|  10.0k|    return loader_alloc(inst ? &inst->alloc_callbacks : NULL, size, allocation_scope);
  ------------------
  |  Branch (110:25): [True: 10.0k, False: 0]
  ------------------
  111|  10.0k|}
loader_instance_heap_calloc:
  113|   454k|void *loader_instance_heap_calloc(const struct loader_instance *inst, size_t size, VkSystemAllocationScope allocation_scope) {
  114|   454k|    return loader_calloc(inst ? &inst->alloc_callbacks : NULL, size, allocation_scope);
  ------------------
  |  Branch (114:26): [True: 454k, False: 0]
  ------------------
  115|   454k|}
loader_instance_heap_free:
  117|  5.86M|void loader_instance_heap_free(const struct loader_instance *inst, void *pMemory) {
  118|  5.86M|    loader_free(inst ? &inst->alloc_callbacks : NULL, pMemory);
  ------------------
  |  Branch (118:17): [True: 5.86M, False: 2]
  ------------------
  119|  5.86M|}
loader_instance_heap_realloc:
  121|    814|                                   VkSystemAllocationScope allocation_scope) {
  122|    814|    return loader_realloc(inst ? &inst->alloc_callbacks : NULL, pMemory, orig_size, size, allocation_scope);
  ------------------
  |  Branch (122:27): [True: 814, False: 0]
  ------------------
  123|    814|}

loader_cJSON_GetStringValue:
   98|   507k|CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
   99|   507k|    if (!loader_cJSON_IsString(item)) {
  ------------------
  |  Branch (99:9): [True: 238k, False: 269k]
  ------------------
  100|   238k|        return NULL;
  101|   238k|    }
  102|       |
  103|   269k|    return item->valuestring;
  104|   507k|}
loader_cJSON_Delete:
  151|   566k|TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
  152|   566k|    cJSON *next = NULL;
  153|  2.74M|    while (item != NULL) {
  ------------------
  |  Branch (153:12): [True: 2.17M, False: 566k]
  ------------------
  154|  2.17M|        next = item->next;
  155|  2.17M|        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
  ------------------
  |  |  106|  2.17M|#define cJSON_IsReference 256
  ------------------
  |  Branch (155:13): [True: 2.17M, False: 0]
  |  Branch (155:50): [True: 444k, False: 1.72M]
  ------------------
  156|   444k|            loader_cJSON_Delete(item->child);
  157|   444k|        }
  158|  2.17M|        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
  ------------------
  |  |  106|  2.17M|#define cJSON_IsReference 256
  ------------------
  |  Branch (158:13): [True: 2.17M, False: 0]
  |  Branch (158:50): [True: 959k, False: 1.21M]
  ------------------
  159|   959k|            loader_free(item->pAllocator, item->valuestring);
  160|   959k|            item->valuestring = NULL;
  161|   959k|        }
  162|  2.17M|        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
  ------------------
  |  |  107|  2.17M|#define cJSON_StringIsConst 512
  ------------------
  |  Branch (162:13): [True: 2.17M, False: 0]
  |  Branch (162:52): [True: 978k, False: 1.19M]
  ------------------
  163|   978k|            loader_free(item->pAllocator, item->string);
  164|       |            item->string = NULL;
  165|   978k|        }
  166|  2.17M|        loader_free(item->pAllocator, item);
  167|  2.17M|        item = next;
  168|  2.17M|    }
  169|   566k|}
loader_cJSON_ParseWithLengthOpts:
  821|  19.1k|                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
  822|  19.1k|    parse_buffer buffer = {0, 0, 0, 0, 0};
  823|  19.1k|    cJSON *item = NULL;
  824|       |
  825|       |    /* reset error position */
  826|       |    // global_error.json = NULL;
  827|       |    // global_error.position = 0;
  828|       |
  829|  19.1k|    if (value == NULL || 0 == buffer_length) {
  ------------------
  |  Branch (829:9): [True: 0, False: 19.1k]
  |  Branch (829:26): [True: 0, False: 19.1k]
  ------------------
  830|      0|        goto fail;
  831|      0|    }
  832|       |
  833|  19.1k|    buffer.content = (const unsigned char *)value;
  834|  19.1k|    buffer.length = buffer_length;
  835|  19.1k|    buffer.offset = 0;
  836|  19.1k|    buffer.pAllocator = pAllocator;
  837|       |
  838|  19.1k|    item = cJSON_New_Item(pAllocator);
  839|  19.1k|    if (item == NULL) /* memory fail */
  ------------------
  |  Branch (839:9): [True: 0, False: 19.1k]
  ------------------
  840|      0|    {
  841|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  842|      0|        goto fail;
  843|      0|    }
  844|       |
  845|  19.1k|    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
  ------------------
  |  Branch (845:9): [True: 7.21k, False: 11.9k]
  ------------------
  846|       |        /* parse failure. ep is set. */
  847|  7.21k|        goto fail;
  848|  7.21k|    }
  849|       |
  850|       |    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
  851|  11.9k|    if (require_null_terminated) {
  ------------------
  |  Branch (851:9): [True: 0, False: 11.9k]
  ------------------
  852|      0|        buffer_skip_whitespace(&buffer);
  853|      0|        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (853:13): [True: 0, False: 0]
  |  Branch (853:49): [True: 0, False: 0]
  ------------------
  854|      0|            goto fail;
  855|      0|        }
  856|      0|    }
  857|  11.9k|    if (return_parse_end) {
  ------------------
  |  Branch (857:9): [True: 0, False: 11.9k]
  ------------------
  858|      0|        *return_parse_end = (const char *)buffer_at_offset(&buffer);
  ------------------
  |  |  195|      0|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  859|      0|    }
  860|       |
  861|  11.9k|    return item;
  862|       |
  863|  7.21k|fail:
  864|  7.21k|    if (item != NULL) {
  ------------------
  |  Branch (864:9): [True: 7.21k, False: 0]
  ------------------
  865|  7.21k|        loader_cJSON_Delete(item);
  866|  7.21k|    }
  867|       |
  868|  7.21k|    if (value != NULL) {
  ------------------
  |  Branch (868:9): [True: 7.21k, False: 0]
  ------------------
  869|  7.21k|        error local_error;
  870|  7.21k|        local_error.json = (const unsigned char *)value;
  871|  7.21k|        local_error.position = 0;
  872|       |
  873|  7.21k|        if (buffer.offset < buffer.length) {
  ------------------
  |  Branch (873:13): [True: 7.01k, False: 198]
  ------------------
  874|  7.01k|            local_error.position = buffer.offset;
  875|  7.01k|        } else if (buffer.length > 0) {
  ------------------
  |  Branch (875:20): [True: 198, False: 0]
  ------------------
  876|    198|            local_error.position = buffer.length - 1;
  877|    198|        }
  878|       |
  879|  7.21k|        if (return_parse_end != NULL) {
  ------------------
  |  Branch (879:13): [True: 0, False: 7.21k]
  ------------------
  880|      0|            *return_parse_end = (const char *)local_error.json + local_error.position;
  881|      0|        }
  882|       |
  883|       |        // global_error = local_error;
  884|  7.21k|    }
  885|       |
  886|       |    return NULL;
  887|  11.9k|}
loader_cJSON_ParseWithLength:
  896|  19.1k|                             bool *out_of_memory) {
  897|  19.1k|    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
  898|  19.1k|}
loader_cJSON_Print:
  950|   125k|TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
  951|   125k|    return (char *)print(item, true, out_of_memory);
  ------------------
  |  |   67|   125k|#define true ((cJSON_bool)1)
  ------------------
  952|   125k|}
loader_cJSON_PrintPreallocated:
  987|   301k|loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
  988|   301k|    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
  989|       |
  990|   301k|    if ((length < 0) || (buffer == NULL)) {
  ------------------
  |  Branch (990:9): [True: 0, False: 301k]
  |  Branch (990:25): [True: 0, False: 301k]
  ------------------
  991|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  992|      0|    }
  993|       |
  994|   301k|    p.buffer = (unsigned char *)buffer;
  995|   301k|    p.length = (size_t)length;
  996|   301k|    p.offset = 0;
  997|   301k|    p.noalloc = true;
  ------------------
  |  |   67|   301k|#define true ((cJSON_bool)1)
  ------------------
  998|   301k|    p.format = format;
  999|   301k|    p.pAllocator = item->pAllocator;
 1000|   301k|    bool out_of_memory = false;
  ------------------
  |  |   72|   301k|#define false ((cJSON_bool)0)
  ------------------
 1001|   301k|    return print_value(item, &p, &out_of_memory);
 1002|   301k|}
loader_cJSON_GetArraySize:
 1454|  14.7k|CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
 1455|  14.7k|    cJSON *child = NULL;
 1456|  14.7k|    size_t size = 0;
 1457|       |
 1458|  14.7k|    if (array == NULL) {
  ------------------
  |  Branch (1458:9): [True: 0, False: 14.7k]
  ------------------
 1459|      0|        return 0;
 1460|      0|    }
 1461|       |
 1462|  14.7k|    child = array->child;
 1463|       |
 1464|   114k|    while (child != NULL) {
  ------------------
  |  Branch (1464:12): [True: 99.5k, False: 14.7k]
  ------------------
 1465|  99.5k|        size++;
 1466|  99.5k|        child = child->next;
 1467|  99.5k|    }
 1468|       |
 1469|       |    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
 1470|       |
 1471|  14.7k|    return (int)size;
 1472|  14.7k|}
loader_cJSON_GetObjectItem:
 1524|  1.12M|CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
 1525|  1.12M|    return get_object_item(object, string, false);
  ------------------
  |  |   72|  1.12M|#define false ((cJSON_bool)0)
  ------------------
 1526|  1.12M|}
loader_cJSON_IsString:
 1667|   507k|CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
 1668|   507k|    if (item == NULL) {
  ------------------
  |  Branch (1668:9): [True: 238k, False: 269k]
  ------------------
 1669|   238k|        return false;
  ------------------
  |  |   72|   238k|#define false ((cJSON_bool)0)
  ------------------
 1670|   238k|    }
 1671|       |
 1672|   269k|    return (item->type & 0xFF) == cJSON_String;
  ------------------
  |  |  101|   269k|#define cJSON_String (1 << 4)
  ------------------
 1673|   507k|}
cJSON.c:cJSON_New_Item:
  142|  2.17M|static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
  143|  2.17M|    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  144|  2.17M|    if (NULL != node) {
  ------------------
  |  Branch (144:9): [True: 2.17M, False: 0]
  ------------------
  145|  2.17M|        node->pAllocator = pAllocator;
  146|  2.17M|    }
  147|  2.17M|    return node;
  148|  2.17M|}
cJSON.c:buffer_skip_whitespace:
  769|  6.76M|static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
  770|  6.76M|    if ((buffer == NULL) || (buffer->content == NULL)) {
  ------------------
  |  Branch (770:9): [True: 0, False: 6.76M]
  |  Branch (770:29): [True: 0, False: 6.76M]
  ------------------
  771|      0|        return NULL;
  772|      0|    }
  773|       |
  774|  6.76M|    if (cannot_access_at_index(buffer, 0)) {
  ------------------
  |  |  193|  6.76M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  6.76M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 6.76M, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 6.76M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  775|      0|        return buffer;
  776|      0|    }
  777|       |
  778|  20.0M|    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  192|  40.1M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 20.0M, False: 0]
  |  |  |  Branch (192:65): [True: 20.0M, False: 4.65k]
  |  |  ------------------
  ------------------
                  while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
  ------------------
  |  |  195|  20.0M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (778:46): [True: 13.3M, False: 6.76M]
  ------------------
  779|  13.3M|        buffer->offset++;
  780|  13.3M|    }
  781|       |
  782|  6.76M|    if (buffer->offset == buffer->length) {
  ------------------
  |  Branch (782:9): [True: 4.65k, False: 6.76M]
  ------------------
  783|  4.65k|        buffer->offset--;
  784|  4.65k|    }
  785|       |
  786|  6.76M|    return buffer;
  787|  6.76M|}
cJSON.c:skip_utf8_bom:
  790|  19.1k|static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
  791|  19.1k|    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
  ------------------
  |  Branch (791:9): [True: 0, False: 19.1k]
  |  Branch (791:29): [True: 0, False: 19.1k]
  |  Branch (791:58): [True: 0, False: 19.1k]
  ------------------
  792|      0|        return NULL;
  793|      0|    }
  794|       |
  795|  19.1k|    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  192|  38.3k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 19.1k, False: 0]
  |  |  |  Branch (192:65): [True: 14.7k, False: 4.44k]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
  ------------------
  |  |  195|  14.7k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (795:43): [True: 121, False: 14.6k]
  ------------------
  796|    121|        buffer->offset += 3;
  797|    121|    }
  798|       |
  799|  19.1k|    return buffer;
  800|  19.1k|}
cJSON.c:print:
  902|   125k|static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
  903|   125k|    static const size_t default_buffer_size = 256;
  904|   125k|    printbuffer buffer[1];
  905|   125k|    unsigned char *printed = NULL;
  906|       |
  907|   125k|    memset(buffer, 0, sizeof(buffer));
  908|       |
  909|       |    /* create buffer */
  910|   125k|    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  911|   125k|    buffer->length = default_buffer_size;
  912|   125k|    buffer->format = format;
  913|   125k|    buffer->pAllocator = item->pAllocator;
  914|   125k|    if (buffer->buffer == NULL) {
  ------------------
  |  Branch (914:9): [True: 0, False: 125k]
  ------------------
  915|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  916|      0|        goto fail;
  917|      0|    }
  918|       |
  919|       |    /* print the value */
  920|   125k|    if (!print_value(item, buffer, out_of_memory)) {
  ------------------
  |  Branch (920:9): [True: 0, False: 125k]
  ------------------
  921|      0|        goto fail;
  922|      0|    }
  923|   125k|    update_offset(buffer);
  924|       |
  925|   125k|    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
  926|   125k|                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  927|   125k|    if (printed == NULL) {
  ------------------
  |  Branch (927:9): [True: 0, False: 125k]
  ------------------
  928|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  929|      0|        goto fail;
  930|      0|    }
  931|   125k|    buffer->buffer = NULL;
  932|       |
  933|   125k|    return printed;
  934|       |
  935|      0|fail:
  936|      0|    if (buffer->buffer != NULL) {
  ------------------
  |  Branch (936:9): [True: 0, False: 0]
  ------------------
  937|      0|        loader_free(item->pAllocator, buffer->buffer);
  938|      0|        buffer->buffer = NULL;
  939|      0|    }
  940|       |
  941|      0|    if (printed != NULL) {
  ------------------
  |  Branch (941:9): [True: 0, False: 0]
  ------------------
  942|      0|        loader_free(item->pAllocator, printed);
  943|      0|        printed = NULL;
  944|      0|    }
  945|       |
  946|       |    return NULL;
  947|   125k|}
cJSON.c:update_offset:
  331|   125k|static void update_offset(printbuffer *const buffer) {
  332|   125k|    const unsigned char *buffer_pointer = NULL;
  333|   125k|    if ((buffer == NULL) || (buffer->buffer == NULL)) {
  ------------------
  |  Branch (333:9): [True: 0, False: 125k]
  |  Branch (333:29): [True: 0, False: 125k]
  ------------------
  334|      0|        return;
  335|      0|    }
  336|   125k|    buffer_pointer = buffer->buffer + buffer->offset;
  337|       |
  338|   125k|    buffer->offset += strlen((const char *)buffer_pointer);
  339|   125k|}
cJSON.c:parse_value:
 1005|  2.17M|static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1006|  2.17M|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (1006:9): [True: 0, False: 2.17M]
  |  Branch (1006:35): [True: 0, False: 2.17M]
  ------------------
 1007|      0|        return false; /* no input */
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1008|      0|    }
 1009|       |
 1010|       |    /* parse the different types of values */
 1011|       |    /* null */
 1012|  2.17M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  190|  4.34M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.17M, False: 0]
  |  |  |  Branch (190:53): [True: 2.16M, False: 5.11k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
  ------------------
  |  |  195|  2.16M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1012:38): [True: 340, False: 2.16M]
  ------------------
 1013|    340|        item->type = cJSON_NULL;
  ------------------
  |  |   99|    340|#define cJSON_NULL (1 << 2)
  ------------------
 1014|    340|        input_buffer->offset += 4;
 1015|    340|        return true;
  ------------------
  |  |   67|    340|#define true ((cJSON_bool)1)
  ------------------
 1016|    340|    }
 1017|       |    /* false */
 1018|  2.17M|    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  190|  4.34M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.17M, False: 0]
  |  |  |  Branch (190:53): [True: 2.16M, False: 5.50k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
  ------------------
  |  |  195|  2.16M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1018:38): [True: 157, False: 2.16M]
  ------------------
 1019|    157|        item->type = cJSON_False;
  ------------------
  |  |   97|    157|#define cJSON_False (1 << 0)
  ------------------
 1020|    157|        input_buffer->offset += 5;
 1021|    157|        return true;
  ------------------
  |  |   67|    157|#define true ((cJSON_bool)1)
  ------------------
 1022|    157|    }
 1023|       |    /* true */
 1024|  2.17M|    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  190|  4.34M|#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (190:33): [True: 2.17M, False: 0]
  |  |  |  Branch (190:53): [True: 2.16M, False: 5.11k]
  |  |  ------------------
  ------------------
                  if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
  ------------------
  |  |  195|  2.16M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1024:38): [True: 59.4k, False: 2.10M]
  ------------------
 1025|  59.4k|        item->type = cJSON_True;
  ------------------
  |  |   98|  59.4k|#define cJSON_True (1 << 1)
  ------------------
 1026|  59.4k|        item->valueint = 1;
 1027|  59.4k|        input_buffer->offset += 4;
 1028|  59.4k|        return true;
  ------------------
  |  |   67|  59.4k|#define true ((cJSON_bool)1)
  ------------------
 1029|  59.4k|    }
 1030|       |    /* string */
 1031|  2.11M|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  192|  4.22M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 2.11M, False: 0]
  |  |  |  Branch (192:65): [True: 2.11M, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
  ------------------
  |  |  195|  2.11M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1031:49): [True: 960k, False: 1.15M]
  ------------------
 1032|   960k|        return parse_string(item, input_buffer, out_of_memory);
 1033|   960k|    }
 1034|       |    /* number */
 1035|  1.15M|    if (can_access_at_index(input_buffer, 0) &&
  ------------------
  |  |  192|  2.30M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 1.15M, False: 0]
  |  |  |  Branch (192:65): [True: 1.15M, False: 0]
  |  |  ------------------
  ------------------
 1036|  1.15M|        ((buffer_at_offset(input_buffer)[0] == '-') ||
  ------------------
  |  |  195|  1.15M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1036:10): [True: 25.4k, False: 1.12M]
  ------------------
 1037|  1.12M|         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|  1.12M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
                       ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
  ------------------
  |  |  195|  1.12M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1037:11): [True: 1.12M, False: 3.90k]
  |  Branch (1037:57): [True: 540k, False: 583k]
  ------------------
 1038|   565k|        return parse_number(item, input_buffer);
 1039|   565k|    }
 1040|       |    /* array */
 1041|   587k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  192|  1.17M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 587k, False: 0]
  |  |  |  Branch (192:65): [True: 587k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
  ------------------
  |  |  195|   587k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1041:49): [True: 158k, False: 428k]
  ------------------
 1042|   158k|        return parse_array(item, input_buffer, out_of_memory);
 1043|   158k|    }
 1044|       |    /* object */
 1045|   428k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  192|   857k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 428k, False: 0]
  |  |  |  Branch (192:65): [True: 428k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
  ------------------
  |  |  195|   428k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1045:49): [True: 423k, False: 5.25k]
  ------------------
 1046|   423k|        return parse_object(item, input_buffer, out_of_memory);
 1047|   423k|    }
 1048|       |
 1049|  5.25k|    return false;
  ------------------
  |  |   72|  5.25k|#define false ((cJSON_bool)0)
  ------------------
 1050|   428k|}
cJSON.c:parse_string:
  533|  1.93M|static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
  534|  1.93M|    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  1.93M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  535|  1.93M|    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
  ------------------
  |  |  195|  1.93M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  536|  1.93M|    unsigned char *output_pointer = NULL;
  537|  1.93M|    unsigned char *output = NULL;
  538|       |
  539|       |    /* not a string */
  540|  1.93M|    if (buffer_at_offset(input_buffer)[0] != '\"') {
  ------------------
  |  |  195|  1.93M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (540:9): [True: 278, False: 1.93M]
  ------------------
  541|    278|        goto fail;
  542|    278|    }
  543|       |
  544|  1.93M|    {
  545|       |        /* calculate approximate size of the output (overestimate) */
  546|  1.93M|        size_t allocation_length = 0;
  547|  1.93M|        size_t skipped_bytes = 0;
  548|   122M|        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
  ------------------
  |  Branch (548:16): [True: 122M, False: 173]
  |  Branch (548:88): [True: 120M, False: 1.93M]
  ------------------
  549|       |            /* is escape sequence */
  550|   120M|            if (input_end[0] == '\\') {
  ------------------
  |  Branch (550:17): [True: 353k, False: 120M]
  ------------------
  551|   353k|                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
  ------------------
  |  Branch (551:21): [True: 0, False: 353k]
  ------------------
  552|       |                    /* prevent buffer overflow when last input character is a backslash */
  553|      0|                    goto fail;
  554|      0|                }
  555|   353k|                skipped_bytes++;
  556|   353k|                input_end++;
  557|   353k|            }
  558|   120M|            input_end++;
  559|   120M|        }
  560|  1.93M|        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
  ------------------
  |  Branch (560:13): [True: 173, False: 1.93M]
  |  Branch (560:86): [True: 0, False: 1.93M]
  ------------------
  561|    173|            goto fail; /* string ended unexpectedly */
  562|    173|        }
  563|       |
  564|       |        /* This is at most how much we need for the output */
  565|  1.93M|        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
  ------------------
  |  |  195|  1.93M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  566|  1.93M|        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
  567|  1.93M|                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  568|  1.93M|        if (output == NULL) {
  ------------------
  |  Branch (568:13): [True: 0, False: 1.93M]
  ------------------
  569|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  570|      0|            goto fail; /* allocation failure */
  571|      0|        }
  572|  1.93M|    }
  573|       |
  574|  1.93M|    output_pointer = output;
  575|       |    /* loop through the string literal */
  576|  75.1M|    while (input_pointer < input_end) {
  ------------------
  |  Branch (576:12): [True: 73.2M, False: 1.93M]
  ------------------
  577|  73.2M|        if (*input_pointer != '\\') {
  ------------------
  |  Branch (577:13): [True: 73.1M, False: 97.9k]
  ------------------
  578|  73.1M|            *output_pointer++ = *input_pointer++;
  579|  73.1M|        }
  580|       |        /* escape sequence */
  581|  97.9k|        else {
  582|  97.9k|            unsigned char sequence_length = 2;
  583|  97.9k|            if ((input_end - input_pointer) < 1) {
  ------------------
  |  Branch (583:17): [True: 0, False: 97.9k]
  ------------------
  584|      0|                goto fail;
  585|      0|            }
  586|       |
  587|  97.9k|            switch (input_pointer[1]) {
  588|    534|                case 'b':
  ------------------
  |  Branch (588:17): [True: 534, False: 97.4k]
  ------------------
  589|    534|                    *output_pointer++ = '\b';
  590|    534|                    break;
  591|    313|                case 'f':
  ------------------
  |  Branch (591:17): [True: 313, False: 97.6k]
  ------------------
  592|    313|                    *output_pointer++ = '\f';
  593|    313|                    break;
  594|    871|                case 'n':
  ------------------
  |  Branch (594:17): [True: 871, False: 97.1k]
  ------------------
  595|    871|                    *output_pointer++ = '\n';
  596|    871|                    break;
  597|    849|                case 'r':
  ------------------
  |  Branch (597:17): [True: 849, False: 97.1k]
  ------------------
  598|    849|                    *output_pointer++ = '\r';
  599|    849|                    break;
  600|    657|                case 't':
  ------------------
  |  Branch (600:17): [True: 657, False: 97.3k]
  ------------------
  601|    657|                    *output_pointer++ = '\t';
  602|    657|                    break;
  603|    311|                case '\"':
  ------------------
  |  Branch (603:17): [True: 311, False: 97.6k]
  ------------------
  604|  8.51k|                case '\\':
  ------------------
  |  Branch (604:17): [True: 8.20k, False: 89.7k]
  ------------------
  605|  8.78k|                case '/':
  ------------------
  |  Branch (605:17): [True: 264, False: 97.7k]
  ------------------
  606|  8.78k|                    *output_pointer++ = input_pointer[1];
  607|  8.78k|                    break;
  608|       |
  609|       |                /* UTF-16 literal */
  610|  85.8k|                case 'u':
  ------------------
  |  Branch (610:17): [True: 85.8k, False: 12.1k]
  ------------------
  611|  85.8k|                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
  612|  85.8k|                    if (sequence_length == 0) {
  ------------------
  |  Branch (612:25): [True: 655, False: 85.1k]
  ------------------
  613|       |                        /* failed to convert UTF16-literal to UTF-8 */
  614|    655|                        goto fail;
  615|    655|                    }
  616|  85.1k|                    break;
  617|       |
  618|  85.1k|                default:
  ------------------
  |  Branch (618:17): [True: 166, False: 97.8k]
  ------------------
  619|    166|                    goto fail;
  620|  97.9k|            }
  621|  97.1k|            input_pointer += sequence_length;
  622|  97.1k|        }
  623|  73.2M|    }
  624|       |
  625|       |    /* zero terminate the output */
  626|  1.93M|    *output_pointer = '\0';
  627|       |
  628|  1.93M|    item->type = cJSON_String;
  ------------------
  |  |  101|  1.93M|#define cJSON_String (1 << 4)
  ------------------
  629|  1.93M|    item->valuestring = (char *)output;
  630|       |
  631|  1.93M|    input_buffer->offset = (size_t)(input_end - input_buffer->content);
  632|  1.93M|    input_buffer->offset++;
  633|       |
  634|  1.93M|    return true;
  ------------------
  |  |   67|  1.93M|#define true ((cJSON_bool)1)
  ------------------
  635|       |
  636|  1.27k|fail:
  637|  1.27k|    if (output != NULL) {
  ------------------
  |  Branch (637:9): [True: 821, False: 451]
  ------------------
  638|    821|        loader_free(input_buffer->pAllocator, output);
  639|    821|        output = NULL;
  640|    821|    }
  641|       |
  642|  1.27k|    if (input_pointer != NULL) {
  ------------------
  |  Branch (642:9): [True: 1.27k, False: 0]
  ------------------
  643|  1.27k|        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
  644|  1.27k|    }
  645|       |
  646|  1.27k|    return false;
  ------------------
  |  |   72|  1.27k|#define false ((cJSON_bool)0)
  ------------------
  647|  1.93M|}
cJSON.c:utf16_literal_to_utf8:
  435|  85.8k|                                           unsigned char **output_pointer) {
  436|  85.8k|    long unsigned int codepoint = 0;
  437|  85.8k|    unsigned int first_code = 0;
  438|  85.8k|    const unsigned char *first_sequence = input_pointer;
  439|  85.8k|    unsigned char utf8_length = 0;
  440|  85.8k|    unsigned char utf8_position = 0;
  441|  85.8k|    unsigned char sequence_length = 0;
  442|  85.8k|    unsigned char first_byte_mark = 0;
  443|       |
  444|  85.8k|    if ((input_end - first_sequence) < 6) {
  ------------------
  |  Branch (444:9): [True: 106, False: 85.7k]
  ------------------
  445|       |        /* input ends unexpectedly */
  446|    106|        goto fail;
  447|    106|    }
  448|       |
  449|       |    /* get the first utf16 sequence */
  450|  85.7k|    first_code = parse_hex4(first_sequence + 2);
  451|       |
  452|       |    /* check that the code is valid */
  453|  85.7k|    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
  ------------------
  |  Branch (453:10): [True: 27.4k, False: 58.2k]
  |  Branch (453:36): [True: 83, False: 27.3k]
  ------------------
  454|     83|        goto fail;
  455|     83|    }
  456|       |
  457|       |    /* UTF16 surrogate pair */
  458|  85.6k|    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
  ------------------
  |  Branch (458:9): [True: 32.5k, False: 53.0k]
  |  Branch (458:35): [True: 5.20k, False: 27.3k]
  ------------------
  459|  5.20k|        const unsigned char *second_sequence = first_sequence + 6;
  460|  5.20k|        unsigned int second_code = 0;
  461|  5.20k|        sequence_length = 12; /* \uXXXX\uXXXX */
  462|       |
  463|  5.20k|        if ((input_end - second_sequence) < 6) {
  ------------------
  |  Branch (463:13): [True: 56, False: 5.15k]
  ------------------
  464|       |            /* input ends unexpectedly */
  465|     56|            goto fail;
  466|     56|        }
  467|       |
  468|  5.15k|        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
  ------------------
  |  Branch (468:13): [True: 95, False: 5.05k]
  |  Branch (468:45): [True: 88, False: 4.97k]
  ------------------
  469|       |            /* missing second half of the surrogate pair */
  470|    183|            goto fail;
  471|    183|        }
  472|       |
  473|       |        /* get the second utf16 sequence */
  474|  4.97k|        second_code = parse_hex4(second_sequence + 2);
  475|       |        /* check that the code is valid */
  476|  4.97k|        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
  ------------------
  |  Branch (476:13): [True: 115, False: 4.85k]
  |  Branch (476:39): [True: 112, False: 4.74k]
  ------------------
  477|       |            /* invalid second half of the surrogate pair */
  478|    227|            goto fail;
  479|    227|        }
  480|       |
  481|       |        /* calculate the unicode codepoint from the surrogate pair */
  482|  4.74k|        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
  483|  80.4k|    } else {
  484|  80.4k|        sequence_length = 6; /* \uXXXX */
  485|  80.4k|        codepoint = first_code;
  486|  80.4k|    }
  487|       |
  488|       |    /* encode as UTF-8
  489|       |     * takes at maximum 4 bytes to encode:
  490|       |     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
  491|  85.1k|    if (codepoint < 0x80) {
  ------------------
  |  Branch (491:9): [True: 48.6k, False: 36.5k]
  ------------------
  492|       |        /* normal ascii, encoding 0xxxxxxx */
  493|  48.6k|        utf8_length = 1;
  494|  48.6k|    } else if (codepoint < 0x800) {
  ------------------
  |  Branch (494:16): [True: 1.72k, False: 34.8k]
  ------------------
  495|       |        /* two bytes, encoding 110xxxxx 10xxxxxx */
  496|  1.72k|        utf8_length = 2;
  497|  1.72k|        first_byte_mark = 0xC0; /* 11000000 */
  498|  34.8k|    } else if (codepoint < 0x10000) {
  ------------------
  |  Branch (498:16): [True: 30.0k, False: 4.74k]
  ------------------
  499|       |        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
  500|  30.0k|        utf8_length = 3;
  501|  30.0k|        first_byte_mark = 0xE0; /* 11100000 */
  502|  30.0k|    } else if (codepoint <= 0x10FFFF) {
  ------------------
  |  Branch (502:16): [True: 4.74k, False: 0]
  ------------------
  503|       |        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
  504|  4.74k|        utf8_length = 4;
  505|  4.74k|        first_byte_mark = 0xF0; /* 11110000 */
  506|  4.74k|    } else {
  507|       |        /* invalid unicode codepoint */
  508|      0|        goto fail;
  509|      0|    }
  510|       |
  511|       |    /* encode as utf8 */
  512|   161k|    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
  ------------------
  |  Branch (512:60): [True: 76.1k, False: 85.1k]
  ------------------
  513|       |        /* 10xxxxxx */
  514|  76.1k|        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
  515|  76.1k|        codepoint >>= 6;
  516|  76.1k|    }
  517|       |    /* encode first byte */
  518|  85.1k|    if (utf8_length > 1) {
  ------------------
  |  Branch (518:9): [True: 36.5k, False: 48.6k]
  ------------------
  519|  36.5k|        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
  520|  48.6k|    } else {
  521|  48.6k|        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
  522|  48.6k|    }
  523|       |
  524|  85.1k|    *output_pointer += utf8_length;
  525|       |
  526|  85.1k|    return sequence_length;
  527|       |
  528|    655|fail:
  529|    655|    return 0;
  530|  85.1k|}
cJSON.c:parse_hex4:
  406|  90.6k|static unsigned parse_hex4(const unsigned char *const input) {
  407|  90.6k|    unsigned int h = 0;
  408|  90.6k|    size_t i = 0;
  409|       |
  410|   312k|    for (i = 0; i < 4; i++) {
  ------------------
  |  Branch (410:17): [True: 270k, False: 42.0k]
  ------------------
  411|       |        /* parse digit */
  412|   270k|        if ((input[i] >= '0') && (input[i] <= '9')) {
  ------------------
  |  Branch (412:13): [True: 257k, False: 13.2k]
  |  Branch (412:34): [True: 78.0k, False: 178k]
  ------------------
  413|  78.0k|            h += (unsigned int)input[i] - '0';
  414|   192k|        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
  ------------------
  |  Branch (414:20): [True: 167k, False: 24.2k]
  |  Branch (414:41): [True: 92.1k, False: 75.8k]
  ------------------
  415|  92.1k|            h += (unsigned int)10 + input[i] - 'A';
  416|   100k|        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
  ------------------
  |  Branch (416:20): [True: 71.3k, False: 28.7k]
  |  Branch (416:41): [True: 51.4k, False: 19.9k]
  ------------------
  417|  51.4k|            h += (unsigned int)10 + input[i] - 'a';
  418|  51.4k|        } else /* invalid */
  419|  48.6k|        {
  420|  48.6k|            return 0;
  421|  48.6k|        }
  422|       |
  423|   221k|        if (i < 3) {
  ------------------
  |  Branch (423:13): [True: 179k, False: 42.0k]
  ------------------
  424|       |            /* shift left to make place for the next nibble */
  425|   179k|            h = h << 4;
  426|   179k|        }
  427|   221k|    }
  428|       |
  429|  42.0k|    return h;
  430|  90.6k|}
cJSON.c:parse_number:
  198|   565k|static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
  199|   565k|    double number = 0;
  200|   565k|    unsigned char *after_end = NULL;
  201|   565k|    unsigned char number_c_string[64];
  202|   565k|    unsigned char decimal_point = get_decimal_point();
  203|   565k|    size_t i = 0;
  204|       |
  205|   565k|    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
  ------------------
  |  Branch (205:9): [True: 0, False: 565k]
  |  Branch (205:35): [True: 0, False: 565k]
  ------------------
  206|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  207|      0|    }
  208|       |
  209|       |    /* copy the number into a temporary buffer and replace '.' with the decimal point
  210|       |     * of the current locale (for strtod)
  211|       |     * This also takes care of '\0' not necessarily being available for marking the end of the input */
  212|  2.64M|    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
  ------------------
  |  |  192|  2.64M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 2.64M, False: 0]
  |  |  |  Branch (192:65): [True: 2.64M, False: 0]
  |  |  ------------------
  ------------------
  |  Branch (212:17): [True: 2.64M, False: 322]
  ------------------
  213|  2.64M|        switch (buffer_at_offset(input_buffer)[i]) {
  ------------------
  |  |  195|  2.64M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  214|  71.6k|            case '0':
  ------------------
  |  Branch (214:13): [True: 71.6k, False: 2.57M]
  ------------------
  215|   213k|            case '1':
  ------------------
  |  Branch (215:13): [True: 141k, False: 2.50M]
  ------------------
  216|   291k|            case '2':
  ------------------
  |  Branch (216:13): [True: 78.2k, False: 2.56M]
  ------------------
  217|   446k|            case '3':
  ------------------
  |  Branch (217:13): [True: 155k, False: 2.48M]
  ------------------
  218|   488k|            case '4':
  ------------------
  |  Branch (218:13): [True: 42.0k, False: 2.60M]
  ------------------
  219|   762k|            case '5':
  ------------------
  |  Branch (219:13): [True: 274k, False: 2.37M]
  ------------------
  220|   818k|            case '6':
  ------------------
  |  Branch (220:13): [True: 55.4k, False: 2.58M]
  ------------------
  221|  1.51M|            case '7':
  ------------------
  |  Branch (221:13): [True: 694k, False: 1.95M]
  ------------------
  222|  1.86M|            case '8':
  ------------------
  |  Branch (222:13): [True: 348k, False: 2.29M]
  ------------------
  223|  2.01M|            case '9':
  ------------------
  |  Branch (223:13): [True: 149k, False: 2.49M]
  ------------------
  224|  2.01M|            case '+':
  ------------------
  |  Branch (224:13): [True: 1.50k, False: 2.64M]
  ------------------
  225|  2.03M|            case '-':
  ------------------
  |  Branch (225:13): [True: 27.3k, False: 2.61M]
  ------------------
  226|  2.04M|            case 'e':
  ------------------
  |  Branch (226:13): [True: 6.32k, False: 2.63M]
  ------------------
  227|  2.04M|            case 'E':
  ------------------
  |  Branch (227:13): [True: 1.72k, False: 2.64M]
  ------------------
  228|  2.04M|                number_c_string[i] = buffer_at_offset(input_buffer)[i];
  ------------------
  |  |  195|  2.04M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  229|  2.04M|                break;
  230|       |
  231|  31.4k|            case '.':
  ------------------
  |  Branch (231:13): [True: 31.4k, False: 2.61M]
  ------------------
  232|  31.4k|                number_c_string[i] = decimal_point;
  233|  31.4k|                break;
  234|       |
  235|   565k|            default:
  ------------------
  |  Branch (235:13): [True: 565k, False: 2.07M]
  ------------------
  236|   565k|                goto loop_end;
  237|  2.64M|        }
  238|  2.64M|    }
  239|   565k|loop_end:
  240|   565k|    number_c_string[i] = '\0';
  241|       |
  242|   565k|    number = strtod((const char *)number_c_string, (char **)&after_end);
  243|   565k|    if (number_c_string == after_end) {
  ------------------
  |  Branch (243:9): [True: 146, False: 565k]
  ------------------
  244|    146|        return false; /* parse_error */
  ------------------
  |  |   72|    146|#define false ((cJSON_bool)0)
  ------------------
  245|    146|    }
  246|       |
  247|   565k|    item->valuedouble = number;
  248|       |
  249|       |    /* use saturation in case of overflow */
  250|   565k|    if (number >= INT_MAX) {
  ------------------
  |  Branch (250:9): [True: 10.5k, False: 554k]
  ------------------
  251|  10.5k|        item->valueint = INT_MAX;
  252|   554k|    } else if (number <= (double)INT_MIN) {
  ------------------
  |  Branch (252:16): [True: 18.4k, False: 536k]
  ------------------
  253|  18.4k|        item->valueint = INT_MIN;
  254|   536k|    } else {
  255|   536k|        item->valueint = (int)number;
  256|   536k|    }
  257|       |
  258|   565k|    item->type = cJSON_Number;
  ------------------
  |  |  100|   565k|#define cJSON_Number (1 << 3)
  ------------------
  259|       |
  260|   565k|    input_buffer->offset += (size_t)(after_end - number_c_string);
  261|   565k|    return true;
  ------------------
  |  |   67|   565k|#define true ((cJSON_bool)1)
  ------------------
  262|   565k|}
cJSON.c:get_decimal_point:
  172|   565k|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|   565k|    return '.';
  178|   565k|#endif
  179|   565k|}
cJSON.c:parse_array:
 1118|   158k|static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1119|   158k|    cJSON *head = NULL; /* head of the linked list */
 1120|   158k|    cJSON *current_item = NULL;
 1121|       |
 1122|   158k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   158k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1122:9): [True: 40, False: 158k]
  ------------------
 1123|     40|        return false; /* to deeply nested */
  ------------------
  |  |   72|     40|#define false ((cJSON_bool)0)
  ------------------
 1124|     40|    }
 1125|   158k|    input_buffer->depth++;
 1126|       |
 1127|   158k|    if (buffer_at_offset(input_buffer)[0] != '[') {
  ------------------
  |  |  195|   158k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1127:9): [True: 0, False: 158k]
  ------------------
 1128|       |        /* not an array */
 1129|      0|        goto fail;
 1130|      0|    }
 1131|       |
 1132|   158k|    input_buffer->offset++;
 1133|   158k|    buffer_skip_whitespace(input_buffer);
 1134|   158k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  192|   317k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 158k, False: 0]
  |  |  |  Branch (192:65): [True: 158k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
  ------------------
  |  |  195|   158k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1134:49): [True: 6.30k, False: 152k]
  ------------------
 1135|       |        /* empty array */
 1136|  6.30k|        goto success;
 1137|  6.30k|    }
 1138|       |
 1139|       |    /* check if we skipped to the end of the buffer */
 1140|   152k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   152k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   152k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 152k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 152k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1141|      0|        input_buffer->offset--;
 1142|      0|        goto fail;
 1143|      0|    }
 1144|       |
 1145|       |    /* step back to character in front of the first element */
 1146|   152k|    input_buffer->offset--;
 1147|       |    /* loop through the comma separated array elements */
 1148|  1.17M|    do {
 1149|       |        /* allocate next item */
 1150|  1.17M|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1151|  1.17M|        if (new_item == NULL) {
  ------------------
  |  Branch (1151:13): [True: 0, False: 1.17M]
  ------------------
 1152|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1153|      0|            goto fail; /* allocation failure */
 1154|      0|        }
 1155|       |
 1156|       |        /* attach next item to list */
 1157|  1.17M|        if (head == NULL) {
  ------------------
  |  Branch (1157:13): [True: 152k, False: 1.02M]
  ------------------
 1158|       |            /* start the linked list */
 1159|   152k|            current_item = head = new_item;
 1160|  1.02M|        } else {
 1161|       |            /* add to the end and advance */
 1162|  1.02M|            current_item->next = new_item;
 1163|  1.02M|            new_item->prev = current_item;
 1164|  1.02M|            current_item = new_item;
 1165|  1.02M|        }
 1166|       |
 1167|       |        /* parse next value */
 1168|  1.17M|        input_buffer->offset++;
 1169|  1.17M|        buffer_skip_whitespace(input_buffer);
 1170|  1.17M|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1170:13): [True: 100k, False: 1.07M]
  ------------------
 1171|   100k|            goto fail; /* failed to parse value */
 1172|   100k|        }
 1173|  1.07M|        buffer_skip_whitespace(input_buffer);
 1174|  1.07M|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  2.15M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 1.07M, False: 0]
  |  |  |  Branch (192:65): [True: 1.07M, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|  1.07M|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1174:54): [True: 1.02M, False: 51.8k]
  ------------------
 1175|       |
 1176|  51.8k|    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  193|   103k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|  51.8k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 51.8k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 51.8k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
  ------------------
  |  |  195|  51.8k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1176:52): [True: 280, False: 51.5k]
  ------------------
 1177|    280|        goto fail; /* expected end of array */
 1178|    280|    }
 1179|       |
 1180|  57.8k|success:
 1181|  57.8k|    input_buffer->depth--;
 1182|       |
 1183|  57.8k|    if (head != NULL) {
  ------------------
  |  Branch (1183:9): [True: 51.5k, False: 6.30k]
  ------------------
 1184|  51.5k|        head->prev = current_item;
 1185|  51.5k|    }
 1186|       |
 1187|  57.8k|    item->type = cJSON_Array;
  ------------------
  |  |  102|  57.8k|#define cJSON_Array (1 << 5)
  ------------------
 1188|  57.8k|    item->child = head;
 1189|       |
 1190|  57.8k|    input_buffer->offset++;
 1191|       |
 1192|  57.8k|    return true;
  ------------------
  |  |   67|  57.8k|#define true ((cJSON_bool)1)
  ------------------
 1193|       |
 1194|   100k|fail:
 1195|   100k|    if (head != NULL) {
  ------------------
  |  Branch (1195:9): [True: 100k, False: 0]
  ------------------
 1196|   100k|        loader_cJSON_Delete(head);
 1197|   100k|    }
 1198|       |
 1199|   100k|    return false;
  ------------------
  |  |   72|   100k|#define false ((cJSON_bool)0)
  ------------------
 1200|  51.8k|}
cJSON.c:parse_object:
 1256|   423k|static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
 1257|   423k|    cJSON *head = NULL; /* linked list head */
 1258|   423k|    cJSON *current_item = NULL;
 1259|       |
 1260|   423k|    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
  ------------------
  |  |  138|   423k|#define CJSON_NESTING_LIMIT 1000
  ------------------
  |  Branch (1260:9): [True: 24, False: 423k]
  ------------------
 1261|     24|        return false; /* to deeply nested */
  ------------------
  |  |   72|     24|#define false ((cJSON_bool)0)
  ------------------
 1262|     24|    }
 1263|   423k|    input_buffer->depth++;
 1264|       |
 1265|   423k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  193|   847k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   423k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 423k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 423k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
  ------------------
  |  |  195|   423k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1265:52): [True: 0, False: 423k]
  ------------------
 1266|      0|        goto fail; /* not an object */
 1267|      0|    }
 1268|       |
 1269|   423k|    input_buffer->offset++;
 1270|   423k|    buffer_skip_whitespace(input_buffer);
 1271|   423k|    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  192|   847k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 423k, False: 0]
  |  |  |  Branch (192:65): [True: 423k, False: 0]
  |  |  ------------------
  ------------------
                  if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
  ------------------
  |  |  195|   423k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1271:49): [True: 29.2k, False: 394k]
  ------------------
 1272|  29.2k|        goto success; /* empty object */
 1273|  29.2k|    }
 1274|       |
 1275|       |    /* check if we skipped to the end of the buffer */
 1276|   394k|    if (cannot_access_at_index(input_buffer, 0)) {
  ------------------
  |  |  193|   394k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   394k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 394k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 394k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1277|      0|        input_buffer->offset--;
 1278|      0|        goto fail;
 1279|      0|    }
 1280|       |
 1281|       |    /* step back to character in front of the first element */
 1282|   394k|    input_buffer->offset--;
 1283|       |    /* loop through the comma separated array elements */
 1284|   979k|    do {
 1285|       |        /* allocate next item */
 1286|   979k|        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
 1287|   979k|        if (new_item == NULL) {
  ------------------
  |  Branch (1287:13): [True: 0, False: 979k]
  ------------------
 1288|      0|            *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1289|      0|            goto fail; /* allocation failure */
 1290|      0|        }
 1291|       |
 1292|       |        /* attach next item to list */
 1293|   979k|        if (head == NULL) {
  ------------------
  |  Branch (1293:13): [True: 394k, False: 584k]
  ------------------
 1294|       |            /* start the linked list */
 1295|   394k|            current_item = head = new_item;
 1296|   584k|        } else {
 1297|       |            /* add to the end and advance */
 1298|   584k|            current_item->next = new_item;
 1299|   584k|            new_item->prev = current_item;
 1300|   584k|            current_item = new_item;
 1301|   584k|        }
 1302|       |
 1303|   979k|        if (cannot_access_at_index(input_buffer, 1)) {
  ------------------
  |  |  193|   979k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   979k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 979k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 979k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1304|      0|            goto fail; /* nothing comes after the comma */
 1305|      0|        }
 1306|       |
 1307|       |        /* parse the name of the child */
 1308|   979k|        input_buffer->offset++;
 1309|   979k|        buffer_skip_whitespace(input_buffer);
 1310|   979k|        if (!parse_string(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1310:13): [True: 515, False: 978k]
  ------------------
 1311|    515|            goto fail; /* failed to parse name */
 1312|    515|        }
 1313|   978k|        buffer_skip_whitespace(input_buffer);
 1314|       |
 1315|       |        /* swap valuestring and string, because we parsed the name */
 1316|   978k|        current_item->string = current_item->valuestring;
 1317|   978k|        current_item->valuestring = NULL;
 1318|       |
 1319|   978k|        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  193|  1.95M|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   978k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 978k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 978k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                      if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
  ------------------
  |  |  195|   978k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1319:56): [True: 86, False: 978k]
  ------------------
 1320|     86|            goto fail; /* invalid object */
 1321|     86|        }
 1322|       |
 1323|       |        /* parse the value */
 1324|   978k|        input_buffer->offset++;
 1325|   978k|        buffer_skip_whitespace(input_buffer);
 1326|   978k|        if (!parse_value(current_item, input_buffer, out_of_memory)) {
  ------------------
  |  Branch (1326:13): [True: 889, False: 977k]
  ------------------
 1327|    889|            goto fail; /* failed to parse value */
 1328|    889|        }
 1329|   977k|        buffer_skip_whitespace(input_buffer);
 1330|   977k|    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  192|  1.95M|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  ------------------
  |  |  |  Branch (192:45): [True: 977k, False: 0]
  |  |  |  Branch (192:65): [True: 977k, False: 0]
  |  |  ------------------
  ------------------
                  } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
  ------------------
  |  |  195|   977k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1330:54): [True: 584k, False: 392k]
  ------------------
 1331|       |
 1332|   392k|    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  193|   785k|#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
  |  |  ------------------
  |  |  |  |  192|   392k|#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (192:45): [True: 392k, False: 0]
  |  |  |  |  |  Branch (192:65): [True: 392k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
                  if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
  ------------------
  |  |  195|   392k|#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
  ------------------
  |  Branch (1332:52): [True: 111, False: 392k]
  ------------------
 1333|    111|        goto fail; /* expected end of object */
 1334|    111|    }
 1335|       |
 1336|   422k|success:
 1337|   422k|    input_buffer->depth--;
 1338|       |
 1339|   422k|    if (head != NULL) {
  ------------------
  |  Branch (1339:9): [True: 392k, False: 29.2k]
  ------------------
 1340|   392k|        head->prev = current_item;
 1341|   392k|    }
 1342|       |
 1343|   422k|    item->type = cJSON_Object;
  ------------------
  |  |  103|   422k|#define cJSON_Object (1 << 6)
  ------------------
 1344|   422k|    item->child = head;
 1345|       |
 1346|   422k|    input_buffer->offset++;
 1347|   422k|    return true;
  ------------------
  |  |   67|   422k|#define true ((cJSON_bool)1)
  ------------------
 1348|       |
 1349|  1.60k|fail:
 1350|  1.60k|    if (head != NULL) {
  ------------------
  |  Branch (1350:9): [True: 1.60k, False: 0]
  ------------------
 1351|  1.60k|        loader_cJSON_Delete(head);
 1352|  1.60k|    }
 1353|       |
 1354|  1.60k|    return false;
  ------------------
  |  |   72|  1.60k|#define false ((cJSON_bool)0)
  ------------------
 1355|   392k|}
cJSON.c:print_value:
 1053|   427k|static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
 1054|   427k|    unsigned char *output = NULL;
 1055|       |
 1056|   427k|    if ((item == NULL) || (output_buffer == NULL)) {
  ------------------
  |  Branch (1056:9): [True: 0, False: 427k]
  |  Branch (1056:27): [True: 0, False: 427k]
  ------------------
 1057|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1058|      0|    }
 1059|       |
 1060|   427k|    switch ((item->type) & 0xFF) {
 1061|      0|        case cJSON_NULL:
  ------------------
  |  |   99|      0|#define cJSON_NULL (1 << 2)
  ------------------
  |  Branch (1061:9): [True: 0, False: 427k]
  ------------------
 1062|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1063|      0|            if (output == NULL) {
  ------------------
  |  Branch (1063:17): [True: 0, False: 0]
  ------------------
 1064|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1065|      0|            }
 1066|      0|            strcpy((char *)output, "null");
 1067|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1068|       |
 1069|      0|        case cJSON_False:
  ------------------
  |  |   97|      0|#define cJSON_False (1 << 0)
  ------------------
  |  Branch (1069:9): [True: 0, False: 427k]
  ------------------
 1070|      0|            output = ensure(output_buffer, 6, out_of_memory);
 1071|      0|            if (output == NULL) {
  ------------------
  |  Branch (1071:17): [True: 0, False: 0]
  ------------------
 1072|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1073|      0|            }
 1074|      0|            strcpy((char *)output, "false");
 1075|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1076|       |
 1077|      0|        case cJSON_True:
  ------------------
  |  |   98|      0|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (1077:9): [True: 0, False: 427k]
  ------------------
 1078|      0|            output = ensure(output_buffer, 5, out_of_memory);
 1079|      0|            if (output == NULL) {
  ------------------
  |  Branch (1079:17): [True: 0, False: 0]
  ------------------
 1080|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1081|      0|            }
 1082|      0|            strcpy((char *)output, "true");
 1083|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1084|       |
 1085|      0|        case cJSON_Number:
  ------------------
  |  |  100|      0|#define cJSON_Number (1 << 3)
  ------------------
  |  Branch (1085:9): [True: 0, False: 427k]
  ------------------
 1086|      0|            return print_number(item, output_buffer, out_of_memory);
 1087|       |
 1088|      0|        case cJSON_Raw: {
  ------------------
  |  |  104|      0|#define cJSON_Raw (1 << 7) /* raw json */
  ------------------
  |  Branch (1088:9): [True: 0, False: 427k]
  ------------------
 1089|      0|            size_t raw_length = 0;
 1090|      0|            if (item->valuestring == NULL) {
  ------------------
  |  Branch (1090:17): [True: 0, False: 0]
  ------------------
 1091|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1092|      0|            }
 1093|       |
 1094|      0|            raw_length = strlen(item->valuestring) + sizeof("");
 1095|      0|            output = ensure(output_buffer, raw_length, out_of_memory);
 1096|      0|            if (output == NULL) {
  ------------------
  |  Branch (1096:17): [True: 0, False: 0]
  ------------------
 1097|      0|                return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1098|      0|            }
 1099|      0|            memcpy(output, item->valuestring, raw_length);
 1100|      0|            return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
 1101|      0|        }
 1102|       |
 1103|   427k|        case cJSON_String:
  ------------------
  |  |  101|   427k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (1103:9): [True: 427k, False: 0]
  ------------------
 1104|   427k|            return print_string(item, output_buffer, out_of_memory);
 1105|       |
 1106|      0|        case cJSON_Array:
  ------------------
  |  |  102|      0|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (1106:9): [True: 0, False: 427k]
  ------------------
 1107|      0|            return print_array(item, output_buffer, out_of_memory);
 1108|       |
 1109|      0|        case cJSON_Object:
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (1109:9): [True: 0, False: 427k]
  ------------------
 1110|      0|            return print_object(item, output_buffer, out_of_memory);
 1111|       |
 1112|      0|        default:
  ------------------
  |  Branch (1112:9): [True: 0, False: 427k]
  ------------------
 1113|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
 1114|   427k|    }
 1115|   427k|}
cJSON.c:ensure:
  275|   427k|static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
  276|   427k|    unsigned char *newbuffer = NULL;
  277|   427k|    size_t newsize = 0;
  278|       |
  279|   427k|    if ((p == NULL) || (p->buffer == NULL)) {
  ------------------
  |  Branch (279:9): [True: 0, False: 427k]
  |  Branch (279:24): [True: 0, False: 427k]
  ------------------
  280|      0|        return NULL;
  281|      0|    }
  282|       |
  283|   427k|    if ((p->length > 0) && (p->offset >= p->length)) {
  ------------------
  |  Branch (283:9): [True: 427k, False: 0]
  |  Branch (283:28): [True: 0, False: 427k]
  ------------------
  284|       |        /* make sure that offset is valid */
  285|      0|        return NULL;
  286|      0|    }
  287|       |
  288|   427k|    if (needed > INT_MAX) {
  ------------------
  |  Branch (288:9): [True: 0, False: 427k]
  ------------------
  289|       |        /* sizes bigger than INT_MAX are currently not supported */
  290|      0|        return NULL;
  291|      0|    }
  292|       |
  293|   427k|    needed += p->offset + 1;
  294|   427k|    if (needed <= p->length) {
  ------------------
  |  Branch (294:9): [True: 425k, False: 2.08k]
  ------------------
  295|   425k|        return p->buffer + p->offset;
  296|   425k|    }
  297|       |
  298|  2.08k|    if (p->noalloc) {
  ------------------
  |  Branch (298:9): [True: 1.26k, False: 824]
  ------------------
  299|  1.26k|        return NULL;
  300|  1.26k|    }
  301|       |
  302|       |    /* calculate new buffer size */
  303|    824|    if (needed > (INT_MAX / 2)) {
  ------------------
  |  Branch (303:9): [True: 0, False: 824]
  ------------------
  304|       |        /* overflow of int, use INT_MAX if possible */
  305|      0|        if (needed <= INT_MAX) {
  ------------------
  |  Branch (305:13): [True: 0, False: 0]
  ------------------
  306|      0|            newsize = INT_MAX;
  307|      0|        } else {
  308|      0|            return NULL;
  309|      0|        }
  310|    824|    } else {
  311|    824|        newsize = needed * 2;
  312|    824|    }
  313|       |
  314|    824|    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  315|    824|    if (newbuffer == NULL) {
  ------------------
  |  Branch (315:9): [True: 0, False: 824]
  ------------------
  316|      0|        *out_of_memory = true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  317|      0|        loader_free(p->pAllocator, p->buffer);
  318|      0|        p->length = 0;
  319|      0|        p->buffer = NULL;
  320|       |
  321|      0|        return NULL;
  322|      0|    }
  323|       |
  324|    824|    p->length = newsize;
  325|    824|    p->buffer = newbuffer;
  326|       |
  327|    824|    return newbuffer + p->offset;
  328|    824|}
cJSON.c:print_string:
  756|   427k|static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
  757|   427k|    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
  758|   427k|}
cJSON.c:print_string_ptr:
  650|   427k|static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
  651|   427k|    const unsigned char *input_pointer = NULL;
  652|   427k|    unsigned char *output = NULL;
  653|   427k|    unsigned char *output_pointer = NULL;
  654|   427k|    size_t output_length = 0;
  655|       |    /* numbers of additional characters needed for escaping */
  656|   427k|    size_t escape_characters = 0;
  657|       |
  658|   427k|    if (output_buffer == NULL) {
  ------------------
  |  Branch (658:9): [True: 0, False: 427k]
  ------------------
  659|      0|        return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  660|      0|    }
  661|       |
  662|       |    /* empty string */
  663|   427k|    if (input == NULL) {
  ------------------
  |  Branch (663:9): [True: 0, False: 427k]
  ------------------
  664|      0|        output = ensure(output_buffer, sizeof(""), out_of_memory);
  665|      0|        if (output == NULL) {
  ------------------
  |  Branch (665:13): [True: 0, False: 0]
  ------------------
  666|      0|            return false;
  ------------------
  |  |   72|      0|#define false ((cJSON_bool)0)
  ------------------
  667|      0|        }
  668|       |
  669|      0|        return true;
  ------------------
  |  |   67|      0|#define true ((cJSON_bool)1)
  ------------------
  670|      0|    }
  671|       |
  672|       |    /* set "flag" to 1 if something needs to be escaped */
  673|  34.8M|    for (input_pointer = input; *input_pointer; input_pointer++) {
  ------------------
  |  Branch (673:33): [True: 34.3M, False: 427k]
  ------------------
  674|  34.3M|        switch (*input_pointer) {
  675|     68|            case '\"':
  ------------------
  |  Branch (675:13): [True: 68, False: 34.3M]
  ------------------
  676|  4.91k|            case '\\':
  ------------------
  |  Branch (676:13): [True: 4.84k, False: 34.3M]
  ------------------
  677|  7.77k|            case '\b':
  ------------------
  |  Branch (677:13): [True: 2.86k, False: 34.3M]
  ------------------
  678|  14.5k|            case '\f':
  ------------------
  |  Branch (678:13): [True: 6.78k, False: 34.3M]
  ------------------
  679|  26.4k|            case '\n':
  ------------------
  |  Branch (679:13): [True: 11.8k, False: 34.3M]
  ------------------
  680|  45.9k|            case '\r':
  ------------------
  |  Branch (680:13): [True: 19.4k, False: 34.3M]
  ------------------
  681|  48.9k|            case '\t':
  ------------------
  |  Branch (681:13): [True: 3.01k, False: 34.3M]
  ------------------
  682|       |                /* one character escape sequence */
  683|  48.9k|                escape_characters++;
  684|  48.9k|                break;
  685|  34.3M|            default:
  ------------------
  |  Branch (685:13): [True: 34.3M, False: 48.9k]
  ------------------
  686|  34.3M|                if (*input_pointer < 32) {
  ------------------
  |  Branch (686:21): [True: 28.1M, False: 6.21M]
  ------------------
  687|       |                    /* UTF-16 escape sequence uXXXX */
  688|  28.1M|                    escape_characters += 5;
  689|  28.1M|                }
  690|  34.3M|                break;
  691|  34.3M|        }
  692|  34.3M|    }
  693|   427k|    output_length = (size_t)(input_pointer - input) + escape_characters;
  694|       |
  695|   427k|    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
  696|   427k|    if (output == NULL) {
  ------------------
  |  Branch (696:9): [True: 1.26k, False: 426k]
  ------------------
  697|  1.26k|        return false;
  ------------------
  |  |   72|  1.26k|#define false ((cJSON_bool)0)
  ------------------
  698|  1.26k|    }
  699|       |
  700|       |    /* no characters have to be escaped */
  701|   426k|    if (escape_characters == 0) {
  ------------------
  |  Branch (701:9): [True: 381k, False: 44.6k]
  ------------------
  702|   381k|        memcpy(output, input, output_length);
  703|   381k|        output[output_length] = '\0';
  704|       |
  705|   381k|        return true;
  ------------------
  |  |   67|   381k|#define true ((cJSON_bool)1)
  ------------------
  706|   381k|    }
  707|       |
  708|  44.6k|    output_pointer = output;
  709|       |    /* copy the string */
  710|  28.7M|    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
  ------------------
  |  Branch (710:33): [True: 28.7M, False: 44.6k]
  ------------------
  711|  28.7M|        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
  ------------------
  |  Branch (711:13): [True: 2.65M, False: 26.0M]
  |  Branch (711:38): [True: 2.65M, False: 68]
  |  Branch (711:66): [True: 2.65M, False: 4.84k]
  ------------------
  712|       |            /* normal character, copy */
  713|  2.65M|            *output_pointer = *input_pointer;
  714|  26.0M|        } else {
  715|       |            // Loader specific modification - don't add a backslash because that will 'double up' any existing back slashes.
  716|       |            // This change was added right after vulkan's public release, so while it may not be a problem, there are plenty
  717|       |            // of API calls made which might not work if the paths have "\\"" in them
  718|       |            /* character needs to be escaped */
  719|       |            //*output_pointer++ = '\\';
  720|  26.0M|            switch (*input_pointer) {
  721|  4.84k|                case '\\':
  ------------------
  |  Branch (721:17): [True: 4.84k, False: 26.0M]
  ------------------
  722|  4.84k|                    *output_pointer = '\\';
  723|  4.84k|                    break;
  724|     68|                case '\"':
  ------------------
  |  Branch (724:17): [True: 68, False: 26.0M]
  ------------------
  725|     68|                    *output_pointer = '\"';
  726|     68|                    break;
  727|  2.86k|                case '\b':
  ------------------
  |  Branch (727:17): [True: 2.86k, False: 26.0M]
  ------------------
  728|  2.86k|                    *output_pointer = '\b';
  729|  2.86k|                    break;
  730|  6.78k|                case '\f':
  ------------------
  |  Branch (730:17): [True: 6.78k, False: 26.0M]
  ------------------
  731|  6.78k|                    *output_pointer = '\f';
  732|  6.78k|                    break;
  733|  10.4k|                case '\n':
  ------------------
  |  Branch (733:17): [True: 10.4k, False: 26.0M]
  ------------------
  734|  10.4k|                    *output_pointer = '\n';
  735|  10.4k|                    break;
  736|  19.4k|                case '\r':
  ------------------
  |  Branch (736:17): [True: 19.4k, False: 26.0M]
  ------------------
  737|  19.4k|                    *output_pointer = '\r';
  738|  19.4k|                    break;
  739|  2.79k|                case '\t':
  ------------------
  |  Branch (739:17): [True: 2.79k, False: 26.0M]
  ------------------
  740|  2.79k|                    *output_pointer = '\t';
  741|  2.79k|                    break;
  742|  26.0M|                default:
  ------------------
  |  Branch (742:17): [True: 26.0M, False: 47.2k]
  ------------------
  743|       |                    /* escape and print as unicode codepoint */
  744|  26.0M|                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
  745|  26.0M|                    output_pointer += 4;
  746|  26.0M|                    break;
  747|  26.0M|            }
  748|  26.0M|        }
  749|  28.7M|    }
  750|  44.6k|    output[output_length] = '\0';
  751|       |
  752|  44.6k|    return true;
  ------------------
  |  |   67|  44.6k|#define true ((cJSON_bool)1)
  ------------------
  753|  44.6k|}
cJSON.c:get_object_item:
 1498|  1.12M|static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
 1499|  1.12M|    cJSON *current_element = NULL;
 1500|       |
 1501|  1.12M|    if ((object == NULL) || (name == NULL)) {
  ------------------
  |  Branch (1501:9): [True: 0, False: 1.12M]
  |  Branch (1501:29): [True: 0, False: 1.12M]
  ------------------
 1502|      0|        return NULL;
 1503|      0|    }
 1504|       |
 1505|  1.12M|    current_element = object->child;
 1506|  1.12M|    if (case_sensitive) {
  ------------------
  |  Branch (1506:9): [True: 0, False: 1.12M]
  ------------------
 1507|      0|        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
  ------------------
  |  Branch (1507:16): [True: 0, False: 0]
  |  Branch (1507:45): [True: 0, False: 0]
  |  Branch (1507:82): [True: 0, False: 0]
  ------------------
 1508|      0|            current_element = current_element->next;
 1509|      0|        }
 1510|  1.12M|    } else {
 1511|  3.63M|        while ((current_element != NULL) &&
  ------------------
  |  Branch (1511:16): [True: 3.19M, False: 442k]
  ------------------
 1512|  3.19M|               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
  ------------------
  |  Branch (1512:16): [True: 2.51M, False: 680k]
  ------------------
 1513|  2.51M|            current_element = current_element->next;
 1514|  2.51M|        }
 1515|  1.12M|    }
 1516|       |
 1517|  1.12M|    if ((current_element == NULL) || (current_element->string == NULL)) {
  ------------------
  |  Branch (1517:9): [True: 442k, False: 680k]
  |  Branch (1517:38): [True: 0, False: 680k]
  ------------------
 1518|   442k|        return NULL;
 1519|   442k|    }
 1520|       |
 1521|   680k|    return current_element;
 1522|  1.12M|}
cJSON.c:case_insensitive_strcmp:
  120|  3.19M|static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
  121|  3.19M|    if ((string1 == NULL) || (string2 == NULL)) {
  ------------------
  |  Branch (121:9): [True: 0, False: 3.19M]
  |  Branch (121:30): [True: 242, False: 3.19M]
  ------------------
  122|    242|        return 1;
  123|    242|    }
  124|       |
  125|  3.19M|    if (string1 == string2) {
  ------------------
  |  Branch (125:9): [True: 0, False: 3.19M]
  ------------------
  126|      0|        return 0;
  127|      0|    }
  128|       |
  129|  7.53M|    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: 7.53M]
  |  Branch (129:12): [True: 5.02M, False: 2.51M]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [True: 0, False: 0]
  |  Branch (129:33): [Folded, False: 7.53M]
  ------------------
  130|  5.02M|        if (*string1 == '\0') {
  ------------------
  |  Branch (130:13): [True: 680k, False: 4.34M]
  ------------------
  131|   680k|            return 0;
  132|   680k|        }
  133|  5.02M|    }
  134|       |
  135|  2.51M|    return tolower(*string1) - tolower(*string2);
  ------------------
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [True: 0, False: 0]
  |  Branch (135:12): [Folded, False: 2.51M]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [True: 0, False: 0]
  |  Branch (135:32): [Folded, False: 2.51M]
  ------------------
  136|  3.19M|}

util_SubmitDebugUtilsMessageEXT:
   78|   770k|                                         const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
   79|   770k|    VkBool32 bail = false;
   80|       |
   81|   770k|    if (NULL != pCallbackData) {
  ------------------
  |  Branch (81:9): [True: 770k, False: 0]
  ------------------
   82|   770k|        VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
   83|   770k|        VkDebugReportObjectTypeEXT object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
   84|   770k|        VkDebugReportFlagsEXT object_flags = 0;
   85|   770k|        uint64_t object_handle = 0;
   86|       |
   87|   770k|        debug_utils_AnnotFlagsToReportFlags(messageSeverity, messageTypes, &object_flags);
   88|   770k|        if (0 < pCallbackData->objectCount) {
  ------------------
  |  Branch (88:13): [True: 770k, False: 0]
  ------------------
   89|   770k|            debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
   90|   770k|        }
   91|   770k|        while (pTrav) {
  ------------------
  |  Branch (91:16): [True: 0, False: 770k]
  ------------------
   92|      0|            if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
  ------------------
  |  Branch (92:17): [True: 0, False: 0]
  |  Branch (92:40): [True: 0, False: 0]
  ------------------
   93|      0|                (pTrav->messenger.messageType & messageTypes)) {
  ------------------
  |  Branch (93:17): [True: 0, False: 0]
  ------------------
   94|      0|                if (pTrav->messenger.pfnUserCallback(messageSeverity, messageTypes, pCallbackData, pTrav->pUserData)) {
  ------------------
  |  Branch (94:21): [True: 0, False: 0]
  ------------------
   95|      0|                    bail = true;
   96|      0|                }
   97|      0|            }
   98|      0|            if (!pTrav->is_messenger && pTrav->report.msgFlags & object_flags) {
  ------------------
  |  Branch (98:17): [True: 0, False: 0]
  |  Branch (98:41): [True: 0, False: 0]
  ------------------
   99|      0|                if (pTrav->report.pfnMsgCallback(object_flags, object_type, object_handle, 0, pCallbackData->messageIdNumber,
  ------------------
  |  Branch (99:21): [True: 0, False: 0]
  ------------------
  100|      0|                                                 pCallbackData->pMessageIdName, pCallbackData->pMessage, pTrav->pUserData)) {
  101|      0|                    bail = true;
  102|      0|                }
  103|      0|            }
  104|      0|            pTrav = pTrav->pNext;
  105|      0|        }
  106|   770k|    }
  107|       |
  108|   770k|    return bail;
  109|   770k|}
util_CreateDebugUtilsMessengers:
  130|  6.52k|                                         const VkAllocationCallbacks *pAllocator) {
  131|  6.52k|    const void *pNext = pChain;
  132|  6.52k|    while (pNext) {
  ------------------
  |  Branch (132:12): [True: 0, False: 6.52k]
  ------------------
  133|      0|        VkBaseInStructure in_structure = {0};
  134|      0|        memcpy(&in_structure, pNext, sizeof(VkBaseInStructure));
  135|      0|        if (in_structure.sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
  ------------------
  |  Branch (135:13): [True: 0, False: 0]
  ------------------
  136|       |            // Assign a unique handle to each messenger (just use the address of the VkDebugUtilsMessengerCreateInfoEXT)
  137|       |            // This is only being used this way due to it being for an 'anonymous' callback during instance creation
  138|      0|            VkDebugUtilsMessengerEXT messenger_handle = (VkDebugUtilsMessengerEXT)(uintptr_t)pNext;
  139|      0|            VkResult ret = util_CreateDebugUtilsMessenger(inst, (const VkDebugUtilsMessengerCreateInfoEXT *)pNext, pAllocator,
  140|      0|                                                          messenger_handle);
  141|      0|            if (ret != VK_SUCCESS) {
  ------------------
  |  Branch (141:17): [True: 0, False: 0]
  ------------------
  142|      0|                return ret;
  143|      0|            }
  144|      0|        }
  145|      0|        pNext = in_structure.pNext;
  146|      0|    }
  147|  6.52k|    return VK_SUCCESS;
  148|  6.52k|}
util_CreateDebugReportCallbacks:
  407|  6.52k|                                         const VkAllocationCallbacks *pAllocator) {
  408|  6.52k|    const void *pNext = pChain;
  409|  6.52k|    while (pNext) {
  ------------------
  |  Branch (409:12): [True: 0, False: 6.52k]
  ------------------
  410|      0|        VkBaseInStructure in_structure = {0};
  411|      0|        memcpy(&in_structure, pNext, sizeof(VkBaseInStructure));
  412|      0|        if (in_structure.sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
  ------------------
  |  Branch (412:13): [True: 0, False: 0]
  ------------------
  413|       |            // Assign a unique handle to each callback (just use the address of the VkDebugReportCallbackCreateInfoEXT):
  414|       |            // This is only being used this way due to it being for an 'anonymous' callback during instance creation
  415|      0|            VkDebugReportCallbackEXT report_handle = (VkDebugReportCallbackEXT)(uintptr_t)pNext;
  416|      0|            VkResult ret =
  417|      0|                util_CreateDebugReportCallback(inst, (const VkDebugReportCallbackCreateInfoEXT *)pNext, pAllocator, report_handle);
  418|      0|            if (ret != VK_SUCCESS) {
  ------------------
  |  Branch (418:17): [True: 0, False: 0]
  ------------------
  419|      0|                return ret;
  420|      0|            }
  421|      0|        }
  422|      0|        pNext = in_structure.pNext;
  423|      0|    }
  424|  6.52k|    return VK_SUCCESS;
  425|  6.52k|}
destroy_debug_callbacks_chain:
  599|  6.52k|void destroy_debug_callbacks_chain(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) {
  600|  6.52k|    VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
  601|  6.52k|    VkLayerDbgFunctionNode *pNext = NULL;
  602|  6.52k|    while (pTrav) {
  ------------------
  |  Branch (602:12): [True: 0, False: 6.52k]
  ------------------
  603|      0|        pNext = pTrav->pNext;
  604|      0|        loader_free_with_instance_fallback(pAllocator, inst, pTrav);
  605|      0|        pTrav = pNext;
  606|      0|    }
  607|       |    inst->current_dbg_function_head = NULL;
  608|  6.52k|}
debug_utils_AnnotFlagsToReportFlags:
  682|   770k|                                         VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
  683|   770k|    if (NULL == dr_flags) {
  ------------------
  |  Branch (683:9): [True: 0, False: 770k]
  ------------------
  684|      0|        return false;
  685|      0|    }
  686|       |
  687|   770k|    *dr_flags = 0;
  688|       |
  689|   770k|    if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
  ------------------
  |  Branch (689:9): [True: 14.3k, False: 756k]
  ------------------
  690|  14.3k|        *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
  691|   756k|    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
  ------------------
  |  Branch (691:16): [True: 556k, False: 200k]
  ------------------
  692|   556k|        if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
  ------------------
  |  Branch (692:13): [True: 0, False: 556k]
  ------------------
  693|      0|            *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
  694|   556k|        } else {
  695|   556k|            *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
  696|   556k|        }
  697|   556k|    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
  ------------------
  |  Branch (697:16): [True: 140k, False: 59.9k]
  ------------------
  698|   140k|        *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
  699|   140k|    } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
  ------------------
  |  Branch (699:16): [True: 59.9k, False: 2]
  ------------------
  700|  59.9k|        *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
  701|  59.9k|    }
  702|       |
  703|       |    return true;
  704|   770k|}
debug_utils_AnnotObjectToDebugReportObject:
  720|   770k|                                                VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle) {
  721|   770k|    if (NULL == da_object_name_info || NULL == dr_object_type || NULL == dr_object_handle) {
  ------------------
  |  Branch (721:9): [True: 0, False: 770k]
  |  Branch (721:40): [True: 0, False: 770k]
  |  Branch (721:66): [True: 0, False: 770k]
  ------------------
  722|      0|        return false;
  723|      0|    }
  724|   770k|    *dr_object_type = convertCoreObjectToDebugReportObject(da_object_name_info->objectType);
  725|   770k|    *dr_object_handle = da_object_name_info->objectHandle;
  726|       |    return true;
  727|   770k|}

debug_utils.c:convertCoreObjectToDebugReportObject:
  391|   770k|static inline VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj){
  392|   770k|    if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {
  ------------------
  |  Branch (392:9): [True: 0, False: 770k]
  ------------------
  393|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
  394|   770k|    } else if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {
  ------------------
  |  Branch (394:16): [True: 0, False: 770k]
  ------------------
  395|      0|        return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
  396|   770k|    } else if (core_report_obj == VK_OBJECT_TYPE_INSTANCE) {
  ------------------
  |  Branch (396:16): [True: 770k, False: 0]
  ------------------
  397|   770k|        return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
  398|   770k|    } 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|   770k|}

loader_make_version:
  112|  14.4k|loader_api_version loader_make_version(uint32_t version) {
  113|  14.4k|    loader_api_version out_version;
  114|  14.4k|    out_version.major = VK_API_VERSION_MAJOR(version);
  115|       |    out_version.minor = VK_API_VERSION_MINOR(version);
  116|  14.4k|    out_version.patch = 0;
  117|  14.4k|    return out_version;
  118|  14.4k|}
loader_make_full_version:
  121|  8.15k|loader_api_version loader_make_full_version(uint32_t version) {
  122|  8.15k|    loader_api_version out_version;
  123|  8.15k|    out_version.major = VK_API_VERSION_MAJOR(version);
  124|  8.15k|    out_version.minor = VK_API_VERSION_MINOR(version);
  125|       |    out_version.patch = VK_API_VERSION_PATCH(version);
  126|  8.15k|    return out_version;
  127|  8.15k|}
loader_combine_version:
  129|  17.8k|loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32_t patch) {
  130|  17.8k|    loader_api_version out_version;
  131|  17.8k|    out_version.major = (uint16_t)major;
  132|  17.8k|    out_version.minor = (uint16_t)minor;
  133|  17.8k|    out_version.patch = (uint16_t)patch;
  134|  17.8k|    return out_version;
  135|  17.8k|}
loader_check_version_meets_required:
  138|  22.2k|bool loader_check_version_meets_required(loader_api_version required, loader_api_version version) {
  139|       |    // major version is satisfied
  140|  22.2k|    return (version.major > required.major) ||
  ------------------
  |  Branch (140:12): [True: 4.82k, False: 17.4k]
  ------------------
  141|       |           // major version is equal, minor version is patch version is greater to minimum minor
  142|  17.4k|           (version.major == required.major && version.minor > required.minor) ||
  ------------------
  |  Branch (142:13): [True: 9.64k, False: 7.81k]
  |  Branch (142:48): [True: 3.02k, False: 6.62k]
  ------------------
  143|       |           // major and minor version are equal, patch version is greater or equal to minimum patch
  144|  14.4k|           (version.major == required.major && version.minor == required.minor && version.patch >= required.patch);
  ------------------
  |  Branch (144:13): [True: 6.62k, False: 7.81k]
  |  Branch (144:48): [True: 5.06k, False: 1.55k]
  |  Branch (144:83): [True: 4.05k, False: 1.00k]
  ------------------
  145|  22.2k|}
loader_opendir:
  172|  69.7k|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|  69.7k|    return opendir(name);
  178|       |#else
  179|       |#warning dirent.h - opendir not available on this platform
  180|       |#endif  // _WIN32
  181|  69.7k|}
loader_closedir:
  182|  5.02k|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|  5.02k|    return closedir(dir);
  188|       |#else
  189|       |#warning dirent.h - closedir not available on this platform
  190|       |#endif  // _WIN32
  191|  5.02k|}
is_json:
  193|   156k|bool is_json(const char *path, size_t len) {
  194|   156k|    if (len < 5) {
  ------------------
  |  Branch (194:9): [True: 10.5k, False: 145k]
  ------------------
  195|  10.5k|        return false;
  196|  10.5k|    }
  197|   145k|    return !strncmp(path, ".json", 5);
  198|   156k|}
loader_free_layer_properties:
  248|   395k|void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties) {
  249|   395k|    loader_instance_heap_free(inst, layer_properties->manifest_file_name);
  250|   395k|    loader_instance_heap_free(inst, layer_properties->lib_name);
  251|   395k|    loader_instance_heap_free(inst, layer_properties->functions.str_gipa);
  252|   395k|    loader_instance_heap_free(inst, layer_properties->functions.str_gdpa);
  253|   395k|    loader_instance_heap_free(inst, layer_properties->functions.str_negotiate_interface);
  254|   395k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->instance_extension_list);
  255|   395k|    if (layer_properties->device_extension_list.capacity > 0 && NULL != layer_properties->device_extension_list.list) {
  ------------------
  |  Branch (255:9): [True: 912, False: 394k]
  |  Branch (255:65): [True: 912, False: 0]
  ------------------
  256|  7.99k|        for (uint32_t i = 0; i < layer_properties->device_extension_list.count; i++) {
  ------------------
  |  Branch (256:30): [True: 7.08k, False: 912]
  ------------------
  257|  7.08k|            free_string_list(inst, &layer_properties->device_extension_list.list[i].entrypoints);
  258|  7.08k|        }
  259|    912|    }
  260|   395k|    loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->device_extension_list);
  261|   395k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.name);
  262|   395k|    loader_instance_heap_free(inst, layer_properties->disable_env_var.value);
  263|   395k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.name);
  264|   395k|    loader_instance_heap_free(inst, layer_properties->enable_env_var.value);
  265|   395k|    free_string_list(inst, &layer_properties->component_layer_names);
  266|   395k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_extension_properties);
  267|   395k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_layer_properties);
  268|   395k|    loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_version);
  269|   395k|    free_string_list(inst, &layer_properties->override_paths);
  270|   395k|    free_string_list(inst, &layer_properties->blacklist_layer_names);
  271|   395k|    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|   395k|    memset(layer_properties, 0, sizeof(struct loader_layer_properties));
  275|   395k|}
loader_copy_to_new_str:
  287|   350k|VkResult loader_copy_to_new_str(const struct loader_instance *inst, const char *source_str, char **dest_str) {
  288|   350k|    assert(source_str && dest_str);
  289|   350k|    size_t str_len = strlen(source_str) + 1;
  290|   350k|    *dest_str = loader_instance_heap_calloc(inst, str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  291|   350k|    if (NULL == *dest_str) return VK_ERROR_OUT_OF_HOST_MEMORY;
  ------------------
  |  Branch (291:9): [True: 0, False: 350k]
  ------------------
  292|   350k|    loader_strncpy(*dest_str, str_len, source_str, str_len);
  293|   350k|    (*dest_str)[str_len - 1] = 0;
  294|   350k|    return VK_SUCCESS;
  295|   350k|}
create_string_list:
  297|  11.5k|VkResult create_string_list(const struct loader_instance *inst, uint32_t allocated_count, struct loader_string_list *string_list) {
  298|  11.5k|    assert(string_list);
  299|  11.5k|    string_list->list = loader_instance_heap_calloc(inst, sizeof(char *) * allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  300|  11.5k|    if (NULL == string_list->list) {
  ------------------
  |  Branch (300:9): [True: 0, False: 11.5k]
  ------------------
  301|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  302|      0|    }
  303|  11.5k|    string_list->allocated_count = allocated_count;
  304|  11.5k|    string_list->count = 0;
  305|  11.5k|    return VK_SUCCESS;
  306|  11.5k|}
increase_str_capacity_by_at_least_one:
  308|  89.7k|VkResult increase_str_capacity_by_at_least_one(const struct loader_instance *inst, struct loader_string_list *string_list) {
  309|  89.7k|    assert(string_list);
  310|  89.7k|    if (string_list->allocated_count == 0) {
  ------------------
  |  Branch (310:9): [True: 4.05k, False: 85.6k]
  ------------------
  311|  4.05k|        string_list->allocated_count = 32;
  312|  4.05k|        string_list->list =
  313|  4.05k|            loader_instance_heap_calloc(inst, sizeof(char *) * string_list->allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  314|  4.05k|        if (NULL == string_list->list) {
  ------------------
  |  Branch (314:13): [True: 0, False: 4.05k]
  ------------------
  315|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  316|      0|        }
  317|  85.6k|    } else if (string_list->count + 1 > string_list->allocated_count) {
  ------------------
  |  Branch (317:16): [True: 9, False: 85.6k]
  ------------------
  318|      9|        uint32_t new_allocated_count = string_list->allocated_count * 2;
  319|      9|        void *new_ptr = loader_instance_heap_realloc(inst, string_list->list, sizeof(char *) * string_list->allocated_count,
  320|      9|                                                     sizeof(char *) * new_allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  321|      9|        if (NULL == new_ptr) {
  ------------------
  |  Branch (321:13): [True: 0, False: 9]
  ------------------
  322|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  323|      0|        }
  324|      9|        string_list->list = new_ptr;
  325|      9|        string_list->allocated_count *= 2;
  326|      9|    }
  327|  89.7k|    return VK_SUCCESS;
  328|  89.7k|}
append_str_to_string_list:
  330|  89.7k|VkResult append_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, char *str) {
  331|  89.7k|    assert(string_list && str);
  332|  89.7k|    VkResult res = increase_str_capacity_by_at_least_one(inst, string_list);
  333|  89.7k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (333:9): [True: 0, False: 89.7k]
  ------------------
  334|      0|        loader_instance_heap_free(inst, str);  // Must clean up in case of failure
  335|      0|        return res;
  336|      0|    }
  337|  89.7k|    string_list->list[string_list->count++] = str;
  338|  89.7k|    return VK_SUCCESS;
  339|  89.7k|}
copy_str_to_string_list:
  356|  4.51k|                                 size_t str_len) {
  357|  4.51k|    assert(string_list && str);
  358|  4.51k|    char *new_str = loader_instance_heap_calloc(inst, sizeof(char *) * str_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  359|  4.51k|    if (NULL == new_str) {
  ------------------
  |  Branch (359:9): [True: 0, False: 4.51k]
  ------------------
  360|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  361|      0|    }
  362|  4.51k|    loader_strncpy(new_str, sizeof(char *) * str_len + 1, str, str_len);
  363|  4.51k|    new_str[str_len] = '\0';
  364|  4.51k|    return append_str_to_string_list(inst, string_list, new_str);
  365|  4.51k|}
free_string_list:
  379|  1.61M|void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list) {
  380|  1.61M|    assert(string_list);
  381|  1.61M|    if (string_list->list) {
  ------------------
  |  Branch (381:9): [True: 15.5k, False: 1.60M]
  ------------------
  382|   105k|        for (uint32_t i = 0; i < string_list->count; i++) {
  ------------------
  |  Branch (382:30): [True: 89.7k, False: 15.5k]
  ------------------
  383|  89.7k|            loader_instance_heap_free(inst, string_list->list[i]);
  384|       |            string_list->list[i] = NULL;
  385|  89.7k|        }
  386|  15.5k|        loader_instance_heap_free(inst, string_list->list);
  387|  15.5k|    }
  388|  1.61M|    memset(string_list, 0, sizeof(struct loader_string_list));
  389|  1.61M|}
loader_parse_version_string:
  665|  30.7k|uint32_t loader_parse_version_string(char *vers_str) {
  666|  30.7k|    uint32_t variant = 0, major = 0, minor = 0, patch = 0;
  667|  30.7k|    char *vers_tok;
  668|  30.7k|    char *context = NULL;
  669|  30.7k|    if (!vers_str) {
  ------------------
  |  Branch (669:9): [True: 0, False: 30.7k]
  ------------------
  670|      0|        return 0;
  671|      0|    }
  672|       |
  673|  30.7k|    vers_tok = thread_safe_strtok(vers_str, ".\"\n\r", &context);
  674|  30.7k|    if (NULL != vers_tok) {
  ------------------
  |  Branch (674:9): [True: 22.6k, False: 8.10k]
  ------------------
  675|  22.6k|        major = (uint16_t)atoi(vers_tok);
  676|  22.6k|        vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  677|  22.6k|        if (NULL != vers_tok) {
  ------------------
  |  Branch (677:13): [True: 14.2k, False: 8.40k]
  ------------------
  678|  14.2k|            minor = (uint16_t)atoi(vers_tok);
  679|  14.2k|            vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  680|  14.2k|            if (NULL != vers_tok) {
  ------------------
  |  Branch (680:17): [True: 9.95k, False: 4.24k]
  ------------------
  681|  9.95k|                patch = (uint16_t)atoi(vers_tok);
  682|  9.95k|                vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context);
  683|       |                // check that we are using a 4 part version string
  684|  9.95k|                if (NULL != vers_tok) {
  ------------------
  |  Branch (684:21): [True: 2.10k, False: 7.85k]
  ------------------
  685|       |                    // if we are, move the values over into the correct place
  686|  2.10k|                    variant = major;
  687|  2.10k|                    major = minor;
  688|  2.10k|                    minor = patch;
  689|  2.10k|                    patch = (uint16_t)atoi(vers_tok);
  690|  2.10k|                }
  691|  9.95k|            }
  692|  14.2k|        }
  693|  22.6k|    }
  694|       |
  695|       |    return VK_MAKE_API_VERSION(variant, major, minor, patch);
  696|  30.7k|}
compare_vk_extension_properties:
  698|   466k|bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) {
  699|   466k|    return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
  ------------------
  |  Branch (699:12): [True: 4.81k, False: 461k]
  ------------------
  700|   466k|}
has_vk_extension_property:
  712|  16.0k|bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) {
  713|   337k|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (713:26): [True: 323k, False: 13.9k]
  ------------------
  714|   323k|        if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true;
  ------------------
  |  Branch (714:13): [True: 2.05k, False: 321k]
  ------------------
  715|   323k|    }
  716|  13.9k|    return false;
  717|  16.0k|}
has_vk_dev_ext_property:
  720|  12.3k|bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) {
  721|   152k|    for (uint32_t i = 0; i < ext_list->count; i++) {
  ------------------
  |  Branch (721:26): [True: 142k, False: 9.62k]
  ------------------
  722|   142k|        if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true;
  ------------------
  |  Branch (722:13): [True: 2.76k, False: 139k]
  ------------------
  723|   142k|    }
  724|  9.62k|    return false;
  725|  12.3k|}
loader_append_layer_property:
  728|   236k|                                      struct loader_layer_properties *layer_property) {
  729|   236k|    VkResult res = VK_SUCCESS;
  730|   236k|    if (layer_list->capacity == 0) {
  ------------------
  |  Branch (730:9): [True: 3.52k, False: 232k]
  ------------------
  731|  3.52k|        res = loader_init_generic_list(inst, (struct loader_generic_list *)layer_list, sizeof(struct loader_layer_properties));
  732|  3.52k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (732:13): [True: 0, False: 3.52k]
  ------------------
  733|      0|            goto out;
  734|      0|        }
  735|  3.52k|    }
  736|       |
  737|       |    // Ensure enough room to add an entry
  738|   236k|    if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) {
  ------------------
  |  Branch (738:9): [True: 475, False: 235k]
  ------------------
  739|    475|        void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2,
  740|    475|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  741|    475|        if (NULL == new_ptr) {
  ------------------
  |  Branch (741:13): [True: 0, False: 475]
  ------------------
  742|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_append_layer_property: realloc failed for layer list");
  743|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  744|      0|            goto out;
  745|      0|        }
  746|    475|        layer_list->list = new_ptr;
  747|    475|        layer_list->capacity *= 2;
  748|    475|    }
  749|   236k|    memcpy(&layer_list->list[layer_list->count], layer_property, sizeof(struct loader_layer_properties));
  750|   236k|    layer_list->count++;
  751|   236k|    memset(layer_property, 0, sizeof(struct loader_layer_properties));
  752|   236k|out:
  753|   236k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (753:9): [True: 0, False: 236k]
  ------------------
  754|      0|        loader_free_layer_properties(inst, layer_property);
  755|      0|    }
  756|   236k|    return res;
  757|   236k|}
loader_find_layer_property:
  760|  13.2k|struct loader_layer_properties *loader_find_layer_property(const char *name, const struct loader_layer_list *layer_list) {
  761|   235k|    for (uint32_t i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (761:26): [True: 228k, False: 7.06k]
  ------------------
  762|   228k|        const VkLayerProperties *item = &layer_list->list[i].info;
  763|   228k|        if (strcmp(name, item->layerName) == 0) return &layer_list->list[i];
  ------------------
  |  Branch (763:13): [True: 6.14k, False: 222k]
  ------------------
  764|   228k|    }
  765|  7.06k|    return NULL;
  766|  13.2k|}
loader_find_layer_name_in_blacklist:
  805|  1.43k|bool loader_find_layer_name_in_blacklist(const char *layer_name, struct loader_layer_properties *meta_layer_props) {
  806|  1.43k|    for (uint32_t black_layer = 0; black_layer < meta_layer_props->blacklist_layer_names.count; ++black_layer) {
  ------------------
  |  Branch (806:36): [True: 0, False: 1.43k]
  ------------------
  807|      0|        if (!strcmp(meta_layer_props->blacklist_layer_names.list[black_layer], layer_name)) {
  ------------------
  |  Branch (807:13): [True: 0, False: 0]
  ------------------
  808|      0|            return true;
  809|      0|        }
  810|      0|    }
  811|  1.43k|    return false;
  812|  1.43k|}
loader_delete_layer_list_and_properties:
  816|  19.5k|                                                                  struct loader_layer_list *layer_list) {
  817|  19.5k|    uint32_t i;
  818|  19.5k|    if (!layer_list) return;
  ------------------
  |  Branch (818:9): [True: 0, False: 19.5k]
  ------------------
  819|       |
  820|   214k|    for (i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (820:17): [True: 195k, False: 19.5k]
  ------------------
  821|   195k|        if (layer_list->list[i].lib_handle) {
  ------------------
  |  Branch (821:13): [True: 0, False: 195k]
  ------------------
  822|      0|            loader_platform_close_library(layer_list->list[i].lib_handle);
  823|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Unloading layer library %s",
  824|      0|                       layer_list->list[i].lib_name);
  825|      0|            layer_list->list[i].lib_handle = NULL;
  826|      0|        }
  827|   195k|        loader_free_layer_properties(inst, &(layer_list->list[i]));
  828|   195k|    }
  829|  19.5k|    layer_list->count = 0;
  830|       |
  831|  19.5k|    if (layer_list->capacity > 0) {
  ------------------
  |  Branch (831:9): [True: 3.83k, False: 15.7k]
  ------------------
  832|  3.83k|        layer_list->capacity = 0;
  833|  3.83k|        loader_instance_heap_free(inst, layer_list->list);
  834|  3.83k|    }
  835|  19.5k|    memset(layer_list, 0, sizeof(struct loader_layer_list));
  836|  19.5k|}
loader_remove_layer_in_list:
  839|  41.1k|                                 uint32_t layer_to_remove) {
  840|  41.1k|    if (layer_list == NULL || layer_to_remove >= layer_list->count) {
  ------------------
  |  Branch (840:9): [True: 0, False: 41.1k]
  |  Branch (840:31): [True: 0, False: 41.1k]
  ------------------
  841|      0|        return;
  842|      0|    }
  843|  41.1k|    loader_free_layer_properties(inst, &(layer_list->list[layer_to_remove]));
  844|       |
  845|       |    // Remove the current invalid meta-layer from the layer list.  Use memmove since we are
  846|       |    // overlapping the source and destination addresses.
  847|  41.1k|    if (layer_to_remove + 1 <= layer_list->count) {
  ------------------
  |  Branch (847:9): [True: 41.1k, False: 0]
  ------------------
  848|  41.1k|        memmove(&layer_list->list[layer_to_remove], &layer_list->list[layer_to_remove + 1],
  849|  41.1k|                sizeof(struct loader_layer_properties) * (layer_list->count - 1 - layer_to_remove));
  850|  41.1k|    }
  851|       |    // Decrement the count (because we now have one less) and decrement the loop index since we need to
  852|       |    // re-check this index.
  853|  41.1k|    layer_list->count--;
  854|  41.1k|}
loader_remove_layers_in_blacklist:
  858|    168|void loader_remove_layers_in_blacklist(const struct loader_instance *inst, struct loader_layer_list *layer_list) {
  859|    168|    struct loader_layer_properties *override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list);
  ------------------
  |  |  138|    168|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  860|    168|    if (NULL == override_prop) {
  ------------------
  |  Branch (860:9): [True: 0, False: 168]
  ------------------
  861|      0|        return;
  862|      0|    }
  863|       |
  864|  1.77k|    for (int32_t j = 0; j < (int32_t)(layer_list->count); j++) {
  ------------------
  |  Branch (864:25): [True: 1.60k, False: 168]
  ------------------
  865|  1.60k|        struct loader_layer_properties cur_layer_prop = layer_list->list[j];
  866|  1.60k|        const char *cur_layer_name = &cur_layer_prop.info.layerName[0];
  867|       |
  868|       |        // Skip the override layer itself.
  869|  1.60k|        if (!strcmp(VK_OVERRIDE_LAYER_NAME, cur_layer_name)) {
  ------------------
  |  |  138|  1.60k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (869:13): [True: 168, False: 1.43k]
  ------------------
  870|    168|            continue;
  871|    168|        }
  872|       |
  873|       |        // If found in the override layer's blacklist, remove it
  874|  1.43k|        if (loader_find_layer_name_in_blacklist(cur_layer_name, override_prop)) {
  ------------------
  |  Branch (874:13): [True: 0, False: 1.43k]
  ------------------
  875|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  876|      0|                       "loader_remove_layers_in_blacklist: Override layer is active and layer %s is in the blacklist inside of it. "
  877|      0|                       "Removing that layer from current layer list.",
  878|      0|                       cur_layer_name);
  879|      0|            loader_remove_layer_in_list(inst, layer_list, j);
  880|      0|            j--;
  881|       |
  882|       |            // Re-do the query for the override layer
  883|      0|            override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list);
  ------------------
  |  |  138|      0|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  884|      0|        }
  885|  1.43k|    }
  886|    168|}
loader_init_generic_list:
 1035|  5.63k|VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) {
 1036|  5.63k|    size_t capacity = 32 * element_size;
 1037|  5.63k|    list_info->count = 0;
 1038|  5.63k|    list_info->capacity = 0;
 1039|  5.63k|    list_info->list = loader_instance_heap_calloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1040|  5.63k|    if (list_info->list == NULL) {
  ------------------
  |  Branch (1040:9): [True: 0, False: 5.63k]
  ------------------
 1041|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_init_generic_list: Failed to allocate space for generic list");
 1042|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
 1043|      0|    }
 1044|  5.63k|    list_info->capacity = capacity;
 1045|  5.63k|    return VK_SUCCESS;
 1046|  5.63k|}
loader_destroy_generic_list:
 1060|   817k|void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) {
 1061|   817k|    loader_instance_heap_free(inst, list->list);
 1062|   817k|    memset(list, 0, sizeof(struct loader_generic_list));
 1063|   817k|}
loader_add_to_ext_list:
 1116|  13.2k|                                uint32_t prop_list_count, const VkExtensionProperties *props) {
 1117|  13.2k|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1117:9): [True: 895, False: 12.3k]
  |  Branch (1117:35): [True: 0, False: 12.3k]
  ------------------
 1118|    895|        VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties));
 1119|    895|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1119:13): [True: 0, False: 895]
  ------------------
 1120|      0|            return res;
 1121|      0|        }
 1122|    895|    }
 1123|       |
 1124|  26.5k|    for (uint32_t i = 0; i < prop_list_count; i++) {
  ------------------
  |  Branch (1124:26): [True: 13.2k, False: 13.2k]
  ------------------
 1125|  13.2k|        const VkExtensionProperties *cur_ext = &props[i];
 1126|       |
 1127|       |        // look for duplicates
 1128|  13.2k|        if (has_vk_extension_property(cur_ext, ext_list)) {
  ------------------
  |  Branch (1128:13): [True: 1.93k, False: 11.3k]
  ------------------
 1129|  1.93k|            continue;
 1130|  1.93k|        }
 1131|       |
 1132|       |        // add to list at end
 1133|       |        // check for enough capacity
 1134|  11.3k|        if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) {
  ------------------
  |  Branch (1134:13): [True: 244, False: 11.1k]
  ------------------
 1135|    244|            void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1136|    244|                                                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1137|    244|            if (new_ptr == NULL) {
  ------------------
  |  Branch (1137:17): [True: 0, False: 244]
  ------------------
 1138|      0|                loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1139|      0|                           "loader_add_to_ext_list: Failed to reallocate space for extension list");
 1140|      0|                return VK_ERROR_OUT_OF_HOST_MEMORY;
 1141|      0|            }
 1142|    244|            ext_list->list = new_ptr;
 1143|       |
 1144|       |            // double capacity
 1145|    244|            ext_list->capacity *= 2;
 1146|    244|        }
 1147|       |
 1148|  11.3k|        memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
 1149|  11.3k|        ext_list->count++;
 1150|  11.3k|    }
 1151|  13.2k|    return VK_SUCCESS;
 1152|  13.2k|}
loader_add_to_dev_ext_list:
 1159|  9.50k|                                    const VkExtensionProperties *props, struct loader_string_list *entrys) {
 1160|  9.50k|    VkResult res = VK_SUCCESS;
 1161|  9.50k|    bool should_free_entrys = true;
 1162|  9.50k|    if (ext_list->list == NULL || ext_list->capacity == 0) {
  ------------------
  |  Branch (1162:9): [True: 912, False: 8.58k]
  |  Branch (1162:35): [True: 0, False: 8.58k]
  ------------------
 1163|    912|        res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props));
 1164|    912|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1164:13): [True: 0, False: 912]
  ------------------
 1165|      0|            goto out;
 1166|      0|        }
 1167|    912|    }
 1168|       |
 1169|       |    // look for duplicates
 1170|  9.50k|    if (has_vk_dev_ext_property(props, ext_list)) {
  ------------------
  |  Branch (1170:9): [True: 2.42k, False: 7.08k]
  ------------------
 1171|  2.42k|        goto out;
 1172|  2.42k|    }
 1173|       |
 1174|  7.08k|    uint32_t idx = ext_list->count;
 1175|       |    // add to list at end
 1176|       |    // check for enough capacity
 1177|  7.08k|    if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
  ------------------
  |  Branch (1177:9): [True: 86, False: 6.99k]
  ------------------
 1178|     86|        void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
 1179|     86|                                                     VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1180|       |
 1181|     86|        if (NULL == new_ptr) {
  ------------------
  |  Branch (1181:13): [True: 0, False: 86]
  ------------------
 1182|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1183|      0|                       "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list");
 1184|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1185|      0|            goto out;
 1186|      0|        }
 1187|     86|        ext_list->list = new_ptr;
 1188|       |
 1189|       |        // double capacity
 1190|     86|        ext_list->capacity *= 2;
 1191|     86|    }
 1192|       |
 1193|  7.08k|    memcpy(&ext_list->list[idx].props, props, sizeof(*props));
 1194|  7.08k|    if (entrys) {
  ------------------
  |  Branch (1194:9): [True: 658, False: 6.42k]
  ------------------
 1195|    658|        ext_list->list[idx].entrypoints = *entrys;
 1196|    658|        should_free_entrys = false;
 1197|    658|    }
 1198|  7.08k|    ext_list->count++;
 1199|  9.50k|out:
 1200|  9.50k|    if (NULL != entrys && should_free_entrys) {
  ------------------
  |  Branch (1200:9): [True: 2.23k, False: 7.26k]
  |  Branch (1200:27): [True: 1.57k, False: 658]
  ------------------
 1201|  1.57k|        free_string_list(inst, entrys);
 1202|  1.57k|    }
 1203|  9.50k|    return res;
 1204|  7.08k|}
loader_destroy_pointer_layer_list:
 1228|  13.0k|void loader_destroy_pointer_layer_list(const struct loader_instance *inst, struct loader_pointer_layer_list *layer_list) {
 1229|  13.0k|    loader_instance_heap_free(inst, layer_list->list);
 1230|  13.0k|    memset(layer_list, 0, sizeof(struct loader_pointer_layer_list));
 1231|  13.0k|}
loader_layer_is_available:
 1262|  31.5k|                               const struct loader_layer_properties *prop) {
 1263|  31.5k|    bool available = true;
 1264|  31.5k|    bool is_implicit = (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER));
 1265|  31.5k|    bool disabled_by_type =
 1266|  31.5k|        (is_implicit) ? (filters->disable_filter.disable_all_implicit) : (filters->disable_filter.disable_all_explicit);
  ------------------
  |  Branch (1266:9): [True: 31.4k, False: 162]
  ------------------
 1267|  31.5k|    if ((filters->disable_filter.disable_all || disabled_by_type ||
  ------------------
  |  Branch (1267:10): [True: 0, False: 31.5k]
  |  Branch (1267:49): [True: 0, False: 31.5k]
  ------------------
 1268|  31.5k|         check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) &&
  ------------------
  |  Branch (1268:10): [True: 0, False: 31.5k]
  ------------------
 1269|      0|        !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) {
  ------------------
  |  Branch (1269:9): [True: 0, False: 0]
  ------------------
 1270|      0|        available = false;
 1271|      0|    }
 1272|  31.5k|    if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) {
  ------------------
  |  Branch (1272:9): [True: 185, False: 31.4k]
  ------------------
 1273|    185|        available = true;
 1274|  31.4k|    } else if (!available) {
  ------------------
  |  Branch (1274:16): [True: 0, False: 31.4k]
  ------------------
 1275|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1276|      0|                   "Layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName,
 1277|      0|                   VK_LAYERS_DISABLE_ENV_VAR);
  ------------------
  |  |  120|      0|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
 1278|      0|    }
 1279|       |
 1280|  31.5k|    return available;
 1281|  31.5k|}
loader_implicit_layer_is_enabled:
 1330|    475|                                      const struct loader_layer_properties *prop) {
 1331|    475|    bool enable = false;
 1332|    475|    bool forced_disabled = false;
 1333|    475|    bool forced_enabled = false;
 1334|       |
 1335|    475|    if ((filters->disable_filter.disable_all || filters->disable_filter.disable_all_implicit ||
  ------------------
  |  Branch (1335:10): [True: 0, False: 475]
  |  Branch (1335:49): [True: 0, False: 475]
  ------------------
 1336|    475|         check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) &&
  ------------------
  |  Branch (1336:10): [True: 0, False: 475]
  ------------------
 1337|      0|        !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) {
  ------------------
  |  Branch (1337:9): [True: 0, False: 0]
  ------------------
 1338|      0|        forced_disabled = true;
 1339|      0|    }
 1340|    475|    if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) {
  ------------------
  |  Branch (1340:9): [True: 0, False: 475]
  ------------------
 1341|      0|        forced_enabled = true;
 1342|      0|    }
 1343|       |
 1344|       |    // If no enable_environment variable is specified, this implicit layer is always be enabled by default.
 1345|    475|    if (NULL == prop->enable_env_var.name) {
  ------------------
  |  Branch (1345:9): [True: 378, False: 97]
  ------------------
 1346|    378|        enable = true;
 1347|    378|    } else {
 1348|     97|        char *env_value = loader_getenv(prop->enable_env_var.name, inst);
 1349|     97|        if (env_value && !strcmp(prop->enable_env_var.value, env_value)) {
  ------------------
  |  Branch (1349:13): [True: 91, False: 6]
  |  Branch (1349:26): [True: 0, False: 91]
  ------------------
 1350|      0|            enable = true;
 1351|      0|        }
 1352|       |
 1353|       |        // Otherwise, only enable this layer if the enable environment variable is defined
 1354|     97|        loader_free_getenv(env_value, inst);
 1355|     97|    }
 1356|       |
 1357|    475|    if (forced_enabled) {
  ------------------
  |  Branch (1357:9): [True: 0, False: 475]
  ------------------
 1358|       |        // Only report a message that we've forced on a layer if it wouldn't have been enabled
 1359|       |        // normally.
 1360|      0|        if (!enable) {
  ------------------
  |  Branch (1360:13): [True: 0, False: 0]
  ------------------
 1361|      0|            enable = true;
 1362|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1363|      0|                       "Implicit layer \"%s\" forced enabled due to env var \'%s\'.", prop->info.layerName,
 1364|      0|                       VK_LAYERS_ENABLE_ENV_VAR);
  ------------------
  |  |  119|      0|#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
  ------------------
 1365|      0|        }
 1366|    475|    } else if (enable && forced_disabled) {
  ------------------
  |  Branch (1366:16): [True: 378, False: 97]
  |  Branch (1366:26): [True: 0, False: 378]
  ------------------
 1367|      0|        enable = false;
 1368|       |        // Report a message that we've forced off a layer if it would have been enabled normally.
 1369|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1370|      0|                   "Implicit layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName,
 1371|      0|                   VK_LAYERS_DISABLE_ENV_VAR);
  ------------------
  |  |  120|      0|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
 1372|      0|        return enable;
 1373|      0|    }
 1374|       |
 1375|       |    // The disable_environment has priority over everything else.  If it is defined, the layer is always
 1376|       |    // disabled.
 1377|    475|    if (NULL != prop->disable_env_var.name) {
  ------------------
  |  Branch (1377:9): [True: 441, False: 34]
  ------------------
 1378|    441|        char *env_value = loader_getenv(prop->disable_env_var.name, inst);
 1379|    441|        if (NULL != env_value) {
  ------------------
  |  Branch (1379:13): [True: 2, False: 439]
  ------------------
 1380|      2|            enable = false;
 1381|      2|        }
 1382|    441|        loader_free_getenv(env_value, inst);
 1383|    441|    } else if ((prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER) == 0) {
  ------------------
  |  Branch (1383:16): [True: 34, False: 0]
  ------------------
 1384|     34|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 1385|     34|                   "Implicit layer \"%s\" missing disabled environment variable!", prop->info.layerName);
 1386|     34|    }
 1387|       |
 1388|       |    // Enable this layer if it is included in the override layer
 1389|    475|    if (inst != NULL && inst->override_layer_present) {
  ------------------
  |  Branch (1389:9): [True: 475, False: 0]
  |  Branch (1389:25): [True: 0, False: 475]
  ------------------
 1390|      0|        struct loader_layer_properties *override = NULL;
 1391|      0|        for (uint32_t i = 0; i < inst->instance_layer_list.count; ++i) {
  ------------------
  |  Branch (1391:30): [True: 0, False: 0]
  ------------------
 1392|      0|            if (strcmp(inst->instance_layer_list.list[i].info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) {
  ------------------
  |  |  138|      0|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (1392:17): [True: 0, False: 0]
  ------------------
 1393|      0|                override = &inst->instance_layer_list.list[i];
 1394|      0|                break;
 1395|      0|            }
 1396|      0|        }
 1397|      0|        if (override != NULL) {
  ------------------
  |  Branch (1397:13): [True: 0, False: 0]
  ------------------
 1398|      0|            for (uint32_t i = 0; i < override->component_layer_names.count; ++i) {
  ------------------
  |  Branch (1398:34): [True: 0, False: 0]
  ------------------
 1399|      0|                if (strcmp(override->component_layer_names.list[i], prop->info.layerName) == 0) {
  ------------------
  |  Branch (1399:21): [True: 0, False: 0]
  ------------------
 1400|      0|                    enable = true;
 1401|      0|                    break;
 1402|      0|                }
 1403|      0|            }
 1404|      0|        }
 1405|      0|    }
 1406|       |
 1407|    475|    return enable;
 1408|    475|}
loader_clear_scanned_icd_list:
 1824|  6.54k|void loader_clear_scanned_icd_list(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
 1825|  6.54k|    if (0 != icd_tramp_list->capacity && icd_tramp_list->scanned_list) {
  ------------------
  |  Branch (1825:9): [True: 17, False: 6.52k]
  |  Branch (1825:42): [True: 17, False: 0]
  ------------------
 1826|     17|        for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
  ------------------
  |  Branch (1826:30): [True: 0, False: 17]
  ------------------
 1827|      0|            if (icd_tramp_list->scanned_list[i].handle) {
  ------------------
  |  Branch (1827:17): [True: 0, False: 0]
  ------------------
 1828|      0|                loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
 1829|       |                icd_tramp_list->scanned_list[i].handle = NULL;
 1830|      0|            }
 1831|      0|            loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name);
 1832|      0|        }
 1833|     17|        loader_instance_heap_free(inst, icd_tramp_list->scanned_list);
 1834|     17|    }
 1835|  6.54k|    memset(icd_tramp_list, 0, sizeof(struct loader_icd_tramp_list));
 1836|  6.54k|}
loader_init_scanned_icd_list:
 1838|     17|VkResult loader_init_scanned_icd_list(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
 1839|     17|    VkResult res = VK_SUCCESS;
 1840|     17|    loader_clear_scanned_icd_list(inst, icd_tramp_list);
 1841|     17|    icd_tramp_list->capacity = 8 * sizeof(struct loader_scanned_icd);
 1842|     17|    icd_tramp_list->scanned_list = loader_instance_heap_alloc(inst, icd_tramp_list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 1843|     17|    if (NULL == icd_tramp_list->scanned_list) {
  ------------------
  |  Branch (1843:9): [True: 0, False: 17]
  ------------------
 1844|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 1845|      0|                   "loader_init_scanned_icd_list: Realloc failed for layer list when attempting to add new layer");
 1846|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1847|      0|    }
 1848|     17|    return res;
 1849|     17|}
loader_scan_for_direct_drivers:
 1987|     17|                                        struct loader_icd_tramp_list *icd_tramp_list, bool *direct_driver_loading_exclusive_mode) {
 1988|     17|    if (NULL == pCreateInfo) {
  ------------------
  |  Branch (1988:9): [True: 0, False: 17]
  ------------------
 1989|       |        // Don't do this logic unless we are being called from vkCreateInstance, when pCreateInfo will be non-null
 1990|      0|        return VK_SUCCESS;
 1991|      0|    }
 1992|     17|    bool direct_driver_loading_enabled = false;
 1993|       |    // Try to if VK_LUNARG_direct_driver_loading is enabled and if we are using it exclusively
 1994|       |    // Skip this step if inst is NULL, aka when this function is being called before instance creation
 1995|     17|    if (inst != NULL && pCreateInfo->ppEnabledExtensionNames && pCreateInfo->enabledExtensionCount > 0) {
  ------------------
  |  Branch (1995:9): [True: 17, False: 0]
  |  Branch (1995:25): [True: 0, False: 17]
  |  Branch (1995:65): [True: 0, False: 0]
  ------------------
 1996|       |        // Look through the enabled extension list, make sure VK_LUNARG_direct_driver_loading is present
 1997|      0|        for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
  ------------------
  |  Branch (1997:30): [True: 0, False: 0]
  ------------------
 1998|      0|            if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME) == 0) {
  ------------------
  |  Branch (1998:17): [True: 0, False: 0]
  ------------------
 1999|      0|                direct_driver_loading_enabled = true;
 2000|      0|                break;
 2001|      0|            }
 2002|      0|        }
 2003|      0|    }
 2004|     17|    const VkDirectDriverLoadingListLUNARG *ddl_list = NULL;
 2005|       |    // Find the VkDirectDriverLoadingListLUNARG struct in the pNext chain of vkInstanceCreateInfo
 2006|     17|    const void *pNext = pCreateInfo->pNext;
 2007|     17|    while (pNext) {
  ------------------
  |  Branch (2007:12): [True: 0, False: 17]
  ------------------
 2008|      0|        VkBaseInStructure out_structure = {0};
 2009|      0|        memcpy(&out_structure, pNext, sizeof(VkBaseInStructure));
 2010|      0|        if (out_structure.sType == VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG) {
  ------------------
  |  Branch (2010:13): [True: 0, False: 0]
  ------------------
 2011|      0|            ddl_list = (VkDirectDriverLoadingListLUNARG *)pNext;
 2012|      0|            break;
 2013|      0|        }
 2014|      0|        pNext = out_structure.pNext;
 2015|      0|    }
 2016|     17|    if (NULL == ddl_list) {
  ------------------
  |  Branch (2016:9): [True: 17, False: 0]
  ------------------
 2017|     17|        if (direct_driver_loading_enabled) {
  ------------------
  |  Branch (2017:13): [True: 0, False: 17]
  ------------------
 2018|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2019|      0|                       "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension was enabled but the "
 2020|      0|                       "pNext chain of "
 2021|      0|                       "VkInstanceCreateInfo did not contain the "
 2022|      0|                       "VkDirectDriverLoadingListLUNARG structure.");
 2023|      0|        }
 2024|       |        // Always want to exit early if there was no VkDirectDriverLoadingListLUNARG in the pNext chain
 2025|     17|        return VK_SUCCESS;
 2026|     17|    }
 2027|       |
 2028|      0|    if (!direct_driver_loading_enabled) {
  ------------------
  |  Branch (2028:9): [True: 0, False: 0]
  ------------------
 2029|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2030|      0|                   "loader_scan_for_direct_drivers: The pNext chain of VkInstanceCreateInfo contained the "
 2031|      0|                   "VkDirectDriverLoadingListLUNARG structure, but the VK_LUNARG_direct_driver_loading extension was "
 2032|      0|                   "not enabled.");
 2033|      0|        return VK_SUCCESS;
 2034|      0|    }
 2035|       |    // If we are using exclusive mode, skip looking for any more drivers from system or environment variables
 2036|      0|    if (ddl_list->mode == VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG) {
  ------------------
  |  Branch (2036:9): [True: 0, False: 0]
  ------------------
 2037|      0|        *direct_driver_loading_exclusive_mode = true;
 2038|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2039|      0|                   "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension is active and specified "
 2040|      0|                   "VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG, skipping system and environment "
 2041|      0|                   "variable driver search mechanisms.");
 2042|      0|    }
 2043|      0|    if (NULL == ddl_list->pDrivers) {
  ------------------
  |  Branch (2043:9): [True: 0, False: 0]
  ------------------
 2044|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2045|      0|                   "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
 2046|      0|                   "VkInstanceCreateInfo has a NULL pDrivers member.");
 2047|      0|        return VK_SUCCESS;
 2048|      0|    }
 2049|      0|    if (ddl_list->driverCount == 0) {
  ------------------
  |  Branch (2049:9): [True: 0, False: 0]
  ------------------
 2050|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 2051|      0|                   "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
 2052|      0|                   "VkInstanceCreateInfo has a non-null pDrivers member but a driverCount member with a value "
 2053|      0|                   "of zero.");
 2054|      0|        return VK_SUCCESS;
 2055|      0|    }
 2056|       |    // Go through all VkDirectDriverLoadingInfoLUNARG entries and add each driver
 2057|       |    // Because icd_tramp's are prepended, this will result in the drivers appearing at the end
 2058|      0|    for (uint32_t i = 0; i < ddl_list->driverCount; i++) {
  ------------------
  |  Branch (2058:26): [True: 0, False: 0]
  ------------------
 2059|      0|        VkResult res = loader_add_direct_driver(inst, i, &ddl_list->pDrivers[i], icd_tramp_list);
 2060|      0|        if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2060:13): [True: 0, False: 0]
  ------------------
 2061|      0|            return res;
 2062|      0|        }
 2063|      0|    }
 2064|       |
 2065|      0|    return VK_SUCCESS;
 2066|      0|}
loader_initialize:
 2298|      2|void loader_initialize(void) {
 2299|      2|    loader_platform_thread_create_mutex(&loader_lock);
 2300|      2|    loader_platform_thread_create_mutex(&loader_preload_icd_lock);
 2301|      2|    init_global_loader_settings();
 2302|      2|#endif
 2303|       |
 2304|       |    // initialize logging
 2305|      2|    loader_init_global_debug_level();
 2306|       |#if defined(_WIN32)
 2307|       |    windows_initialization();
 2308|       |#endif
 2309|       |
 2310|      2|    loader_api_version version = loader_make_full_version(VK_HEADER_VERSION_COMPLETE);
 2311|      2|    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", version.major, version.minor, version.patch);
 2312|       |
 2313|       |#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO)
 2314|       |    loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "[Vulkan Loader Git - Tag: " GIT_BRANCH_NAME ", Branch/Commit: " GIT_TAG_INFO "]");
 2315|       |#endif
 2316|       |
 2317|      2|    char *loader_disable_dynamic_library_unloading_env_var = loader_getenv("VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING", NULL);
 2318|      2|    if (loader_disable_dynamic_library_unloading_env_var &&
  ------------------
  |  Branch (2318:9): [True: 0, False: 2]
  ------------------
 2319|      0|        0 == strncmp(loader_disable_dynamic_library_unloading_env_var, "1", 2)) {
  ------------------
  |  Branch (2319:9): [True: 0, False: 0]
  ------------------
 2320|      0|        loader_disable_dynamic_library_unloading = true;
 2321|      0|        loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: library unloading is disabled");
 2322|      2|    } else {
 2323|      2|        loader_disable_dynamic_library_unloading = false;
 2324|      2|    }
 2325|      2|    loader_free_getenv(loader_disable_dynamic_library_unloading_env_var, NULL);
 2326|       |#if defined(LOADER_USE_UNSAFE_FILE_SEARCH)
 2327|       |    loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: unsafe searching is enabled");
 2328|       |#endif
 2329|       |#if defined(_WIN32)
 2330|       |    return TRUE;
 2331|       |#endif
 2332|      2|}
loader_init_library:
 2369|      2|__attribute__((constructor)) void loader_init_library(void) { loader_initialize(); }
loader_get_next_path:
 2380|   156k|char *loader_get_next_path(char *path) {
 2381|   156k|    uint32_t len;
 2382|   156k|    char *next;
 2383|       |
 2384|   156k|    if (path == NULL) return NULL;
  ------------------
  |  Branch (2384:9): [True: 0, False: 156k]
  ------------------
 2385|   156k|    next = strchr(path, PATH_SEPARATOR);
  ------------------
  |  |  150|   156k|#define PATH_SEPARATOR ':'
  ------------------
 2386|   156k|    if (next == NULL) {
  ------------------
  |  Branch (2386:9): [True: 36.4k, False: 119k]
  ------------------
 2387|  36.4k|        len = (uint32_t)strlen(path);
 2388|  36.4k|        next = path + len;
 2389|   119k|    } else {
 2390|   119k|        *next = '\0';
 2391|   119k|        next++;
 2392|   119k|    }
 2393|       |
 2394|   156k|    return next;
 2395|   156k|}
combine_manifest_directory_and_library_path:
 2405|  6.70k|                                                     const char *manifest_file_path, char **out_fullpath) {
 2406|  6.70k|    assert(library_path && manifest_file_path && out_fullpath);
 2407|  6.70k|    if (loader_platform_is_path_absolute(library_path)) {
  ------------------
  |  Branch (2407:9): [True: 371, False: 6.33k]
  ------------------
 2408|    371|        *out_fullpath = library_path;
 2409|    371|        return VK_SUCCESS;
 2410|    371|    }
 2411|  6.33k|    VkResult res = VK_SUCCESS;
 2412|       |
 2413|  6.33k|    size_t library_path_len = strlen(library_path);
 2414|  6.33k|    size_t manifest_file_path_str_len = strlen(manifest_file_path);
 2415|  6.33k|    bool library_path_contains_directory_symbol = false;
 2416|  90.4M|    for (size_t i = 0; i < library_path_len; i++) {
  ------------------
  |  Branch (2416:24): [True: 90.4M, False: 2.58k]
  ------------------
 2417|  90.4M|        if (library_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  151|  90.4M|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2417:13): [True: 3.75k, False: 90.4M]
  ------------------
 2418|  3.75k|            library_path_contains_directory_symbol = true;
 2419|  3.75k|            break;
 2420|  3.75k|        }
 2421|  90.4M|    }
 2422|       |    // Means that the library_path is neither absolute nor relative - thus we should not modify it at all
 2423|  6.33k|    if (!library_path_contains_directory_symbol) {
  ------------------
  |  Branch (2423:9): [True: 2.58k, False: 3.75k]
  ------------------
 2424|  2.58k|        *out_fullpath = library_path;
 2425|  2.58k|        return VK_SUCCESS;
 2426|  2.58k|    }
 2427|       |    // must include both a directory symbol and the null terminator
 2428|  3.75k|    size_t new_str_len = library_path_len + manifest_file_path_str_len + 1 + 1;
 2429|       |
 2430|  3.75k|    *out_fullpath = loader_instance_heap_calloc(inst, new_str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
 2431|  3.75k|    if (NULL == *out_fullpath) {
  ------------------
  |  Branch (2431:9): [True: 0, False: 3.75k]
  ------------------
 2432|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 2433|      0|        goto out;
 2434|      0|    }
 2435|  3.75k|    size_t cur_loc_in_out_fullpath = 0;
 2436|       |    // look for the last occurrence of DIRECTORY_SYMBOL in manifest_file_path
 2437|  3.75k|    size_t last_directory_symbol = 0;
 2438|  3.75k|    bool found_directory_symbol = false;
 2439|   104k|    for (size_t i = 0; i < manifest_file_path_str_len; i++) {
  ------------------
  |  Branch (2439:24): [True: 101k, False: 3.75k]
  ------------------
 2440|   101k|        if (manifest_file_path[i] == DIRECTORY_SYMBOL) {
  ------------------
  |  |  151|   101k|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (2440:13): [True: 2.39k, False: 98.7k]
  ------------------
 2441|  2.39k|            last_directory_symbol = i + 1;  // we want to include the symbol
 2442|  2.39k|            found_directory_symbol = true;
 2443|       |            // dont break because we want to find the last occurrence
 2444|  2.39k|        }
 2445|   101k|    }
 2446|       |    // Add manifest_file_path up to the last directory symbol
 2447|  3.75k|    if (found_directory_symbol) {
  ------------------
  |  Branch (2447:9): [True: 878, False: 2.87k]
  ------------------
 2448|    878|        loader_strncpy(*out_fullpath, new_str_len, manifest_file_path, last_directory_symbol);
 2449|    878|        cur_loc_in_out_fullpath += last_directory_symbol;
 2450|    878|    }
 2451|  3.75k|    loader_strncpy(&(*out_fullpath)[cur_loc_in_out_fullpath], new_str_len - cur_loc_in_out_fullpath, library_path,
 2452|  3.75k|                   library_path_len);
 2453|  3.75k|    cur_loc_in_out_fullpath += library_path_len + 1;
 2454|  3.75k|    (*out_fullpath)[cur_loc_in_out_fullpath] = '\0';
 2455|       |
 2456|  3.75k|out:
 2457|  3.75k|    loader_instance_heap_free(inst, library_path);
 2458|       |
 2459|  3.75k|    return res;
 2460|  3.75k|}
loader_get_fullpath:
 2466|  16.3k|void loader_get_fullpath(const char *file, const char *in_dirs, size_t out_size, char *out_fullpath) {
 2467|  16.3k|    if (!loader_platform_is_path(file) && *in_dirs) {
  ------------------
  |  Branch (2467:9): [True: 16.3k, False: 11]
  |  Branch (2467:43): [True: 16.3k, False: 0]
  ------------------
 2468|  16.3k|        size_t dirs_copy_len = strlen(in_dirs) + 1;
 2469|  16.3k|        char *dirs_copy = loader_stack_alloc(dirs_copy_len);
  ------------------
  |  |   42|  16.3k|#define loader_stack_alloc(size) alloca(size)
  ------------------
 2470|  16.3k|        loader_strncpy(dirs_copy, dirs_copy_len, in_dirs, dirs_copy_len);
 2471|       |
 2472|       |        // find if file exists after prepending paths in given list
 2473|       |        // for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); dir = next_dir) {
 2474|  16.3k|        char *dir = dirs_copy;
 2475|  16.3k|        char *next_dir = loader_get_next_path(dir);
 2476|  16.5k|        while (*dir && next_dir) {
  ------------------
  |  Branch (2476:16): [True: 16.3k, False: 190]
  |  Branch (2476:24): [True: 16.3k, False: 0]
  ------------------
 2477|  16.3k|            int path_concat_ret = snprintf(out_fullpath, out_size, "%s%c%s", dir, DIRECTORY_SYMBOL, file);
  ------------------
  |  |  151|  16.3k|#define DIRECTORY_SYMBOL '/'
  ------------------
 2478|  16.3k|            if (path_concat_ret < 0) {
  ------------------
  |  Branch (2478:17): [True: 0, False: 16.3k]
  ------------------
 2479|      0|                continue;
 2480|      0|            }
 2481|  16.3k|            if (loader_platform_file_exists(out_fullpath)) {
  ------------------
  |  Branch (2481:17): [True: 16.1k, False: 190]
  ------------------
 2482|  16.1k|                return;
 2483|  16.1k|            }
 2484|    190|            dir = next_dir;
 2485|    190|            next_dir = loader_get_next_path(dir);
 2486|    190|        }
 2487|  16.3k|    }
 2488|       |
 2489|    201|    (void)snprintf(out_fullpath, out_size, "%s", file);
 2490|    201|}
verify_meta_layer_component_layers:
 2496|  3.50k|                                        struct loader_layer_list *instance_layers, bool *already_checked_meta_layers) {
 2497|  3.50k|    struct loader_layer_properties *prop = &instance_layers->list[prop_index];
 2498|  3.50k|    loader_api_version meta_layer_version = loader_make_version(prop->info.specVersion);
 2499|       |
 2500|  3.50k|    if (NULL == already_checked_meta_layers) {
  ------------------
  |  Branch (2500:9): [True: 2.27k, False: 1.23k]
  ------------------
 2501|  2.27k|        already_checked_meta_layers = loader_stack_alloc(sizeof(bool) * instance_layers->count);
  ------------------
  |  |   42|  2.27k|#define loader_stack_alloc(size) alloca(size)
  ------------------
 2502|  2.27k|        if (already_checked_meta_layers == NULL) {
  ------------------
  |  Branch (2502:13): [True: 0, False: 2.27k]
  ------------------
 2503|      0|            return false;
 2504|      0|        }
 2505|  2.27k|        memset(already_checked_meta_layers, 0, sizeof(bool) * instance_layers->count);
 2506|  2.27k|    }
 2507|       |
 2508|       |    // Mark this meta layer as 'already checked', indicating which layers have already been recursed.
 2509|  3.50k|    already_checked_meta_layers[prop_index] = true;
 2510|       |
 2511|  7.07k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2511:35): [True: 4.99k, False: 2.07k]
  ------------------
 2512|  4.99k|        struct loader_layer_properties *comp_prop =
 2513|  4.99k|            loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers);
 2514|  4.99k|        if (comp_prop == NULL) {
  ------------------
  |  Branch (2514:13): [True: 555, False: 4.43k]
  ------------------
 2515|    555|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2516|    555|                       "verify_meta_layer_component_layers: Meta-layer %s can't find component layer %s at index %d."
 2517|    555|                       "  Skipping this layer.",
 2518|    555|                       prop->info.layerName, prop->component_layer_names.list[comp_layer], comp_layer);
 2519|       |
 2520|    555|            return false;
 2521|    555|        }
 2522|       |
 2523|       |        // Check the version of each layer, they need to be at least MAJOR and MINOR
 2524|  4.43k|        loader_api_version comp_prop_version = loader_make_version(comp_prop->info.specVersion);
 2525|  4.43k|        if (!loader_check_version_meets_required(meta_layer_version, comp_prop_version)) {
  ------------------
  |  Branch (2525:13): [True: 146, False: 4.29k]
  ------------------
 2526|    146|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2527|    146|                       "verify_meta_layer_component_layers: Meta-layer uses API version %d.%d, but component "
 2528|    146|                       "layer %d has API version %d.%d that is lower.  Skipping this layer.",
 2529|    146|                       meta_layer_version.major, meta_layer_version.minor, comp_layer, comp_prop_version.major,
 2530|    146|                       comp_prop_version.minor);
 2531|       |
 2532|    146|            return false;
 2533|    146|        }
 2534|       |
 2535|       |        // Make sure the layer isn't using it's own name
 2536|  4.29k|        if (!strcmp(prop->info.layerName, prop->component_layer_names.list[comp_layer])) {
  ------------------
  |  Branch (2536:13): [True: 106, False: 4.18k]
  ------------------
 2537|    106|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2538|    106|                       "verify_meta_layer_component_layers: Meta-layer %s lists itself in its component layer "
 2539|    106|                       "list at index %d.  Skipping this layer.",
 2540|    106|                       prop->info.layerName, comp_layer);
 2541|       |
 2542|    106|            return false;
 2543|    106|        }
 2544|  4.18k|        if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (2544:13): [True: 1.34k, False: 2.84k]
  ------------------
 2545|  1.34k|            size_t comp_prop_index = INT32_MAX;
 2546|       |            // Make sure we haven't verified this meta layer before
 2547|  37.7k|            for (uint32_t i = 0; i < instance_layers->count; i++) {
  ------------------
  |  Branch (2547:34): [True: 36.4k, False: 1.34k]
  ------------------
 2548|  36.4k|                if (strcmp(comp_prop->info.layerName, instance_layers->list[i].info.layerName) == 0) {
  ------------------
  |  Branch (2548:21): [True: 2.59k, False: 33.8k]
  ------------------
 2549|  2.59k|                    comp_prop_index = i;
 2550|  2.59k|                }
 2551|  36.4k|            }
 2552|  1.34k|            if (comp_prop_index != INT32_MAX && already_checked_meta_layers[comp_prop_index]) {
  ------------------
  |  Branch (2552:17): [True: 1.34k, False: 0]
  |  Branch (2552:49): [True: 111, False: 1.23k]
  ------------------
 2553|    111|                loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2554|    111|                           "verify_meta_layer_component_layers: Recursive dependency between Meta-layer %s and  Meta-layer %s.  "
 2555|    111|                           "Skipping this layer.",
 2556|    111|                           instance_layers->list[prop_index].info.layerName, comp_prop->info.layerName);
 2557|    111|                return false;
 2558|    111|            }
 2559|       |
 2560|  1.23k|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 2561|  1.23k|                       "verify_meta_layer_component_layers: Adding meta-layer %s which also contains meta-layer %s",
 2562|  1.23k|                       prop->info.layerName, comp_prop->info.layerName);
 2563|       |
 2564|       |            // Make sure if the layer is using a meta-layer in its component list that we also verify that.
 2565|  1.23k|            if (!verify_meta_layer_component_layers(inst, comp_prop_index, instance_layers, already_checked_meta_layers)) {
  ------------------
  |  Branch (2565:17): [True: 506, False: 727]
  ------------------
 2566|    506|                loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2567|    506|                           "Meta-layer %s component layer %s can not find all component layers."
 2568|    506|                           "  Skipping this layer.",
 2569|    506|                           prop->info.layerName, prop->component_layer_names.list[comp_layer]);
 2570|    506|                return false;
 2571|    506|            }
 2572|  1.23k|        }
 2573|  4.18k|    }
 2574|       |    // Didn't exit early so that means it passed all checks
 2575|  2.07k|    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2576|  2.07k|               "Meta-layer \"%s\" all %d component layers appear to be valid.", prop->info.layerName,
 2577|  2.07k|               prop->component_layer_names.count);
 2578|       |
 2579|       |    // If layer logging is on, list the internals included in the meta-layer
 2580|  5.62k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2580:35): [True: 3.54k, False: 2.07k]
  ------------------
 2581|  3.54k|        loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "  [%d] %s", comp_layer, prop->component_layer_names.list[comp_layer]);
 2582|  3.54k|    }
 2583|       |    return true;
 2584|  3.50k|}
update_meta_layer_extensions_from_component_layers:
 2589|  1.35k|                                                        struct loader_layer_list *instance_layers) {
 2590|  1.35k|    VkResult res = VK_SUCCESS;
 2591|  2.87k|    for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) {
  ------------------
  |  Branch (2591:35): [True: 1.51k, False: 1.35k]
  ------------------
 2592|  1.51k|        struct loader_layer_properties *comp_prop =
 2593|  1.51k|            loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers);
 2594|       |
 2595|  1.51k|        if (NULL != comp_prop->instance_extension_list.list) {
  ------------------
  |  Branch (2595:13): [True: 187, False: 1.33k]
  ------------------
 2596|  2.92k|            for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) {
  ------------------
  |  Branch (2596:36): [True: 2.73k, False: 187]
  ------------------
 2597|  2.73k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding instance extension %s",
 2598|  2.73k|                           prop->info.layerName, prop->component_layer_names.list[comp_layer],
 2599|  2.73k|                           comp_prop->instance_extension_list.list[ext].extensionName);
 2600|       |
 2601|  2.73k|                if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) {
  ------------------
  |  Branch (2601:21): [True: 2.61k, False: 119]
  ------------------
 2602|  2.61k|                    res = loader_add_to_ext_list(inst, &prop->instance_extension_list, 1,
 2603|  2.61k|                                                 &comp_prop->instance_extension_list.list[ext]);
 2604|  2.61k|                    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2604:25): [True: 0, False: 2.61k]
  ------------------
 2605|      0|                        return res;
 2606|      0|                    }
 2607|  2.61k|                }
 2608|  2.73k|            }
 2609|    187|        }
 2610|  1.51k|        if (NULL != comp_prop->device_extension_list.list) {
  ------------------
  |  Branch (2610:13): [True: 203, False: 1.31k]
  ------------------
 2611|  3.09k|            for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) {
  ------------------
  |  Branch (2611:36): [True: 2.88k, False: 203]
  ------------------
 2612|  2.88k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding device extension %s",
 2613|  2.88k|                           prop->info.layerName, prop->component_layer_names.list[comp_layer],
 2614|  2.88k|                           comp_prop->device_extension_list.list[ext].props.extensionName);
 2615|       |
 2616|  2.88k|                if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) {
  ------------------
  |  Branch (2616:21): [True: 2.54k, False: 346]
  ------------------
 2617|  2.54k|                    loader_add_to_dev_ext_list(inst, &prop->device_extension_list,
 2618|  2.54k|                                               &comp_prop->device_extension_list.list[ext].props, NULL);
 2619|  2.54k|                    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2619:25): [True: 0, False: 2.54k]
  ------------------
 2620|      0|                        return res;
 2621|      0|                    }
 2622|  2.54k|                }
 2623|  2.88k|            }
 2624|    203|        }
 2625|  1.51k|    }
 2626|  1.35k|    return res;
 2627|  1.35k|}
verify_all_meta_layers:
 2631|  4.97k|                                struct loader_layer_list *instance_layers, bool *override_layer_present) {
 2632|  4.97k|    VkResult res = VK_SUCCESS;
 2633|  4.97k|    *override_layer_present = false;
 2634|  37.4k|    for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
  ------------------
  |  Branch (2634:25): [True: 32.5k, False: 4.97k]
  ------------------
 2635|  32.5k|        struct loader_layer_properties *prop = &instance_layers->list[i];
 2636|       |
 2637|       |        // If this is a meta-layer, make sure it is valid
 2638|  32.5k|        if (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
  ------------------
  |  Branch (2638:13): [True: 2.27k, False: 30.2k]
  ------------------
 2639|  2.27k|            if (verify_meta_layer_component_layers(inst, i, instance_layers, NULL)) {
  ------------------
  |  Branch (2639:17): [True: 1.35k, False: 918]
  ------------------
 2640|       |                // If any meta layer is valid, update its extension list to include the extensions from its component layers.
 2641|  1.35k|                res = update_meta_layer_extensions_from_component_layers(inst, prop, instance_layers);
 2642|  1.35k|                if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (2642:21): [True: 0, False: 1.35k]
  ------------------
 2643|      0|                    return res;
 2644|      0|                }
 2645|  1.35k|                if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop)) {
  ------------------
  |  Branch (2645:21): [True: 174, False: 1.17k]
  |  Branch (2645:42): [True: 168, False: 6]
  ------------------
 2646|    168|                    *override_layer_present = true;
 2647|    168|                }
 2648|  1.35k|            } else {
 2649|    918|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
 2650|    918|                           "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName);
 2651|       |
 2652|    918|                loader_remove_layer_in_list(inst, instance_layers, i);
 2653|    918|                i--;
 2654|    918|            }
 2655|  2.27k|        }
 2656|  32.5k|    }
 2657|  4.97k|    return res;
 2658|  4.97k|}
remove_all_non_valid_override_layers:
 2662|  4.97k|void remove_all_non_valid_override_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
 2663|  4.97k|    if (instance_layers == NULL) {
  ------------------
  |  Branch (2663:9): [True: 0, False: 4.97k]
  ------------------
 2664|      0|        return;
 2665|      0|    }
 2666|       |
 2667|  4.97k|    char cur_path[1024];
 2668|  4.97k|    char *ret = loader_platform_executable_path(cur_path, 1024);
 2669|  4.97k|    if (NULL == ret) {
  ------------------
  |  Branch (2669:9): [True: 0, False: 4.97k]
  ------------------
 2670|      0|        return;
 2671|      0|    }
 2672|       |    // Find out if there is an override layer with same the app_key_path as the path to the current executable.
 2673|       |    // If more than one is found, remove it and use the first layer
 2674|       |    // Remove any layers which aren't global and do not have the same app_key_path as the path to the current executable.
 2675|  4.97k|    bool found_active_override_layer = false;
 2676|  4.97k|    int global_layer_index = -1;
 2677|  37.6k|    for (uint32_t i = 0; i < instance_layers->count; i++) {
  ------------------
  |  Branch (2677:26): [True: 32.6k, False: 4.97k]
  ------------------
 2678|  32.6k|        struct loader_layer_properties *props = &instance_layers->list[i];
 2679|  32.6k|        if (strcmp(props->info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) {
  ------------------
  |  |  138|  32.6k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (2679:13): [True: 724, False: 31.9k]
  ------------------
 2680|    724|            if (props->app_key_paths.count > 0) {  // not the global layer
  ------------------
  |  Branch (2680:17): [True: 138, False: 586]
  ------------------
 2681|    880|                for (uint32_t j = 0; j < props->app_key_paths.count; j++) {
  ------------------
  |  Branch (2681:38): [True: 742, False: 138]
  ------------------
 2682|    742|                    if (strcmp(props->app_key_paths.list[j], cur_path) == 0) {
  ------------------
  |  Branch (2682:25): [True: 0, False: 742]
  ------------------
 2683|      0|                        if (!found_active_override_layer) {
  ------------------
  |  Branch (2683:29): [True: 0, False: 0]
  ------------------
 2684|      0|                            found_active_override_layer = true;
 2685|      0|                        } else {
 2686|      0|                            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2687|      0|                                       "remove_all_non_valid_override_layers: Multiple override layers where the same path in "
 2688|      0|                                       "app_keys "
 2689|      0|                                       "was found. Using the first layer found");
 2690|       |
 2691|       |                            // Remove duplicate active override layers that have the same app_key_path
 2692|      0|                            loader_remove_layer_in_list(inst, instance_layers, i);
 2693|      0|                            i--;
 2694|      0|                        }
 2695|      0|                    }
 2696|    742|                }
 2697|    138|                if (!found_active_override_layer) {
  ------------------
  |  Branch (2697:21): [True: 138, False: 0]
  ------------------
 2698|    138|                    loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2699|    138|                               "--Override layer found but not used because app \'%s\' is not in \'app_keys\' list!", cur_path);
 2700|       |
 2701|       |                    // Remove non-global override layers that don't have an app_key that matches cur_path
 2702|    138|                    loader_remove_layer_in_list(inst, instance_layers, i);
 2703|    138|                    i--;
 2704|    138|                }
 2705|    586|            } else {
 2706|    586|                if (global_layer_index == -1) {
  ------------------
  |  Branch (2706:21): [True: 301, False: 285]
  ------------------
 2707|    301|                    global_layer_index = i;
 2708|    301|                } else {
 2709|    285|                    loader_log(
 2710|    285|                        inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2711|    285|                        "remove_all_non_valid_override_layers: Multiple global override layers found. Using the first global "
 2712|    285|                        "layer found");
 2713|    285|                    loader_remove_layer_in_list(inst, instance_layers, i);
 2714|    285|                    i--;
 2715|    285|                }
 2716|    586|            }
 2717|    724|        }
 2718|  32.6k|    }
 2719|       |    // Remove global layer if layer with same the app_key_path as the path to the current executable is found
 2720|  4.97k|    if (found_active_override_layer && global_layer_index >= 0) {
  ------------------
  |  Branch (2720:9): [True: 0, False: 4.97k]
  |  Branch (2720:40): [True: 0, False: 0]
  ------------------
 2721|      0|        loader_remove_layer_in_list(inst, instance_layers, global_layer_index);
 2722|      0|    }
 2723|       |    // Should be at most 1 override layer in the list now.
 2724|  4.97k|    if (found_active_override_layer) {
  ------------------
  |  Branch (2724:9): [True: 0, False: 4.97k]
  ------------------
 2725|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the override layer for app key %s", cur_path);
 2726|  4.97k|    } else if (global_layer_index >= 0) {
  ------------------
  |  Branch (2726:16): [True: 301, False: 4.67k]
  ------------------
 2727|    301|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the global override layer");
 2728|    301|    }
 2729|  4.97k|}
loader_read_layer_json:
 2743|   341k|                                cJSON *layer_node, loader_api_version version, bool is_implicit, char *filename) {
 2744|   341k|    assert(layer_instance_list);
 2745|   341k|    char *library_path = NULL;
 2746|   341k|    VkResult result = VK_SUCCESS;
 2747|   341k|    struct loader_layer_properties props = {0};
 2748|       |
 2749|   341k|    result = loader_copy_to_new_str(inst, filename, &props.manifest_file_name);
 2750|   341k|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2750:9): [True: 0, False: 341k]
  ------------------
 2751|      0|        goto out;
 2752|      0|    }
 2753|       |
 2754|       |    // Parse name
 2755|       |
 2756|   341k|    result = loader_parse_json_string_to_existing_str(layer_node, "name", VK_MAX_EXTENSION_NAME_SIZE, props.info.layerName);
 2757|   341k|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2757:9): [True: 75.6k, False: 265k]
  ------------------
 2758|  75.6k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2759|  75.6k|                   "Layer located at %s didn't find required layer value \"name\" in manifest JSON file, skipping this layer",
 2760|  75.6k|                   filename);
 2761|  75.6k|        goto out;
 2762|  75.6k|    }
 2763|       |
 2764|       |    // Check if this layer's name matches the override layer name, set is_override to true if so.
 2765|   265k|    if (!strcmp(props.info.layerName, VK_OVERRIDE_LAYER_NAME)) {
  ------------------
  |  |  138|   265k|#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
  ------------------
  |  Branch (2765:9): [True: 24.5k, False: 241k]
  ------------------
 2766|  24.5k|        props.is_override = true;
 2767|  24.5k|    }
 2768|       |
 2769|   265k|    if (0 != strncmp(props.info.layerName, "VK_LAYER_", 9)) {
  ------------------
  |  Branch (2769:9): [True: 223k, False: 42.2k]
  ------------------
 2770|   223k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Layer name %s does not conform to naming standard (Policy #LLP_LAYER_3)",
 2771|   223k|                   props.info.layerName);
 2772|   223k|    }
 2773|       |
 2774|       |    // Parse type
 2775|   265k|    char *type = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "type"));
 2776|   265k|    if (NULL == type) {
  ------------------
  |  Branch (2776:9): [True: 45.4k, False: 220k]
  ------------------
 2777|  45.4k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2778|  45.4k|                   "Layer located at %s didn't find required layer value \"type\" in manifest JSON file, skipping this layer",
 2779|  45.4k|                   filename);
 2780|  45.4k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2781|  45.4k|        goto out;
 2782|  45.4k|    }
 2783|       |
 2784|       |    // Add list entry
 2785|   220k|    if (!strcmp(type, "DEVICE")) {
  ------------------
  |  Branch (2785:9): [True: 135, False: 220k]
  ------------------
 2786|    135|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Device layers are deprecated. Skipping layer %s",
 2787|    135|                   props.info.layerName);
 2788|    135|        result = VK_ERROR_INITIALIZATION_FAILED;
 2789|    135|        goto out;
 2790|    135|    }
 2791|       |
 2792|       |    // Allow either GLOBAL or INSTANCE type interchangeably to handle layers that must work with older loaders
 2793|   220k|    if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
  ------------------
  |  Branch (2793:9): [True: 165k, False: 54.6k]
  |  Branch (2793:38): [True: 33.3k, False: 21.3k]
  ------------------
 2794|   198k|        props.type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER;
 2795|   198k|        if (!is_implicit) {
  ------------------
  |  Branch (2795:13): [True: 120k, False: 78.8k]
  ------------------
 2796|   120k|            props.type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER;
 2797|   120k|        }
 2798|   198k|    } else {
 2799|  21.3k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2800|  21.3k|        goto out;
 2801|  21.3k|    }
 2802|       |
 2803|       |    // Parse api_version
 2804|   198k|    char *api_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "api_version"));
 2805|   198k|    if (NULL == api_version) {
  ------------------
  |  Branch (2805:9): [True: 176k, False: 22.5k]
  ------------------
 2806|   176k|        loader_log(
 2807|   176k|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2808|   176k|            "Layer located at %s didn't find required layer value \"api_version\" in manifest JSON file, skipping this layer",
 2809|   176k|            filename);
 2810|   176k|        goto out;
 2811|   176k|    }
 2812|       |
 2813|  22.5k|    props.info.specVersion = loader_parse_version_string(api_version);
 2814|       |
 2815|       |    // Make sure the layer's manifest doesn't contain a non zero variant value
 2816|  22.5k|    if (VK_API_VERSION_VARIANT(props.info.specVersion) != 0) {
  ------------------
  |  Branch (2816:9): [True: 2.13k, False: 20.4k]
  ------------------
 2817|  2.13k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 2818|  2.13k|                   "Layer \"%s\" has an \'api_version\' field which contains a non-zero variant value of %d. "
 2819|  2.13k|                   " Skipping Layer.",
 2820|  2.13k|                   props.info.layerName, VK_API_VERSION_VARIANT(props.info.specVersion));
 2821|  2.13k|        result = VK_ERROR_INITIALIZATION_FAILED;
 2822|  2.13k|        goto out;
 2823|  2.13k|    }
 2824|       |
 2825|       |    // Parse implementation_version
 2826|  20.4k|    char *implementation_version = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "implementation_version"));
 2827|  20.4k|    if (NULL == implementation_version) {
  ------------------
  |  Branch (2827:9): [True: 3.04k, False: 17.3k]
  ------------------
 2828|  3.04k|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2829|  3.04k|                   "Layer located at %s didn't find required layer value \"implementation_version\" in manifest JSON file, "
 2830|  3.04k|                   "skipping this layer",
 2831|  3.04k|                   filename);
 2832|  3.04k|        goto out;
 2833|  3.04k|    }
 2834|  17.3k|    props.info.implementationVersion = atoi(implementation_version);
 2835|       |
 2836|       |    // Parse description
 2837|       |
 2838|  17.3k|    result = loader_parse_json_string_to_existing_str(layer_node, "description", VK_MAX_DESCRIPTION_SIZE, props.info.description);
 2839|  17.3k|    if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2839:9): [True: 480, False: 16.9k]
  ------------------
 2840|    480|        loader_log(
 2841|    480|            inst, VULKAN_LOADER_WARN_BIT, 0,
 2842|    480|            "Layer located at %s didn't find required layer value \"description\" in manifest JSON file, skipping this layer",
 2843|    480|            filename);
 2844|    480|        goto out;
 2845|    480|    }
 2846|       |
 2847|       |    // Parse library_path
 2848|       |
 2849|       |    // Library path no longer required unless component_layers is also not defined
 2850|  16.9k|    result = loader_parse_json_string(layer_node, "library_path", &library_path);
 2851|  16.9k|    if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (2851:9): [True: 0, False: 16.9k]
  ------------------
 2852|      0|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2853|      0|                   "Skipping layer \"%s\" due to problem accessing the library_path value in the manifest JSON file",
 2854|      0|                   props.info.layerName);
 2855|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
 2856|      0|        goto out;
 2857|      0|    }
 2858|  16.9k|    if (NULL != library_path) {
  ------------------
  |  Branch (2858:9): [True: 6.76k, False: 10.1k]
  ------------------
 2859|  6.76k|        if (NULL != loader_cJSON_GetObjectItem(layer_node, "component_layers")) {
  ------------------
  |  Branch (2859:13): [True: 61, False: 6.70k]
  ------------------
 2860|     61|            loader_log(
 2861|     61|                inst, VULKAN_LOADER_WARN_BIT, 0,
 2862|     61|                "Layer \"%s\" contains meta-layer-specific component_layers, but also defining layer library path.  Both are not "
 2863|     61|                "compatible, so skipping this layer",
 2864|     61|                props.info.layerName);
 2865|     61|            result = VK_ERROR_INITIALIZATION_FAILED;
 2866|     61|            loader_instance_heap_free(inst, library_path);
 2867|     61|            goto out;
 2868|     61|        }
 2869|       |
 2870|       |        // This function takes ownership of library_path_str - so we don't need to clean it up
 2871|  6.70k|        result = combine_manifest_directory_and_library_path(inst, library_path, filename, &props.lib_name);
 2872|  6.70k|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2872:13): [True: 0, False: 6.70k]
  ------------------
 2873|  6.70k|    }
 2874|       |
 2875|       |    // Parse component_layers
 2876|       |
 2877|  16.8k|    if (NULL == library_path) {
  ------------------
  |  Branch (2877:9): [True: 10.1k, False: 6.70k]
  ------------------
 2878|  10.1k|        if (!loader_check_version_meets_required(LOADER_VERSION_1_1_0, version)) {
  ------------------
  |  |  261|  10.1k|#define LOADER_VERSION_1_1_0 loader_combine_version(1, 1, 0)
  ------------------
  |  Branch (2878:13): [True: 5.66k, False: 4.47k]
  ------------------
 2879|  5.66k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2880|  5.66k|                       "Layer \"%s\" contains meta-layer-specific component_layers, but using older JSON file version.",
 2881|  5.66k|                       props.info.layerName);
 2882|  5.66k|        }
 2883|       |
 2884|  10.1k|        result = loader_parse_json_array_of_strings(inst, layer_node, "component_layers", &(props.component_layer_names));
 2885|  10.1k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2885:13): [True: 0, False: 10.1k]
  ------------------
 2886|      0|            goto out;
 2887|      0|        }
 2888|  10.1k|        if (VK_ERROR_INITIALIZATION_FAILED == result) {
  ------------------
  |  Branch (2888:13): [True: 1.96k, False: 8.17k]
  ------------------
 2889|  1.96k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2890|  1.96k|                       "Layer \"%s\" is missing both library_path and component_layers fields.  One or the other MUST be defined.  "
 2891|  1.96k|                       "Skipping this layer",
 2892|  1.96k|                       props.info.layerName);
 2893|  1.96k|            goto out;
 2894|  1.96k|        }
 2895|       |        // This is now, officially, a meta-layer
 2896|  8.17k|        props.type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
 2897|  8.17k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Encountered meta-layer \"%s\"",
 2898|  8.17k|                   props.info.layerName);
 2899|  8.17k|    }
 2900|       |
 2901|       |    // Parse blacklisted_layers
 2902|       |
 2903|  14.8k|    if (props.is_override) {
  ------------------
  |  Branch (2903:9): [True: 981, False: 13.9k]
  ------------------
 2904|    981|        result = loader_parse_json_array_of_strings(inst, layer_node, "blacklisted_layers", &(props.blacklist_layer_names));
 2905|    981|        if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2905:13): [True: 0, False: 981]
  ------------------
 2906|      0|            goto out;
 2907|      0|        }
 2908|    981|    }
 2909|       |
 2910|       |    // Parse override_paths
 2911|       |
 2912|  14.8k|    result = loader_parse_json_array_of_strings(inst, layer_node, "override_paths", &(props.override_paths));
 2913|  14.8k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == result) {
  ------------------
  |  Branch (2913:9): [True: 0, False: 14.8k]
  ------------------
 2914|      0|        goto out;
 2915|      0|    }
 2916|  14.8k|    if (NULL != props.override_paths.list && !loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2916:9): [True: 90, False: 14.7k]
  |  Branch (2916:46): [True: 69, False: 21]
  ------------------
 2917|     69|        loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2918|     69|                   "Layer \"%s\" contains meta-layer-specific override paths, but using older JSON file version.",
 2919|     69|                   props.info.layerName);
 2920|     69|    }
 2921|       |
 2922|       |    // Parse disable_environment
 2923|       |
 2924|  14.8k|    if (is_implicit) {
  ------------------
  |  Branch (2924:9): [True: 5.57k, False: 9.31k]
  ------------------
 2925|  5.57k|        cJSON *disable_environment = loader_cJSON_GetObjectItem(layer_node, "disable_environment");
 2926|  5.57k|        if (disable_environment == NULL) {
  ------------------
  |  Branch (2926:13): [True: 356, False: 5.21k]
  ------------------
 2927|    356|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2928|    356|                       "Layer \"%s\" doesn't contain required layer object disable_environment in the manifest JSON file, skipping "
 2929|    356|                       "this layer",
 2930|    356|                       props.info.layerName);
 2931|    356|            result = VK_ERROR_INITIALIZATION_FAILED;
 2932|    356|            goto out;
 2933|    356|        }
 2934|       |
 2935|  5.21k|        if (!disable_environment->child || disable_environment->child->type != cJSON_String ||
  ------------------
  |  |  101|  10.0k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (2935:13): [True: 361, False: 4.85k]
  |  Branch (2935:44): [True: 31, False: 4.82k]
  ------------------
 2936|  4.82k|            !disable_environment->child->string || !disable_environment->child->valuestring) {
  ------------------
  |  Branch (2936:13): [True: 583, False: 4.24k]
  |  Branch (2936:52): [True: 0, False: 4.24k]
  ------------------
 2937|    975|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 2938|    975|                       "Layer \"%s\" doesn't contain required child value in object disable_environment in the manifest JSON file, "
 2939|    975|                       "skipping this layer (Policy #LLP_LAYER_9)",
 2940|    975|                       props.info.layerName);
 2941|    975|            result = VK_ERROR_INITIALIZATION_FAILED;
 2942|    975|            goto out;
 2943|    975|        }
 2944|  4.24k|        result = loader_copy_to_new_str(inst, disable_environment->child->string, &(props.disable_env_var.name));
 2945|  4.24k|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (2945:13): [True: 0, False: 4.24k]
  ------------------
 2946|  4.24k|        result = loader_copy_to_new_str(inst, disable_environment->child->valuestring, &(props.disable_env_var.value));
 2947|  4.24k|        if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (2947:13): [True: 0, False: 4.24k]
  ------------------
 2948|  4.24k|    }
 2949|       |
 2950|       |    // Now get all optional items and objects and put in list:
 2951|       |    // functions
 2952|       |    // instance_extensions
 2953|       |    // device_extensions
 2954|       |    // enable_environment (implicit layers only)
 2955|       |    // library_arch
 2956|       |
 2957|       |    // Layer interface functions
 2958|       |    //    vkGetInstanceProcAddr
 2959|       |    //    vkGetDeviceProcAddr
 2960|       |    //    vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
 2961|  13.5k|    cJSON *functions = loader_cJSON_GetObjectItem(layer_node, "functions");
 2962|  13.5k|    if (functions != NULL) {
  ------------------
  |  Branch (2962:9): [True: 28, False: 13.5k]
  ------------------
 2963|     28|        if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2963:13): [True: 26, False: 2]
  ------------------
 2964|     26|            result = loader_parse_json_string(functions, "vkNegotiateLoaderLayerInterfaceVersion",
 2965|     26|                                              &props.functions.str_negotiate_interface);
 2966|     26|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2966:17): [True: 0, False: 26]
  ------------------
 2967|     26|        }
 2968|     28|        result = loader_parse_json_string(functions, "vkGetInstanceProcAddr", &props.functions.str_gipa);
 2969|     28|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2969:13): [True: 0, False: 28]
  ------------------
 2970|       |
 2971|     28|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gipa &&
  ------------------
  |  Branch (2971:13): [True: 28, False: 0]
  |  Branch (2971:64): [True: 0, False: 28]
  ------------------
 2972|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2972:13): [True: 0, False: 0]
  ------------------
 2973|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 2974|      0|                       "Layer \"%s\" using deprecated \'vkGetInstanceProcAddr\' tag which was deprecated starting with JSON "
 2975|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 2976|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 2977|      0|                       props.info.layerName);
 2978|      0|        }
 2979|       |
 2980|     28|        result = loader_parse_json_string(functions, "vkGetDeviceProcAddr", &props.functions.str_gdpa);
 2981|     28|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (2981:13): [True: 0, False: 28]
  ------------------
 2982|       |
 2983|     28|        if (NULL == props.functions.str_negotiate_interface && props.functions.str_gdpa &&
  ------------------
  |  Branch (2983:13): [True: 28, False: 0]
  |  Branch (2983:64): [True: 0, False: 28]
  ------------------
 2984|      0|            loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
  ------------------
  |  Branch (2984:13): [True: 0, False: 0]
  ------------------
 2985|      0|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 2986|      0|                       "Layer \"%s\" using deprecated \'vkGetDeviceProcAddr\' tag which was deprecated starting with JSON "
 2987|      0|                       "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
 2988|      0|                       "compatibility reasons it may be desirable to continue using the deprecated tag.",
 2989|      0|                       props.info.layerName);
 2990|      0|        }
 2991|     28|    }
 2992|       |
 2993|       |    // instance_extensions
 2994|       |    //   array of {
 2995|       |    //     name
 2996|       |    //     spec_version
 2997|       |    //   }
 2998|       |
 2999|  13.5k|    cJSON *instance_extensions = loader_cJSON_GetObjectItem(layer_node, "instance_extensions");
 3000|  13.5k|    if (instance_extensions != NULL && instance_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|  2.14k|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3000:9): [True: 2.14k, False: 11.4k]
  |  Branch (3000:40): [True: 987, False: 1.16k]
  ------------------
 3001|    987|        cJSON *ext_item = NULL;
 3002|  15.6k|        cJSON_ArrayForEach(ext_item, instance_extensions) {
  ------------------
  |  |  213|  16.6k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 987, False: 0]
  |  |  |  Branch (213:61): [True: 15.6k, False: 987]
  |  |  ------------------
  ------------------
 3003|  15.6k|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|  15.6k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3003:17): [True: 1.23k, False: 14.4k]
  ------------------
 3004|  1.23k|                continue;
 3005|  1.23k|            }
 3006|       |
 3007|  14.4k|            VkExtensionProperties ext_prop = {0};
 3008|  14.4k|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3009|  14.4k|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3009:17): [True: 3.56k, False: 10.8k]
  ------------------
 3010|  3.56k|                continue;
 3011|  3.56k|            }
 3012|  10.8k|            char *spec_version = NULL;
 3013|  10.8k|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3014|  10.8k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3014:17): [True: 0, False: 10.8k]
  ------------------
 3015|  10.8k|            if (NULL != spec_version) {
  ------------------
  |  Branch (3015:17): [True: 235, False: 10.6k]
  ------------------
 3016|    235|                ext_prop.specVersion = atoi(spec_version);
 3017|    235|            }
 3018|  10.8k|            loader_instance_heap_free(inst, spec_version);
 3019|  10.8k|            bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop);
 3020|  10.8k|            if (!ext_unsupported) {
  ------------------
  |  Branch (3020:17): [True: 10.6k, False: 190]
  ------------------
 3021|  10.6k|                loader_add_to_ext_list(inst, &props.instance_extension_list, 1, &ext_prop);
 3022|  10.6k|            }
 3023|  10.8k|        }
 3024|    987|    }
 3025|       |
 3026|       |    // device_extensions
 3027|       |    //   array of {
 3028|       |    //     name
 3029|       |    //     spec_version
 3030|       |    //     entrypoints
 3031|       |    //   }
 3032|  13.5k|    cJSON *device_extensions = loader_cJSON_GetObjectItem(layer_node, "device_extensions");
 3033|  13.5k|    if (device_extensions != NULL && device_extensions->type == cJSON_Array) {
  ------------------
  |  |  102|  1.41k|#define cJSON_Array (1 << 5)
  ------------------
  |  Branch (3033:9): [True: 1.41k, False: 12.1k]
  |  Branch (3033:38): [True: 956, False: 459]
  ------------------
 3034|    956|        cJSON *ext_item = NULL;
 3035|  10.4k|        cJSON_ArrayForEach(ext_item, device_extensions) {
  ------------------
  |  |  213|  11.4k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 956, False: 0]
  |  |  |  Branch (213:61): [True: 10.4k, False: 956]
  |  |  ------------------
  ------------------
 3036|  10.4k|            if (ext_item->type != cJSON_Object) {
  ------------------
  |  |  103|  10.4k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3036:17): [True: 1.70k, False: 8.75k]
  ------------------
 3037|  1.70k|                continue;
 3038|  1.70k|            }
 3039|       |
 3040|  8.75k|            VkExtensionProperties ext_prop = {0};
 3041|  8.75k|            result = loader_parse_json_string_to_existing_str(ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, ext_prop.extensionName);
 3042|  8.75k|            if (result == VK_ERROR_INITIALIZATION_FAILED) {
  ------------------
  |  Branch (3042:17): [True: 1.79k, False: 6.95k]
  ------------------
 3043|  1.79k|                continue;
 3044|  1.79k|            }
 3045|       |
 3046|  6.95k|            char *spec_version = NULL;
 3047|  6.95k|            result = loader_parse_json_string(ext_item, "spec_version", &spec_version);
 3048|  6.95k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3048:17): [True: 0, False: 6.95k]
  ------------------
 3049|  6.95k|            if (NULL != spec_version) {
  ------------------
  |  Branch (3049:17): [True: 770, False: 6.18k]
  ------------------
 3050|    770|                ext_prop.specVersion = atoi(spec_version);
 3051|    770|            }
 3052|  6.95k|            loader_instance_heap_free(inst, spec_version);
 3053|       |
 3054|  6.95k|            cJSON *entrypoints = loader_cJSON_GetObjectItem(ext_item, "entrypoints");
 3055|  6.95k|            if (entrypoints == NULL) {
  ------------------
  |  Branch (3055:17): [True: 4.72k, False: 2.23k]
  ------------------
 3056|  4.72k|                result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, NULL);
 3057|  4.72k|                if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3057:21): [True: 0, False: 4.72k]
  ------------------
 3058|  4.72k|                continue;
 3059|  4.72k|            }
 3060|       |
 3061|  2.23k|            struct loader_string_list entrys = {0};
 3062|  2.23k|            result = loader_parse_json_array_of_strings(inst, ext_item, "entrypoints", &entrys);
 3063|  2.23k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3063:17): [True: 0, False: 2.23k]
  ------------------
 3064|  2.23k|            result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, &entrys);
 3065|  2.23k|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3065:17): [True: 0, False: 2.23k]
  ------------------
 3066|  2.23k|        }
 3067|    956|    }
 3068|  13.5k|    if (is_implicit) {
  ------------------
  |  Branch (3068:9): [True: 4.24k, False: 9.31k]
  ------------------
 3069|  4.24k|        cJSON *enable_environment = loader_cJSON_GetObjectItem(layer_node, "enable_environment");
 3070|       |
 3071|       |        // enable_environment is optional
 3072|  4.24k|        if (enable_environment && enable_environment->child && enable_environment->child->type == cJSON_String &&
  ------------------
  |  |  101|  4.96k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (3072:13): [True: 1.69k, False: 2.54k]
  |  Branch (3072:35): [True: 722, False: 977]
  |  Branch (3072:64): [True: 353, False: 369]
  ------------------
 3073|    353|            enable_environment->child->string && enable_environment->child->valuestring) {
  ------------------
  |  Branch (3073:13): [True: 284, False: 69]
  |  Branch (3073:50): [True: 284, False: 0]
  ------------------
 3074|    284|            result = loader_copy_to_new_str(inst, enable_environment->child->string, &(props.enable_env_var.name));
 3075|    284|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3075:17): [True: 0, False: 284]
  ------------------
 3076|    284|            result = loader_copy_to_new_str(inst, enable_environment->child->valuestring, &(props.enable_env_var.value));
 3077|    284|            if (VK_SUCCESS != result) goto out;
  ------------------
  |  Branch (3077:17): [True: 0, False: 284]
  ------------------
 3078|    284|        }
 3079|  4.24k|    }
 3080|       |
 3081|       |    // Read in the pre-instance stuff
 3082|  13.5k|    cJSON *pre_instance = loader_cJSON_GetObjectItem(layer_node, "pre_instance_functions");
 3083|  13.5k|    if (NULL != pre_instance) {
  ------------------
  |  Branch (3083:9): [True: 33, False: 13.5k]
  ------------------
 3084|       |        // Supported versions started in 1.1.2, so anything newer
 3085|     33|        if (!loader_check_version_meets_required(loader_combine_version(1, 1, 2), version)) {
  ------------------
  |  Branch (3085:13): [True: 16, False: 17]
  ------------------
 3086|     16|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3087|     16|                       "Found pre_instance_functions section in layer from \"%s\". This section is only valid in manifest version "
 3088|     16|                       "1.1.2 or later. The section will be ignored",
 3089|     16|                       filename);
 3090|     17|        } else if (!is_implicit) {
  ------------------
  |  Branch (3090:20): [True: 0, False: 17]
  ------------------
 3091|      0|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
 3092|      0|                       "Found pre_instance_functions section in explicit layer from \"%s\". This section is only valid in implicit "
 3093|      0|                       "layers. The section will be ignored",
 3094|      0|                       filename);
 3095|     17|        } else {
 3096|     17|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceExtensionProperties",
 3097|     17|                                              &props.pre_instance_functions.enumerate_instance_extension_properties);
 3098|     17|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3098:17): [True: 0, False: 17]
  ------------------
 3099|       |
 3100|     17|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceLayerProperties",
 3101|     17|                                              &props.pre_instance_functions.enumerate_instance_layer_properties);
 3102|     17|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3102:17): [True: 0, False: 17]
  ------------------
 3103|       |
 3104|     17|            result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceVersion",
 3105|     17|                                              &props.pre_instance_functions.enumerate_instance_version);
 3106|     17|            if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3106:17): [True: 0, False: 17]
  ------------------
 3107|     17|        }
 3108|     33|    }
 3109|       |
 3110|  13.5k|    if (loader_cJSON_GetObjectItem(layer_node, "app_keys")) {
  ------------------
  |  Branch (3110:9): [True: 1.39k, False: 12.1k]
  ------------------
 3111|  1.39k|        if (!props.is_override) {
  ------------------
  |  Branch (3111:13): [True: 946, False: 451]
  ------------------
 3112|    946|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3113|    946|                       "Layer %s contains app_keys, but any app_keys can only be provided by the override meta layer. "
 3114|    946|                       "These will be ignored.",
 3115|    946|                       props.info.layerName);
 3116|    946|        }
 3117|       |
 3118|  1.39k|        result = loader_parse_json_array_of_strings(inst, layer_node, "app_keys", &props.app_key_paths);
 3119|  1.39k|        if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
  ------------------
  |  Branch (3119:13): [True: 0, False: 1.39k]
  ------------------
 3120|  1.39k|    }
 3121|       |
 3122|  13.5k|    char *library_arch = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(layer_node, "library_arch"));
 3123|  13.5k|    if (NULL != library_arch) {
  ------------------
  |  Branch (3123:9): [True: 23, False: 13.5k]
  ------------------
 3124|     23|        if ((strncmp(library_arch, "32", 2) == 0 && sizeof(void *) != 4) ||
  ------------------
  |  Branch (3124:14): [True: 15, False: 8]
  |  Branch (3124:53): [True: 0, Folded]
  ------------------
 3125|     15|            (strncmp(library_arch, "64", 2) == 0 && sizeof(void *) != 8)) {
  ------------------
  |  Branch (3125:14): [True: 0, False: 8]
  |  Branch (3125:53): [Folded, False: 0]
  ------------------
 3126|     15|            loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
 3127|     15|                       "The library architecture in layer %s doesn't match the current running architecture, skipping this layer",
 3128|     15|                       filename);
 3129|     15|            result = VK_ERROR_INITIALIZATION_FAILED;
 3130|     15|            goto out;
 3131|     15|        }
 3132|     23|    }
 3133|       |
 3134|  13.5k|    result = VK_SUCCESS;
 3135|       |
 3136|   341k|out:
 3137|       |    // Try to append the layer property
 3138|   341k|    if (VK_SUCCESS == result) {
  ------------------
  |  Branch (3138:9): [True: 192k, False: 148k]
  ------------------
 3139|   192k|        result = loader_append_layer_property(inst, layer_instance_list, &props);
 3140|   192k|    }
 3141|       |    // If appending fails - free all the memory allocated in it
 3142|   341k|    if (VK_SUCCESS != result) {
  ------------------
  |  Branch (3142:9): [True: 148k, False: 192k]
  ------------------
 3143|   148k|        loader_free_layer_properties(inst, &props);
 3144|   148k|    }
 3145|   341k|    return result;
 3146|  13.5k|}
is_valid_layer_json_version:
 3148|  8.14k|bool is_valid_layer_json_version(const loader_api_version *layer_json) {
 3149|       |    // Supported versions are: 1.0.0, 1.0.1, 1.1.0 - 1.1.2, and 1.2.0 - 1.2.1.
 3150|  8.14k|    if ((layer_json->major == 1 && layer_json->minor == 2 && layer_json->patch < 2) ||
  ------------------
  |  Branch (3150:10): [True: 2.18k, False: 5.96k]
  |  Branch (3150:36): [True: 241, False: 1.93k]
  |  Branch (3150:62): [True: 90, False: 151]
  ------------------
 3151|  8.05k|        (layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) ||
  ------------------
  |  Branch (3151:10): [True: 2.09k, False: 5.96k]
  |  Branch (3151:36): [True: 246, False: 1.84k]
  |  Branch (3151:62): [True: 146, False: 100]
  ------------------
 3152|  7.91k|        (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
  ------------------
  |  Branch (3152:10): [True: 1.94k, False: 5.96k]
  |  Branch (3152:36): [True: 1.53k, False: 406]
  |  Branch (3152:62): [True: 1.05k, False: 488]
  ------------------
 3153|  1.28k|        return true;
 3154|  1.28k|    }
 3155|  6.86k|    return false;
 3156|  8.14k|}
loader_add_layer_properties:
 3168|  8.82k|                                     bool is_implicit, char *filename) {
 3169|       |    // The following Fields in layer manifest file that are required:
 3170|       |    //   - "file_format_version"
 3171|       |    //   - If more than one "layer" object are used, then the "layers" array is
 3172|       |    //     required
 3173|  8.82k|    VkResult result = VK_ERROR_INITIALIZATION_FAILED;
 3174|       |    // Make sure sure the top level json value is an object
 3175|  8.82k|    if (!json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  8.82k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3175:9): [True: 0, False: 8.82k]
  |  Branch (3175:18): [True: 587, False: 8.23k]
  ------------------
 3176|    587|        goto out;
 3177|    587|    }
 3178|  8.23k|    char *file_vers = loader_cJSON_GetStringValue(loader_cJSON_GetObjectItem(json, "file_format_version"));
 3179|  8.23k|    if (NULL == file_vers) {
  ------------------
  |  Branch (3179:9): [True: 88, False: 8.14k]
  ------------------
 3180|     88|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3181|     88|                   "loader_add_layer_properties: Manifest %s missing required field file_format_version", filename);
 3182|     88|        goto out;
 3183|     88|    }
 3184|       |
 3185|  8.14k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Found manifest file %s (file version %s)", filename, file_vers);
 3186|       |    // Get the major/minor/and patch as integers for easier comparison
 3187|  8.14k|    loader_api_version json_version = loader_make_full_version(loader_parse_version_string(file_vers));
 3188|       |
 3189|  8.14k|    if (!is_valid_layer_json_version(&json_version)) {
  ------------------
  |  Branch (3189:9): [True: 6.86k, False: 1.28k]
  ------------------
 3190|  6.86k|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3191|  6.86k|                   "loader_add_layer_properties: %s has unknown layer manifest file version %d.%d.%d.  May cause errors.", filename,
 3192|  6.86k|                   json_version.major, json_version.minor, json_version.patch);
 3193|  6.86k|    }
 3194|       |
 3195|       |    // If "layers" is present, read in the array of layer objects
 3196|  8.14k|    cJSON *layers_node = loader_cJSON_GetObjectItem(json, "layers");
 3197|  8.14k|    if (layers_node != NULL) {
  ------------------
  |  Branch (3197:9): [True: 6.87k, False: 1.27k]
  ------------------
 3198|       |        // Supported versions started in 1.0.1, so anything newer
 3199|  6.87k|        if (!loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3199:13): [True: 4.15k, False: 2.72k]
  ------------------
 3200|  4.15k|            loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3201|  4.15k|                       "loader_add_layer_properties: \'layers\' tag not supported until file version 1.0.1, but %s is reporting "
 3202|  4.15k|                       "version %s",
 3203|  4.15k|                       filename, file_vers);
 3204|  4.15k|        }
 3205|  6.87k|        cJSON *layer_node = NULL;
 3206|   338k|        cJSON_ArrayForEach(layer_node, layers_node) {
  ------------------
  |  |  213|   344k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 6.87k, False: 0]
  |  |  |  Branch (213:61): [True: 338k, False: 5.85k]
  |  |  ------------------
  ------------------
 3207|   338k|            if (layer_node->type != cJSON_Object) {
  ------------------
  |  |  103|   338k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (3207:17): [True: 1.02k, False: 337k]
  ------------------
 3208|  1.02k|                loader_log(
 3209|  1.02k|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3210|  1.02k|                    "loader_add_layer_properties: Array element in \"layers\" field in manifest JSON file %s is not an object.  "
 3211|  1.02k|                    "Skipping this file",
 3212|  1.02k|                    filename);
 3213|  1.02k|                goto out;
 3214|  1.02k|            }
 3215|   337k|            result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3216|   337k|        }
 3217|  6.87k|    } else {
 3218|       |        // Otherwise, try to read in individual layers
 3219|  1.27k|        cJSON *layer_node = loader_cJSON_GetObjectItem(json, "layer");
 3220|  1.27k|        if (layer_node == NULL) {
  ------------------
  |  Branch (3220:13): [True: 529, False: 747]
  ------------------
 3221|       |            // Don't warn if this happens to be an ICD manifest
 3222|    529|            if (loader_cJSON_GetObjectItem(json, "ICD") == NULL) {
  ------------------
  |  Branch (3222:17): [True: 492, False: 37]
  ------------------
 3223|    492|                loader_log(
 3224|    492|                    inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3225|    492|                    "loader_add_layer_properties: Can not find 'layer' object in manifest JSON file %s.  Skipping this file.",
 3226|    492|                    filename);
 3227|    492|            }
 3228|    529|            goto out;
 3229|    529|        }
 3230|       |        // Loop through all "layer" objects in the file to get a count of them
 3231|       |        // first.
 3232|    747|        uint16_t layer_count = 0;
 3233|    747|        cJSON *tempNode = layer_node;
 3234|  5.18k|        do {
 3235|  5.18k|            tempNode = tempNode->next;
 3236|  5.18k|            layer_count++;
 3237|  5.18k|        } while (tempNode != NULL);
  ------------------
  |  Branch (3237:18): [True: 4.44k, False: 747]
  ------------------
 3238|       |
 3239|       |        // Throw a warning if we encounter multiple "layer" objects in file
 3240|       |        // versions newer than 1.0.0.  Having multiple objects with the same
 3241|       |        // name at the same level is actually a JSON standard violation.
 3242|    747|        if (layer_count > 1 && loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
  ------------------
  |  Branch (3242:13): [True: 672, False: 75]
  |  Branch (3242:32): [True: 347, False: 325]
  ------------------
 3243|    347|            loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3244|    347|                       "loader_add_layer_properties: Multiple 'layer' nodes are deprecated starting in file version \"1.0.1\".  "
 3245|    347|                       "Please use 'layers' : [] array instead in %s.",
 3246|    347|                       filename);
 3247|    400|        } else {
 3248|  4.24k|            do {
 3249|  4.24k|                result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename);
 3250|  4.24k|                layer_node = layer_node->next;
 3251|  4.24k|            } while (layer_node != NULL);
  ------------------
  |  Branch (3251:22): [True: 3.84k, False: 400]
  ------------------
 3252|    400|        }
 3253|    747|    }
 3254|       |
 3255|  8.82k|out:
 3256|       |
 3257|  8.82k|    return result;
 3258|  8.14k|}
determine_data_file_path_size:
 3260|  59.9k|size_t determine_data_file_path_size(const char *cur_path, size_t relative_path_size) {
 3261|  59.9k|    size_t path_size = 0;
 3262|       |
 3263|  59.9k|    if (NULL != cur_path) {
  ------------------
  |  Branch (3263:9): [True: 59.9k, False: 0]
  ------------------
 3264|       |        // For each folder in cur_path, (detected by finding additional
 3265|       |        // path separators in the string) we need to add the relative path on
 3266|       |        // the end.  Plus, leave an additional two slots on the end to add an
 3267|       |        // additional directory slash and path separator if needed
 3268|  59.9k|        path_size += strlen(cur_path) + relative_path_size + 2;
 3269|  1.45M|        for (const char *x = cur_path; *x; ++x) {
  ------------------
  |  Branch (3269:40): [True: 1.39M, False: 59.9k]
  ------------------
 3270|  1.39M|            if (*x == PATH_SEPARATOR) {
  ------------------
  |  |  150|  1.39M|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3270:17): [True: 10.2k, False: 1.38M]
  ------------------
 3271|  10.2k|                path_size += relative_path_size + 2;
 3272|  10.2k|            }
 3273|  1.39M|        }
 3274|  59.9k|    }
 3275|       |
 3276|  59.9k|    return path_size;
 3277|  59.9k|}
copy_data_file_info:
 3279|  59.9k|void copy_data_file_info(const char *cur_path, const char *relative_path, size_t relative_path_size, char **output_path) {
 3280|  59.9k|    if (NULL != cur_path) {
  ------------------
  |  Branch (3280:9): [True: 59.9k, False: 0]
  ------------------
 3281|  59.9k|        uint32_t start = 0;
 3282|  59.9k|        uint32_t stop = 0;
 3283|  59.9k|        char *cur_write = *output_path;
 3284|       |
 3285|   130k|        while (cur_path[start] != '\0') {
  ------------------
  |  Branch (3285:16): [True: 70.1k, False: 59.9k]
  ------------------
 3286|  80.4k|            while (cur_path[start] == PATH_SEPARATOR && cur_path[start] != '\0') {
  ------------------
  |  |  150|   160k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3286:20): [True: 10.2k, False: 70.1k]
  |  Branch (3286:57): [True: 10.2k, False: 0]
  ------------------
 3287|  10.2k|                start++;
 3288|  10.2k|            }
 3289|  70.1k|            stop = start;
 3290|  1.45M|            while (cur_path[stop] != PATH_SEPARATOR && cur_path[stop] != '\0') {
  ------------------
  |  |  150|  2.90M|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3290:20): [True: 1.44M, False: 10.2k]
  |  Branch (3290:56): [True: 1.38M, False: 59.9k]
  ------------------
 3291|  1.38M|                stop++;
 3292|  1.38M|            }
 3293|  70.1k|            const size_t s = stop - start;
 3294|  70.1k|            if (s) {
  ------------------
  |  Branch (3294:17): [True: 70.1k, False: 25]
  ------------------
 3295|  70.1k|                memcpy(cur_write, &cur_path[start], s);
 3296|  70.1k|                cur_write += s;
 3297|       |
 3298|       |                // If this is a specific JSON file, just add it and don't add any
 3299|       |                // relative path or directory symbol to it.
 3300|  70.1k|                if (!is_json(cur_write - 5, s)) {
  ------------------
  |  Branch (3300:21): [True: 69.9k, False: 207]
  ------------------
 3301|       |                    // Add the relative directory if present.
 3302|  69.9k|                    if (relative_path_size > 0) {
  ------------------
  |  Branch (3302:25): [True: 69.3k, False: 531]
  ------------------
 3303|       |                        // If last symbol written was not a directory symbol, add it.
 3304|  69.3k|                        if (*(cur_write - 1) != DIRECTORY_SYMBOL) {
  ------------------
  |  |  151|  69.3k|#define DIRECTORY_SYMBOL '/'
  ------------------
  |  Branch (3304:29): [True: 69.3k, False: 0]
  ------------------
 3305|  69.3k|                            *cur_write++ = DIRECTORY_SYMBOL;
  ------------------
  |  |  151|  69.3k|#define DIRECTORY_SYMBOL '/'
  ------------------
 3306|  69.3k|                        }
 3307|  69.3k|                        memcpy(cur_write, relative_path, relative_path_size);
 3308|  69.3k|                        cur_write += relative_path_size;
 3309|  69.3k|                    }
 3310|  69.9k|                }
 3311|       |
 3312|  70.1k|                *cur_write++ = PATH_SEPARATOR;
  ------------------
  |  |  150|  70.1k|#define PATH_SEPARATOR ':'
  ------------------
 3313|  70.1k|                start = stop;
 3314|  70.1k|            }
 3315|  70.1k|        }
 3316|  59.9k|        *output_path = cur_write;
 3317|  59.9k|    }
 3318|  59.9k|}
add_if_manifest_file:
 3321|  16.3k|VkResult add_if_manifest_file(const struct loader_instance *inst, const char *file_name, struct loader_string_list *out_files) {
 3322|  16.3k|    assert(NULL != file_name && "add_if_manifest_file: Received NULL pointer for file_name");
 3323|  16.3k|    assert(NULL != out_files && "add_if_manifest_file: Received NULL pointer for out_files");
 3324|       |
 3325|       |    // Look for files ending with ".json" suffix
 3326|  16.3k|    size_t name_len = strlen(file_name);
 3327|  16.3k|    const char *name_suffix = file_name + name_len - 5;
 3328|  16.3k|    if (!is_json(name_suffix, name_len)) {
  ------------------
  |  Branch (3328:9): [True: 11.8k, False: 4.51k]
  ------------------
 3329|       |        // Use incomplete to indicate invalid name, but to keep going.
 3330|  11.8k|        return VK_INCOMPLETE;
 3331|  11.8k|    }
 3332|       |
 3333|  4.51k|    return copy_str_to_string_list(inst, out_files, file_name, name_len);
 3334|  16.3k|}
add_data_files:
 3354|  9.97k|VkResult add_data_files(const struct loader_instance *inst, char *search_path, struct loader_string_list *out_files) {
 3355|  9.97k|    VkResult vk_result = VK_SUCCESS;
 3356|  9.97k|    char full_path[2048];
 3357|  9.97k|#if !defined(_WIN32)
 3358|  9.97k|    char temp_path[2048];
 3359|  9.97k|#endif
 3360|       |
 3361|       |    // Now, parse the paths
 3362|  9.97k|    char *next_file = search_path;
 3363|  79.8k|    while (NULL != next_file && *next_file != '\0') {
  ------------------
  |  Branch (3363:12): [True: 79.8k, False: 0]
  |  Branch (3363:33): [True: 69.9k, False: 9.97k]
  ------------------
 3364|  69.9k|        char *name = NULL;
 3365|  69.9k|        char *cur_file = next_file;
 3366|  69.9k|        next_file = loader_get_next_path(cur_file);
 3367|       |
 3368|       |        // Is this a JSON file, then try to open it.
 3369|  69.9k|        size_t len = strlen(cur_file);
 3370|  69.9k|        if (is_json(cur_file + len - 5, len)) {
  ------------------
  |  Branch (3370:13): [True: 200, False: 69.7k]
  ------------------
 3371|       |#if defined(_WIN32)
 3372|       |            name = cur_file;
 3373|       |#elif COMMON_UNIX_PLATFORMS
 3374|       |            // Only Linux has relative paths, make a copy of location so it isn't modified
 3375|    200|            size_t str_len;
 3376|    200|            if (NULL != next_file) {
  ------------------
  |  Branch (3376:17): [True: 200, False: 0]
  ------------------
 3377|    200|                str_len = next_file - cur_file + 1;
 3378|    200|            } else {
 3379|      0|                str_len = strlen(cur_file) + 1;
 3380|      0|            }
 3381|    200|            if (str_len > sizeof(temp_path)) {
  ------------------
  |  Branch (3381:17): [True: 7, False: 193]
  ------------------
 3382|      7|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "add_data_files: Path to %s too long", cur_file);
 3383|      7|                continue;
 3384|      7|            }
 3385|    193|            strncpy(temp_path, cur_file, str_len);
 3386|    193|            name = temp_path;
 3387|       |#else
 3388|       |#warning add_data_files must define relative path copy for this platform
 3389|       |#endif
 3390|    193|            loader_get_fullpath(cur_file, name, sizeof(full_path), full_path);
 3391|    193|            name = full_path;
 3392|       |
 3393|    193|            VkResult local_res;
 3394|    193|            local_res = add_if_manifest_file(inst, name, out_files);
 3395|       |
 3396|       |            // Incomplete means this was not a valid data file.
 3397|    193|            if (local_res == VK_INCOMPLETE) {
  ------------------
  |  Branch (3397:17): [True: 0, False: 193]
  ------------------
 3398|      0|                continue;
 3399|    193|            } else if (local_res != VK_SUCCESS) {
  ------------------
  |  Branch (3399:24): [True: 0, False: 193]
  ------------------
 3400|      0|                vk_result = local_res;
 3401|      0|                break;
 3402|      0|            }
 3403|  69.7k|        } else {  // Otherwise, treat it as a directory
 3404|  69.7k|            DIR *dir_stream = loader_opendir(inst, cur_file);
 3405|  69.7k|            if (NULL == dir_stream) {
  ------------------
  |  Branch (3405:17): [True: 64.6k, False: 5.02k]
  ------------------
 3406|  64.6k|                continue;
 3407|  64.6k|            }
 3408|  21.2k|            while (1) {
  ------------------
  |  Branch (3408:20): [True: 21.2k, Folded]
  ------------------
 3409|  21.2k|                errno = 0;
 3410|  21.2k|                struct dirent *dir_entry = readdir(dir_stream);
 3411|  21.2k|#if !defined(WIN32)  // Windows doesn't use readdir, don't check errors on functions which aren't called
 3412|  21.2k|                if (errno != 0) {
  ------------------
  |  Branch (3412:21): [True: 0, False: 21.2k]
  ------------------
 3413|      0|                    loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "readdir failed with %d: %s", errno, strerror(errno));
 3414|      0|                    break;
 3415|      0|                }
 3416|  21.2k|#endif
 3417|  21.2k|                if (NULL == dir_entry) {
  ------------------
  |  Branch (3417:21): [True: 5.02k, False: 16.1k]
  ------------------
 3418|  5.02k|                    break;
 3419|  5.02k|                }
 3420|       |
 3421|  16.1k|                name = &(dir_entry->d_name[0]);
 3422|  16.1k|                loader_get_fullpath(name, cur_file, sizeof(full_path), full_path);
 3423|  16.1k|                name = full_path;
 3424|       |
 3425|  16.1k|                VkResult local_res;
 3426|  16.1k|                local_res = add_if_manifest_file(inst, name, out_files);
 3427|       |
 3428|       |                // Incomplete means this was not a valid data file.
 3429|  16.1k|                if (local_res == VK_INCOMPLETE) {
  ------------------
  |  Branch (3429:21): [True: 11.8k, False: 4.32k]
  ------------------
 3430|  11.8k|                    continue;
 3431|  11.8k|                } else if (local_res != VK_SUCCESS) {
  ------------------
  |  Branch (3431:28): [True: 0, False: 4.32k]
  ------------------
 3432|      0|                    vk_result = local_res;
 3433|      0|                    break;
 3434|      0|                }
 3435|  16.1k|            }
 3436|  5.02k|            loader_closedir(inst, dir_stream);
 3437|  5.02k|            if (vk_result != VK_SUCCESS) {
  ------------------
  |  Branch (3437:17): [True: 0, False: 5.02k]
  ------------------
 3438|      0|                goto out;
 3439|      0|            }
 3440|  5.02k|        }
 3441|  69.9k|    }
 3442|       |
 3443|  9.97k|out:
 3444|       |
 3445|  9.97k|    return vk_result;
 3446|  9.97k|}
read_data_files_in_search_paths:
 3451|  9.97k|                                         const char *path_override, bool *override_active, struct loader_string_list *out_files) {
 3452|  9.97k|    VkResult vk_result = VK_SUCCESS;
 3453|  9.97k|    char *override_env = NULL;
 3454|  9.97k|    const char *override_path = NULL;
 3455|  9.97k|    char *additional_env = NULL;
 3456|  9.97k|    size_t search_path_size = 0;
 3457|  9.97k|    char *search_path = NULL;
 3458|  9.97k|    char *cur_path_ptr = NULL;
 3459|  9.97k|#if COMMON_UNIX_PLATFORMS
 3460|  9.97k|    const char *relative_location = NULL;  // Only used on unix platforms
 3461|  9.97k|    size_t rel_size = 0;                   // unused in windows, dont declare so no compiler warnings are generated
 3462|  9.97k|#endif
 3463|       |
 3464|       |#if defined(_WIN32)
 3465|       |    char *package_path = NULL;
 3466|       |#elif COMMON_UNIX_PLATFORMS
 3467|       |    // Determine how much space is needed to generate the full search path
 3468|       |    // for the current manifest files.
 3469|  9.97k|    char *xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
 3470|  9.97k|    char *xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
 3471|       |
 3472|  9.97k|#if !defined(__Fuchsia__) && !defined(__QNX__)
 3473|  9.97k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (3473:9): [True: 9.97k, False: 0]
  |  Branch (3473:36): [True: 0, False: 0]
  ------------------
 3474|  9.97k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
 3475|  9.97k|    }
 3476|  9.97k|#endif
 3477|       |
 3478|  9.97k|    char *xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
 3479|  9.97k|    char *xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
 3480|       |
 3481|  9.97k|#if !defined(__Fuchsia__) && !defined(__QNX__)
 3482|  9.97k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (3482:9): [True: 9.97k, False: 0]
  |  Branch (3482:34): [True: 0, False: 0]
  ------------------
 3483|  9.97k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
 3484|  9.97k|    }
 3485|  9.97k|#endif
 3486|       |
 3487|  9.97k|    char *home = NULL;
 3488|  9.97k|    char *default_data_home = NULL;
 3489|  9.97k|    char *default_config_home = NULL;
 3490|  9.97k|    char *home_data_dir = NULL;
 3491|  9.97k|    char *home_config_dir = NULL;
 3492|       |
 3493|       |    // Only use HOME if XDG_DATA_HOME is not present on the system
 3494|  9.97k|    home = loader_secure_getenv("HOME", inst);
 3495|  9.97k|    if (home != NULL) {
  ------------------
  |  Branch (3495:9): [True: 9.97k, False: 0]
  ------------------
 3496|  9.97k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (3496:13): [True: 9.97k, False: 0]
  |  Branch (3496:40): [True: 0, False: 0]
  ------------------
 3497|  9.97k|            const char config_suffix[] = "/.config";
 3498|  9.97k|            size_t default_config_home_len = strlen(home) + sizeof(config_suffix) + 1;
 3499|  9.97k|            default_config_home = loader_instance_heap_calloc(inst, default_config_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3500|  9.97k|            if (default_config_home == NULL) {
  ------------------
  |  Branch (3500:17): [True: 0, False: 9.97k]
  ------------------
 3501|      0|                vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3502|      0|                goto out;
 3503|      0|            }
 3504|  9.97k|            strncpy(default_config_home, home, default_config_home_len);
 3505|  9.97k|            strncat(default_config_home, config_suffix, default_config_home_len);
 3506|  9.97k|        }
 3507|  9.97k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (3507:13): [True: 9.97k, False: 0]
  |  Branch (3507:38): [True: 0, False: 0]
  ------------------
 3508|  9.97k|            const char data_suffix[] = "/.local/share";
 3509|  9.97k|            size_t default_data_home_len = strlen(home) + sizeof(data_suffix) + 1;
 3510|  9.97k|            default_data_home = loader_instance_heap_calloc(inst, default_data_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3511|  9.97k|            if (default_data_home == NULL) {
  ------------------
  |  Branch (3511:17): [True: 0, False: 9.97k]
  ------------------
 3512|      0|                vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3513|      0|                goto out;
 3514|      0|            }
 3515|  9.97k|            strncpy(default_data_home, home, default_data_home_len);
 3516|  9.97k|            strncat(default_data_home, data_suffix, default_data_home_len);
 3517|  9.97k|        }
 3518|  9.97k|    }
 3519|       |
 3520|  9.97k|    if (NULL != default_config_home) {
  ------------------
  |  Branch (3520:9): [True: 9.97k, False: 0]
  ------------------
 3521|  9.97k|        home_config_dir = default_config_home;
 3522|  9.97k|    } else {
 3523|      0|        home_config_dir = xdg_config_home;
 3524|      0|    }
 3525|  9.97k|    if (NULL != default_data_home) {
  ------------------
  |  Branch (3525:9): [True: 9.97k, False: 0]
  ------------------
 3526|  9.97k|        home_data_dir = default_data_home;
 3527|  9.97k|    } else {
 3528|      0|        home_data_dir = xdg_data_home;
 3529|      0|    }
 3530|       |#else
 3531|       |#warning read_data_files_in_search_paths unsupported platform
 3532|       |#endif
 3533|       |
 3534|  9.97k|    switch (manifest_type) {
 3535|     17|        case LOADER_DATA_FILE_MANIFEST_DRIVER:
  ------------------
  |  Branch (3535:9): [True: 17, False: 9.95k]
  ------------------
 3536|     17|            if (loader_settings_should_use_driver_environment_variables(inst)) {
  ------------------
  |  Branch (3536:17): [True: 17, False: 0]
  ------------------
 3537|     17|                override_env = loader_secure_getenv(VK_DRIVER_FILES_ENV_VAR, inst);
  ------------------
  |  |  113|     17|#define VK_DRIVER_FILES_ENV_VAR "VK_DRIVER_FILES"
  ------------------
 3538|     17|                if (NULL == override_env) {
  ------------------
  |  Branch (3538:21): [True: 17, False: 0]
  ------------------
 3539|       |                    // Not there, so fall back to the old name
 3540|     17|                    override_env = loader_secure_getenv(VK_ICD_FILENAMES_ENV_VAR, inst);
  ------------------
  |  |  112|     17|#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES"  // Deprecated in v1.3.207 loader
  ------------------
 3541|     17|                }
 3542|     17|                additional_env = loader_secure_getenv(VK_ADDITIONAL_DRIVER_FILES_ENV_VAR, inst);
  ------------------
  |  |  116|     17|#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
  ------------------
 3543|     17|            }
 3544|     17|#if COMMON_UNIX_PLATFORMS
 3545|     17|            relative_location = VK_DRIVERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  161|     17|#define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
  |  |  ------------------
  |  |  |  |  153|     17|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_DRIVERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ICDCONF_DIR
  |  |  ------------------
  |  |  |  |  154|     17|#define VULKAN_ICDCONF_DIR "icd.d"
  |  |  ------------------
  ------------------
 3546|     17|#endif
 3547|       |#if defined(_WIN32)
 3548|       |            package_path = windows_get_app_package_manifest_path(inst);
 3549|       |#endif
 3550|     17|            break;
 3551|  4.97k|        case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER:
  ------------------
  |  Branch (3551:9): [True: 4.97k, False: 4.99k]
  ------------------
 3552|  4.97k|            override_env = loader_secure_getenv(VK_IMPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  130|  4.97k|#define VK_IMPLICIT_LAYER_PATH_ENV_VAR "VK_IMPLICIT_LAYER_PATH"
  ------------------
 3553|  4.97k|            additional_env = loader_secure_getenv(VK_ADDITIONAL_IMPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  131|  4.97k|#define VK_ADDITIONAL_IMPLICIT_LAYER_PATH_ENV_VAR "VK_ADD_IMPLICIT_LAYER_PATH"
  ------------------
 3554|  4.97k|#if COMMON_UNIX_PLATFORMS
 3555|  4.97k|            relative_location = VK_ILAYERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  164|  4.97k|#define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  153|  4.97k|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  158|  4.97k|#define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
  |  |  ------------------
  ------------------
 3556|  4.97k|#endif
 3557|       |#if defined(_WIN32)
 3558|       |            package_path = windows_get_app_package_manifest_path(inst);
 3559|       |#endif
 3560|  4.97k|            break;
 3561|  4.97k|        case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER:
  ------------------
  |  Branch (3561:9): [True: 4.97k, False: 4.99k]
  ------------------
 3562|  4.97k|            override_env = loader_secure_getenv(VK_EXPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  114|  4.97k|#define VK_EXPLICIT_LAYER_PATH_ENV_VAR "VK_LAYER_PATH"
  ------------------
 3563|  4.97k|            additional_env = loader_secure_getenv(VK_ADDITIONAL_EXPLICIT_LAYER_PATH_ENV_VAR, inst);
  ------------------
  |  |  117|  4.97k|#define VK_ADDITIONAL_EXPLICIT_LAYER_PATH_ENV_VAR "VK_ADD_LAYER_PATH"
  ------------------
 3564|  4.97k|#if COMMON_UNIX_PLATFORMS
 3565|  4.97k|            relative_location = VK_ELAYERS_INFO_RELATIVE_DIR;
  ------------------
  |  |  163|  4.97k|#define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  153|  4.97k|#define VULKAN_DIR "vulkan/"
  |  |  ------------------
  |  |               #define VK_ELAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
  |  |  ------------------
  |  |  |  |  157|  4.97k|#define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
  |  |  ------------------
  ------------------
 3566|  4.97k|#endif
 3567|  4.97k|            break;
 3568|      0|        default:
  ------------------
  |  Branch (3568:9): [True: 0, False: 9.97k]
  ------------------
 3569|      0|            assert(false && "Shouldn't get here!");
 3570|      0|            break;
 3571|  9.97k|    }
 3572|       |
 3573|       |    // Log a message when VK_LAYER_PATH is set but the override layer paths take priority
 3574|  9.97k|    if (manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER && NULL != override_env && NULL != path_override) {
  ------------------
  |  Branch (3574:9): [True: 4.97k, False: 4.99k]
  |  Branch (3574:70): [True: 0, False: 4.97k]
  |  Branch (3574:94): [True: 0, False: 0]
  ------------------
 3575|      0|        loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
 3576|      0|                   "Ignoring VK_LAYER_PATH. The Override layer is active and has override paths set, which takes priority. "
 3577|      0|                   "VK_LAYER_PATH is set to %s",
 3578|      0|                   override_env);
 3579|      0|    }
 3580|       |
 3581|  9.97k|    if (path_override != NULL) {
  ------------------
  |  Branch (3581:9): [True: 57, False: 9.91k]
  ------------------
 3582|     57|        override_path = path_override;
 3583|  9.91k|    } else if (override_env != NULL) {
  ------------------
  |  Branch (3583:16): [True: 0, False: 9.91k]
  ------------------
 3584|      0|        override_path = override_env;
 3585|      0|    }
 3586|       |
 3587|       |    // Add two by default for NULL terminator and one path separator on end (just in case)
 3588|  9.97k|    search_path_size = 2;
 3589|       |
 3590|       |    // If there's an override, use that (and the local folder if required) and nothing else
 3591|  9.97k|    if (NULL != override_path) {
  ------------------
  |  Branch (3591:9): [True: 57, False: 9.91k]
  ------------------
 3592|       |        // Local folder and null terminator
 3593|     57|        search_path_size += strlen(override_path) + 2;
 3594|  9.91k|    } else {
 3595|       |        // Add the size of any additional search paths defined in the additive environment variable
 3596|  9.91k|        if (NULL != additional_env) {
  ------------------
  |  Branch (3596:13): [True: 0, False: 9.91k]
  ------------------
 3597|      0|            search_path_size += determine_data_file_path_size(additional_env, 0) + 2;
 3598|       |#if defined(_WIN32)
 3599|       |        }
 3600|       |        if (NULL != package_path) {
 3601|       |            search_path_size += determine_data_file_path_size(package_path, 0) + 2;
 3602|       |        }
 3603|       |        if (search_path_size == 2) {
 3604|       |            goto out;
 3605|       |        }
 3606|       |#elif COMMON_UNIX_PLATFORMS
 3607|       |        }
 3608|       |
 3609|       |        // Add the general search folders (with the appropriate relative folder added)
 3610|  9.91k|        rel_size = strlen(relative_location);
 3611|  9.91k|        if (rel_size > 0) {
  ------------------
  |  Branch (3611:13): [True: 9.91k, False: 0]
  ------------------
 3612|       |#if defined(__APPLE__)
 3613|       |            search_path_size += MAXPATHLEN;
 3614|       |#endif
 3615|       |            // Only add the home folders if defined
 3616|  9.91k|            if (NULL != home_config_dir) {
  ------------------
  |  Branch (3616:17): [True: 9.91k, False: 0]
  ------------------
 3617|  9.91k|                search_path_size += determine_data_file_path_size(home_config_dir, rel_size);
 3618|  9.91k|            }
 3619|  9.91k|            search_path_size += determine_data_file_path_size(xdg_config_dirs, rel_size);
 3620|  9.91k|            search_path_size += determine_data_file_path_size(SYSCONFDIR, rel_size);
 3621|  9.91k|#if defined(EXTRASYSCONFDIR)
 3622|  9.91k|            search_path_size += determine_data_file_path_size(EXTRASYSCONFDIR, rel_size);
 3623|  9.91k|#endif
 3624|       |            // Only add the home folders if defined
 3625|  9.91k|            if (NULL != home_data_dir) {
  ------------------
  |  Branch (3625:17): [True: 9.91k, False: 0]
  ------------------
 3626|  9.91k|                search_path_size += determine_data_file_path_size(home_data_dir, rel_size);
 3627|  9.91k|            }
 3628|  9.91k|            search_path_size += determine_data_file_path_size(xdg_data_dirs, rel_size);
 3629|  9.91k|        }
 3630|       |#else
 3631|       |#warning read_data_files_in_search_paths unsupported platform
 3632|       |#endif
 3633|  9.91k|    }
 3634|       |
 3635|       |    // Allocate the required space
 3636|  9.97k|    search_path = loader_instance_heap_calloc(inst, search_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3637|  9.97k|    if (NULL == search_path) {
  ------------------
  |  Branch (3637:9): [True: 0, False: 9.97k]
  ------------------
 3638|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 3639|      0|                   "read_data_files_in_search_paths: Failed to allocate space for search path of length %d",
 3640|      0|                   (uint32_t)search_path_size);
 3641|      0|        vk_result = VK_ERROR_OUT_OF_HOST_MEMORY;
 3642|      0|        goto out;
 3643|      0|    }
 3644|       |
 3645|  9.97k|    cur_path_ptr = search_path;
 3646|       |
 3647|       |    // Add the remaining paths to the list
 3648|  9.97k|    if (NULL != override_path) {
  ------------------
  |  Branch (3648:9): [True: 57, False: 9.91k]
  ------------------
 3649|     57|        size_t override_path_len = strlen(override_path);
 3650|     57|        loader_strncpy(cur_path_ptr, search_path_size, override_path, override_path_len);
 3651|     57|        cur_path_ptr += override_path_len;
 3652|  9.91k|    } else {
 3653|       |        // Add any additional search paths defined in the additive environment variable
 3654|  9.91k|        if (NULL != additional_env) {
  ------------------
  |  Branch (3654:13): [True: 0, False: 9.91k]
  ------------------
 3655|      0|            copy_data_file_info(additional_env, NULL, 0, &cur_path_ptr);
 3656|      0|        }
 3657|       |
 3658|       |#if defined(_WIN32)
 3659|       |        if (NULL != package_path) {
 3660|       |            copy_data_file_info(package_path, NULL, 0, &cur_path_ptr);
 3661|       |        }
 3662|       |#elif COMMON_UNIX_PLATFORMS
 3663|  9.91k|        if (rel_size > 0) {
  ------------------
  |  Branch (3663:13): [True: 9.91k, False: 0]
  ------------------
 3664|       |#if defined(__APPLE__)
 3665|       |            // Add the bundle's Resources dir to the beginning of the search path.
 3666|       |            // Looks for manifests in the bundle first, before any system directories.
 3667|       |            // This also appears to work unmodified for iOS, it finds the app bundle on the devices
 3668|       |            // file system. (RSW)
 3669|       |            CFBundleRef main_bundle = CFBundleGetMainBundle();
 3670|       |            if (NULL != main_bundle) {
 3671|       |                CFURLRef ref = CFBundleCopyResourcesDirectoryURL(main_bundle);
 3672|       |                if (NULL != ref) {
 3673|       |                    if (CFURLGetFileSystemRepresentation(ref, TRUE, (UInt8 *)cur_path_ptr, search_path_size)) {
 3674|       |                        cur_path_ptr += strlen(cur_path_ptr);
 3675|       |                        *cur_path_ptr++ = DIRECTORY_SYMBOL;
 3676|       |                        memcpy(cur_path_ptr, relative_location, rel_size);
 3677|       |                        cur_path_ptr += rel_size;
 3678|       |                        *cur_path_ptr++ = PATH_SEPARATOR;
 3679|       |                    }
 3680|       |                    CFRelease(ref);
 3681|       |                }
 3682|       |            }
 3683|       |#endif  // __APPLE__
 3684|       |
 3685|       |            // Only add the home folders if not NULL
 3686|  9.91k|            if (NULL != home_config_dir) {
  ------------------
  |  Branch (3686:17): [True: 9.91k, False: 0]
  ------------------
 3687|  9.91k|                copy_data_file_info(home_config_dir, relative_location, rel_size, &cur_path_ptr);
 3688|  9.91k|            }
 3689|  9.91k|            copy_data_file_info(xdg_config_dirs, relative_location, rel_size, &cur_path_ptr);
 3690|  9.91k|            copy_data_file_info(SYSCONFDIR, relative_location, rel_size, &cur_path_ptr);
 3691|  9.91k|#if defined(EXTRASYSCONFDIR)
 3692|  9.91k|            copy_data_file_info(EXTRASYSCONFDIR, relative_location, rel_size, &cur_path_ptr);
 3693|  9.91k|#endif
 3694|       |
 3695|       |            // Only add the home folders if not NULL
 3696|  9.91k|            if (NULL != home_data_dir) {
  ------------------
  |  Branch (3696:17): [True: 9.91k, False: 0]
  ------------------
 3697|  9.91k|                copy_data_file_info(home_data_dir, relative_location, rel_size, &cur_path_ptr);
 3698|  9.91k|            }
 3699|  9.91k|            copy_data_file_info(xdg_data_dirs, relative_location, rel_size, &cur_path_ptr);
 3700|  9.91k|        }
 3701|       |
 3702|       |        // Remove the last path separator
 3703|  9.91k|        --cur_path_ptr;
 3704|       |
 3705|  9.91k|        assert(cur_path_ptr - search_path < (ptrdiff_t)search_path_size);
 3706|  9.91k|        *cur_path_ptr = '\0';
 3707|       |#else
 3708|       |#warning read_data_files_in_search_paths unsupported platform
 3709|       |#endif
 3710|  9.91k|    }
 3711|       |
 3712|       |    // Remove duplicate paths, or it would result in duplicate extensions, duplicate devices, etc.
 3713|       |    // This uses minimal memory, but is O(N^2) on the number of paths. Expect only a few paths.
 3714|  9.97k|    char path_sep_str[2] = {PATH_SEPARATOR, '\0'};
  ------------------
  |  |  150|  9.97k|#define PATH_SEPARATOR ':'
  ------------------
 3715|  9.97k|    size_t search_path_updated_size = strlen(search_path);
 3716|  79.8k|    for (size_t first = 0; first < search_path_updated_size;) {
  ------------------
  |  Branch (3716:28): [True: 69.9k, False: 9.97k]
  ------------------
 3717|       |        // If this is an empty path, erase it
 3718|  69.9k|        if (search_path[first] == PATH_SEPARATOR) {
  ------------------
  |  |  150|  69.9k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3718:13): [True: 0, False: 69.9k]
  ------------------
 3719|      0|            memmove(&search_path[first], &search_path[first + 1], search_path_updated_size - first + 1);
 3720|      0|            search_path_updated_size -= 1;
 3721|      0|            continue;
 3722|      0|        }
 3723|       |
 3724|  69.9k|        size_t first_end = first + 1;
 3725|  69.9k|        first_end += strcspn(&search_path[first_end], path_sep_str);
 3726|   285k|        for (size_t second = first_end + 1; second < search_path_updated_size;) {
  ------------------
  |  Branch (3726:45): [True: 215k, False: 69.9k]
  ------------------
 3727|   215k|            size_t second_end = second + 1;
 3728|   215k|            second_end += strcspn(&search_path[second_end], path_sep_str);
 3729|   215k|            if (first_end - first == second_end - second &&
  ------------------
  |  Branch (3729:17): [True: 1.21k, False: 214k]
  ------------------
 3730|  1.21k|                !strncmp(&search_path[first], &search_path[second], second_end - second)) {
  ------------------
  |  Branch (3730:17): [True: 215, False: 995]
  ------------------
 3731|       |                // Found duplicate. Include PATH_SEPARATOR in second_end, then erase it from search_path.
 3732|    215|                if (search_path[second_end] == PATH_SEPARATOR) {
  ------------------
  |  |  150|    215|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (3732:21): [True: 210, False: 5]
  ------------------
 3733|    210|                    second_end++;
 3734|    210|                }
 3735|    215|                memmove(&search_path[second], &search_path[second_end], search_path_updated_size - second_end + 1);
 3736|    215|                search_path_updated_size -= second_end - second;
 3737|   215k|            } else {
 3738|   215k|                second = second_end + 1;
 3739|   215k|            }
 3740|   215k|        }
 3741|  69.9k|        first = first_end + 1;
 3742|  69.9k|    }
 3743|  9.97k|    search_path_size = search_path_updated_size;
 3744|       |
 3745|       |    // Print out the paths being searched if debugging is enabled
 3746|  9.97k|    uint32_t log_flags = 0;
 3747|  9.97k|    if (search_path_size > 0) {
  ------------------
  |  Branch (3747:9): [True: 9.96k, False: 2]
  ------------------
 3748|  9.96k|        char *tmp_search_path = loader_instance_heap_alloc(inst, search_path_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 3749|  9.96k|        if (NULL != tmp_search_path) {
  ------------------
  |  Branch (3749:13): [True: 9.96k, False: 0]
  ------------------
 3750|  9.96k|            loader_strncpy(tmp_search_path, search_path_size + 1, search_path, search_path_size);
 3751|  9.96k|            tmp_search_path[search_path_size] = '\0';
 3752|  9.96k|            if (manifest_type == LOADER_DATA_FILE_MANIFEST_DRIVER) {
  ------------------
  |  Branch (3752:17): [True: 17, False: 9.95k]
  ------------------
 3753|     17|                log_flags = VULKAN_LOADER_DRIVER_BIT;
 3754|     17|                loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Searching for driver manifest files");
 3755|  9.95k|            } else {
 3756|  9.95k|                log_flags = VULKAN_LOADER_LAYER_BIT;
 3757|  9.95k|                loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "Searching for %s layer manifest files",
 3758|  9.95k|                           manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER ? "explicit" : "implicit");
  ------------------
  |  Branch (3758:28): [True: 4.97k, False: 4.97k]
  ------------------
 3759|  9.95k|            }
 3760|  9.96k|            loader_log(inst, log_flags, 0, "   In following locations:");
 3761|  9.96k|            char *cur_file;
 3762|  9.96k|            char *next_file = tmp_search_path;
 3763|  79.8k|            while (NULL != next_file && *next_file != '\0') {
  ------------------
  |  Branch (3763:20): [True: 79.8k, False: 0]
  |  Branch (3763:41): [True: 69.9k, False: 9.96k]
  ------------------
 3764|  69.9k|                cur_file = next_file;
 3765|  69.9k|                next_file = loader_get_next_path(cur_file);
 3766|  69.9k|                loader_log(inst, log_flags, 0, "      %s", cur_file);
 3767|  69.9k|            }
 3768|  9.96k|            loader_instance_heap_free(inst, tmp_search_path);
 3769|  9.96k|        }
 3770|  9.96k|    }
 3771|       |
 3772|       |    // Now, parse the paths and add any manifest files found in them.
 3773|  9.97k|    vk_result = add_data_files(inst, search_path, out_files);
 3774|       |
 3775|  9.97k|    if (log_flags != 0 && out_files->count > 0) {
  ------------------
  |  Branch (3775:9): [True: 9.96k, False: 2]
  |  Branch (3775:27): [True: 4.05k, False: 5.91k]
  ------------------
 3776|  4.05k|        loader_log(inst, log_flags, 0, "   Found the following files:");
 3777|  8.57k|        for (uint32_t cur_file = 0; cur_file < out_files->count; ++cur_file) {
  ------------------
  |  Branch (3777:37): [True: 4.51k, False: 4.05k]
  ------------------
 3778|  4.51k|            loader_log(inst, log_flags, 0, "      %s", out_files->list[cur_file]);
 3779|  4.51k|        }
 3780|  5.91k|    } else {
 3781|  5.91k|        loader_log(inst, log_flags, 0, "   Found no files");
 3782|  5.91k|    }
 3783|       |
 3784|  9.97k|    if (NULL != override_path) {
  ------------------
  |  Branch (3784:9): [True: 57, False: 9.91k]
  ------------------
 3785|     57|        *override_active = true;
 3786|  9.91k|    } else {
 3787|  9.91k|        *override_active = false;
 3788|  9.91k|    }
 3789|       |
 3790|  9.97k|out:
 3791|       |
 3792|  9.97k|    loader_free_getenv(additional_env, inst);
 3793|  9.97k|    loader_free_getenv(override_env, inst);
 3794|       |#if defined(_WIN32)
 3795|       |    loader_instance_heap_free(inst, package_path);
 3796|       |#elif COMMON_UNIX_PLATFORMS
 3797|       |    loader_free_getenv(xdg_config_home, inst);
 3798|  9.97k|    loader_free_getenv(xdg_config_dirs, inst);
 3799|  9.97k|    loader_free_getenv(xdg_data_home, inst);
 3800|  9.97k|    loader_free_getenv(xdg_data_dirs, inst);
 3801|  9.97k|    loader_free_getenv(xdg_data_home, inst);
 3802|  9.97k|    loader_free_getenv(home, inst);
 3803|  9.97k|    loader_instance_heap_free(inst, default_data_home);
 3804|  9.97k|    loader_instance_heap_free(inst, default_config_home);
 3805|       |#else
 3806|       |#warning read_data_files_in_search_paths unsupported platform
 3807|       |#endif
 3808|       |
 3809|  9.97k|    loader_instance_heap_free(inst, search_path);
 3810|       |
 3811|  9.97k|    return vk_result;
 3812|  9.97k|}
loader_get_data_files:
 3838|  9.97k|                               const char *path_override, struct loader_string_list *out_files) {
 3839|  9.97k|    VkResult res = VK_SUCCESS;
 3840|  9.97k|    bool override_active = false;
 3841|       |
 3842|       |    // Free and init the out_files information so there's no false data left from uninitialized variables.
 3843|  9.97k|    free_string_list(inst, out_files);
 3844|       |
 3845|  9.97k|    res = read_data_files_in_search_paths(inst, manifest_type, path_override, &override_active, out_files);
 3846|  9.97k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3846:9): [True: 0, False: 9.97k]
  ------------------
 3847|      0|        goto out;
 3848|      0|    }
 3849|       |
 3850|       |#if defined(_WIN32)
 3851|       |    // Read the registry if the override wasn't active.
 3852|       |    if (!override_active) {
 3853|       |        bool warn_if_not_present = false;
 3854|       |        char *registry_location = NULL;
 3855|       |
 3856|       |        switch (manifest_type) {
 3857|       |            default:
 3858|       |                goto out;
 3859|       |            case LOADER_DATA_FILE_MANIFEST_DRIVER:
 3860|       |                warn_if_not_present = true;
 3861|       |                registry_location = VK_DRIVERS_INFO_REGISTRY_LOC;
 3862|       |                break;
 3863|       |            case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER:
 3864|       |                registry_location = VK_ILAYERS_INFO_REGISTRY_LOC;
 3865|       |                break;
 3866|       |            case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER:
 3867|       |                warn_if_not_present = true;
 3868|       |                registry_location = VK_ELAYERS_INFO_REGISTRY_LOC;
 3869|       |                break;
 3870|       |        }
 3871|       |        VkResult tmp_res =
 3872|       |            windows_read_data_files_in_registry(inst, manifest_type, warn_if_not_present, registry_location, out_files);
 3873|       |        // Only return an error if there was an error this time, and no manifest files from before.
 3874|       |        if (VK_SUCCESS != tmp_res && out_files->count == 0) {
 3875|       |            res = tmp_res;
 3876|       |            goto out;
 3877|       |        }
 3878|       |    }
 3879|       |#endif
 3880|       |
 3881|  9.97k|out:
 3882|       |
 3883|  9.97k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (3883:9): [True: 0, False: 9.97k]
  ------------------
 3884|      0|        free_string_list(inst, out_files);
 3885|      0|    }
 3886|       |
 3887|  9.97k|    return res;
 3888|  9.97k|}
loader_icd_scan:
 4055|     17|                         const VkInstanceCreateInfo *pCreateInfo, bool *skipped_portability_drivers) {
 4056|     17|    VkResult res = VK_SUCCESS;
 4057|     17|    struct loader_string_list manifest_files = {0};
 4058|     17|    struct loader_envvar_filter select_filter = {0};
 4059|     17|    struct loader_envvar_filter disable_filter = {0};
 4060|     17|    struct ICDManifestInfo *icd_details = NULL;
 4061|       |
 4062|       |    // Set up the ICD Trampoline list so elements can be written into it.
 4063|     17|    res = loader_init_scanned_icd_list(inst, icd_tramp_list);
 4064|     17|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (4064:9): [True: 0, False: 17]
  ------------------
 4065|      0|        return res;
 4066|      0|    }
 4067|       |
 4068|     17|    bool direct_driver_loading_exclusive_mode = false;
 4069|     17|    res = loader_scan_for_direct_drivers(inst, pCreateInfo, icd_tramp_list, &direct_driver_loading_exclusive_mode);
 4070|     17|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (4070:9): [True: 0, False: 17]
  ------------------
 4071|      0|        goto out;
 4072|      0|    }
 4073|     17|    if (direct_driver_loading_exclusive_mode) {
  ------------------
  |  Branch (4073:9): [True: 0, False: 17]
  ------------------
 4074|       |        // Make sure to jump over the system & env-var driver discovery mechanisms if exclusive mode is set, even if no drivers
 4075|       |        // were successfully found through the direct driver loading mechanism
 4076|      0|        goto out;
 4077|      0|    }
 4078|       |
 4079|     17|    if (loader_settings_should_use_driver_environment_variables(inst)) {
  ------------------
  |  Branch (4079:9): [True: 17, False: 0]
  ------------------
 4080|       |        // Parse the filter environment variables to determine if we have any special behavior
 4081|     17|        res = parse_generic_filter_environment_var(inst, VK_DRIVERS_SELECT_ENV_VAR, &select_filter);
  ------------------
  |  |  122|     17|#define VK_DRIVERS_SELECT_ENV_VAR "VK_LOADER_DRIVERS_SELECT"
  ------------------
 4082|     17|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4082:13): [True: 0, False: 17]
  ------------------
 4083|      0|            goto out;
 4084|      0|        }
 4085|     17|        res = parse_generic_filter_environment_var(inst, VK_DRIVERS_DISABLE_ENV_VAR, &disable_filter);
  ------------------
  |  |  123|     17|#define VK_DRIVERS_DISABLE_ENV_VAR "VK_LOADER_DRIVERS_DISABLE"
  ------------------
 4086|     17|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4086:13): [True: 0, False: 17]
  ------------------
 4087|      0|            goto out;
 4088|      0|        }
 4089|     17|    }
 4090|       |
 4091|       |    // Get a list of manifest files for ICDs
 4092|     17|    res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files);
 4093|     17|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4093:9): [True: 0, False: 17]
  ------------------
 4094|      0|        goto out;
 4095|      0|    }
 4096|       |
 4097|       |    // Add any drivers provided by the loader settings file
 4098|     17|    res = loader_settings_get_additional_driver_files(inst, &manifest_files);
 4099|     17|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4099:9): [True: 0, False: 17]
  ------------------
 4100|      0|        goto out;
 4101|      0|    }
 4102|       |
 4103|     17|    icd_details = loader_stack_alloc(sizeof(struct ICDManifestInfo) * manifest_files.count);
  ------------------
  |  |   42|     17|#define loader_stack_alloc(size) alloca(size)
  ------------------
 4104|     17|    if (NULL == icd_details) {
  ------------------
  |  Branch (4104:9): [True: 0, False: 17]
  ------------------
 4105|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4106|      0|        goto out;
 4107|      0|    }
 4108|     17|    memset(icd_details, 0, sizeof(struct ICDManifestInfo) * manifest_files.count);
 4109|       |
 4110|     17|    for (uint32_t i = 0; i < manifest_files.count; i++) {
  ------------------
  |  Branch (4110:26): [True: 0, False: 17]
  ------------------
 4111|      0|        VkResult icd_res = VK_SUCCESS;
 4112|       |
 4113|      0|        icd_res = loader_parse_icd_manifest(inst, manifest_files.list[i], &icd_details[i], skipped_portability_drivers);
 4114|      0|        if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) {
  ------------------
  |  Branch (4114:13): [True: 0, False: 0]
  ------------------
 4115|      0|            res = icd_res;
 4116|      0|            goto out;
 4117|      0|        } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) {
  ------------------
  |  Branch (4117:20): [True: 0, False: 0]
  ------------------
 4118|      0|            continue;
 4119|      0|        }
 4120|       |
 4121|      0|        if (select_filter.count > 0 || disable_filter.count > 0) {
  ------------------
  |  Branch (4121:13): [True: 0, False: 0]
  |  Branch (4121:40): [True: 0, False: 0]
  ------------------
 4122|       |            // Get only the filename for comparing to the filters
 4123|      0|            char *just_filename_str = strrchr(manifest_files.list[i], DIRECTORY_SYMBOL);
  ------------------
  |  |  151|      0|#define DIRECTORY_SYMBOL '/'
  ------------------
 4124|       |
 4125|       |            // No directory symbol, just the filename
 4126|      0|            if (NULL == just_filename_str) {
  ------------------
  |  Branch (4126:17): [True: 0, False: 0]
  ------------------
 4127|      0|                just_filename_str = manifest_files.list[i];
 4128|      0|            } else {
 4129|      0|                just_filename_str++;
 4130|      0|            }
 4131|       |
 4132|      0|            bool name_matches_select =
 4133|      0|                (select_filter.count > 0 && check_name_matches_filter_environment_var(just_filename_str, &select_filter));
  ------------------
  |  Branch (4133:18): [True: 0, False: 0]
  |  Branch (4133:45): [True: 0, False: 0]
  ------------------
 4134|      0|            bool name_matches_disable =
 4135|      0|                (disable_filter.count > 0 && check_name_matches_filter_environment_var(just_filename_str, &disable_filter));
  ------------------
  |  Branch (4135:18): [True: 0, False: 0]
  |  Branch (4135:46): [True: 0, False: 0]
  ------------------
 4136|       |
 4137|      0|            if (name_matches_disable && !name_matches_select) {
  ------------------
  |  Branch (4137:17): [True: 0, False: 0]
  |  Branch (4137:41): [True: 0, False: 0]
  ------------------
 4138|      0|                loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4139|      0|                           "Driver \"%s\" ignored because it was disabled by env var \'%s\'", just_filename_str,
 4140|      0|                           VK_DRIVERS_DISABLE_ENV_VAR);
  ------------------
  |  |  123|      0|#define VK_DRIVERS_DISABLE_ENV_VAR "VK_LOADER_DRIVERS_DISABLE"
  ------------------
 4141|      0|                continue;
 4142|      0|            }
 4143|      0|            if (select_filter.count != 0 && !name_matches_select) {
  ------------------
  |  Branch (4143:17): [True: 0, False: 0]
  |  Branch (4143:45): [True: 0, False: 0]
  ------------------
 4144|      0|                loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4145|      0|                           "Driver \"%s\" ignored because not selected by env var \'%s\'", just_filename_str,
 4146|      0|                           VK_DRIVERS_SELECT_ENV_VAR);
  ------------------
  |  |  122|      0|#define VK_DRIVERS_SELECT_ENV_VAR "VK_LOADER_DRIVERS_SELECT"
  ------------------
 4147|      0|                continue;
 4148|      0|            }
 4149|      0|        }
 4150|       |
 4151|      0|        enum loader_layer_library_status lib_status;
 4152|      0|        icd_res =
 4153|      0|            loader_scanned_icd_add(inst, icd_tramp_list, icd_details[i].full_library_path, icd_details[i].version, &lib_status);
 4154|      0|        if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) {
  ------------------
  |  Branch (4154:13): [True: 0, False: 0]
  ------------------
 4155|      0|            res = icd_res;
 4156|      0|            goto out;
 4157|      0|        } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) {
  ------------------
  |  Branch (4157:20): [True: 0, False: 0]
  ------------------
 4158|      0|            switch (lib_status) {
  ------------------
  |  Branch (4158:21): [True: 0, False: 0]
  ------------------
 4159|      0|                case LOADER_LAYER_LIB_NOT_LOADED:
  ------------------
  |  Branch (4159:17): [True: 0, False: 0]
  ------------------
 4160|      0|                case LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD:
  ------------------
  |  Branch (4160:17): [True: 0, False: 0]
  ------------------
 4161|      0|                    loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4162|      0|                               "loader_icd_scan: Failed loading library associated with ICD JSON %s. Ignoring this JSON",
 4163|      0|                               icd_details[i].full_library_path);
 4164|      0|                    break;
 4165|      0|                case LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE: {
  ------------------
  |  Branch (4165:17): [True: 0, False: 0]
  ------------------
 4166|      0|                    loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Requested ICD %s was wrong bit-type. Ignoring this JSON",
 4167|      0|                               icd_details[i].full_library_path);
 4168|      0|                    break;
 4169|      0|                }
 4170|      0|                case LOADER_LAYER_LIB_SUCCESS_LOADED:
  ------------------
  |  Branch (4170:17): [True: 0, False: 0]
  ------------------
 4171|      0|                case LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY:
  ------------------
  |  Branch (4171:17): [True: 0, False: 0]
  ------------------
 4172|       |                    // Shouldn't be able to reach this but if it is, best to report a debug
 4173|      0|                    loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
 4174|      0|                               "Shouldn't reach this. A valid version of requested ICD %s was loaded but something bad "
 4175|      0|                               "happened afterwards.",
 4176|      0|                               icd_details[i].full_library_path);
 4177|      0|                    break;
 4178|      0|            }
 4179|      0|        }
 4180|      0|    }
 4181|       |
 4182|     17|out:
 4183|     17|    if (NULL != icd_details) {
  ------------------
  |  Branch (4183:9): [True: 17, False: 0]
  ------------------
 4184|       |        // Successfully got the icd_details structure, which means we need to free the paths contained within
 4185|     17|        for (uint32_t i = 0; i < manifest_files.count; i++) {
  ------------------
  |  Branch (4185:30): [True: 0, False: 17]
  ------------------
 4186|      0|            loader_instance_heap_free(inst, icd_details[i].full_library_path);
 4187|      0|        }
 4188|     17|    }
 4189|     17|    free_string_list(inst, &manifest_files);
 4190|     17|    return res;
 4191|     17|}
loader_parse_instance_layers:
 4197|  9.95k|                                      const char *path_override, struct loader_layer_list *instance_layers) {
 4198|  9.95k|    assert(manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER || manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER);
 4199|  9.95k|    VkResult res = VK_SUCCESS;
 4200|  9.95k|    struct loader_string_list manifest_files = {0};
 4201|       |
 4202|  9.95k|    res = loader_get_data_files(inst, manifest_type, path_override, &manifest_files);
 4203|  9.95k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4203:9): [True: 0, False: 9.95k]
  ------------------
 4204|      0|        goto out;
 4205|      0|    }
 4206|       |
 4207|  14.4k|    for (uint32_t i = 0; i < manifest_files.count; i++) {
  ------------------
  |  Branch (4207:26): [True: 4.51k, False: 9.95k]
  ------------------
 4208|  4.51k|        char *file_str = manifest_files.list[i];
 4209|  4.51k|        if (file_str == NULL) {
  ------------------
  |  Branch (4209:13): [True: 0, False: 4.51k]
  ------------------
 4210|      0|            continue;
 4211|      0|        }
 4212|       |
 4213|       |        // Parse file into JSON struct
 4214|  4.51k|        cJSON *json = NULL;
 4215|  4.51k|        VkResult local_res = loader_get_json(inst, file_str, &json);
 4216|  4.51k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (4216:13): [True: 0, False: 4.51k]
  ------------------
 4217|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4218|      0|            goto out;
 4219|  4.51k|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (4219:20): [True: 26, False: 4.48k]
  |  Branch (4219:47): [True: 1.31k, False: 3.17k]
  ------------------
 4220|  1.34k|            continue;
 4221|  1.34k|        }
 4222|       |
 4223|  3.17k|        local_res = loader_add_layer_properties(inst, instance_layers, json,
 4224|  3.17k|                                                manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, file_str);
 4225|  3.17k|        loader_cJSON_Delete(json);
 4226|       |
 4227|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 4228|  3.17k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (4228:13): [True: 0, False: 3.17k]
  ------------------
 4229|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 4230|      0|            goto out;
 4231|      0|        }
 4232|  3.17k|    }
 4233|  9.95k|out:
 4234|  9.95k|    free_string_list(inst, &manifest_files);
 4235|       |
 4236|  9.95k|    return res;
 4237|  9.95k|}
get_override_layer_override_paths:
 4242|     57|                                           char **override_paths) {
 4243|     57|    if (prop->override_paths.count > 0) {
  ------------------
  |  Branch (4243:9): [True: 57, False: 0]
  ------------------
 4244|     57|        char *cur_write_ptr = NULL;
 4245|     57|        size_t override_path_size = 0;
 4246|    530|        for (uint32_t j = 0; j < prop->override_paths.count; j++) {
  ------------------
  |  Branch (4246:30): [True: 473, False: 57]
  ------------------
 4247|    473|            override_path_size += determine_data_file_path_size(prop->override_paths.list[j], 0);
 4248|    473|        }
 4249|     57|        *override_paths = loader_instance_heap_alloc(inst, override_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
 4250|     57|        if (*override_paths == NULL) {
  ------------------
  |  Branch (4250:13): [True: 0, False: 57]
  ------------------
 4251|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
 4252|      0|        }
 4253|     57|        cur_write_ptr = &(*override_paths)[0];
 4254|    530|        for (uint32_t j = 0; j < prop->override_paths.count; j++) {
  ------------------
  |  Branch (4254:30): [True: 473, False: 57]
  ------------------
 4255|    473|            copy_data_file_info(prop->override_paths.list[j], NULL, 0, &cur_write_ptr);
 4256|    473|        }
 4257|       |
 4258|       |        // Subtract one from cur_write_ptr only if something was written so we can set the null terminator
 4259|     57|        if (*override_paths < cur_write_ptr) {
  ------------------
  |  Branch (4259:13): [True: 55, False: 2]
  ------------------
 4260|     55|            --cur_write_ptr;
 4261|     55|            assert(cur_write_ptr - (*override_paths) < (ptrdiff_t)override_path_size);
 4262|     55|        }
 4263|       |        // Remove the last path separator
 4264|     57|        *cur_write_ptr = '\0';
 4265|     57|        loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Override layer has override paths set to %s",
 4266|     57|                   *override_paths);
 4267|     57|    }
 4268|     57|    return VK_SUCCESS;
 4269|     57|}
loader_remove_duplicate_layers:
 4271|  4.97k|void loader_remove_duplicate_layers(struct loader_instance *inst, struct loader_layer_list *layers) {
 4272|       |    // Remove duplicate layers (that share the same layerName)
 4273|  22.8k|    for (uint32_t i = 0; i < layers->count; ++i) {
  ------------------
  |  Branch (4273:26): [True: 17.8k, False: 4.97k]
  ------------------
 4274|  17.8k|        bool has_duplicate = false;
 4275|  17.8k|        uint32_t duplicate_index = 0;
 4276|   344k|        for (uint32_t j = i + 1; j < layers->count; ++j) {
  ------------------
  |  Branch (4276:34): [True: 340k, False: 4.07k]
  ------------------
 4277|   340k|            if (strcmp(layers->list[i].info.layerName, layers->list[j].info.layerName) == 0) {
  ------------------
  |  Branch (4277:17): [True: 13.7k, False: 326k]
  ------------------
 4278|  13.7k|                has_duplicate = true;
 4279|  13.7k|                duplicate_index = j;
 4280|  13.7k|                break;
 4281|  13.7k|            }
 4282|   340k|        }
 4283|  17.8k|        if (has_duplicate) {
  ------------------
  |  Branch (4283:13): [True: 13.7k, False: 4.07k]
  ------------------
 4284|  13.7k|            loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Removing layer %s (%s) because it is a duplicate of %s (%s)",
 4285|  13.7k|                       layers->list[duplicate_index].info.layerName, layers->list[duplicate_index].manifest_file_name,
 4286|  13.7k|                       layers->list[i].info.layerName, layers->list[i].manifest_file_name);
 4287|  13.7k|            loader_remove_layer_in_list(inst, layers, duplicate_index);
 4288|  13.7k|        }
 4289|  17.8k|    }
 4290|  4.97k|}
loader_scan_for_layers:
 4293|  6.52k|                                const struct loader_envvar_all_filters *filters) {
 4294|  6.52k|    VkResult res = VK_SUCCESS;
 4295|  6.52k|    struct loader_layer_list settings_layers = {0};
 4296|  6.52k|    struct loader_layer_list regular_instance_layers = {0};
 4297|  6.52k|    bool override_layer_valid = false;
 4298|  6.52k|    char *override_paths = NULL;
 4299|       |
 4300|  6.52k|    bool should_search_for_other_layers = true;
 4301|  6.52k|    res = get_settings_layers(inst, &settings_layers, &should_search_for_other_layers);
 4302|  6.52k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4302:9): [True: 0, False: 6.52k]
  ------------------
 4303|      0|        goto out;
 4304|      0|    }
 4305|       |
 4306|       |    // If we should not look for layers using other mechanisms, assign settings_layers to instance_layers and jump to the
 4307|       |    // output
 4308|  6.52k|    if (!should_search_for_other_layers) {
  ------------------
  |  Branch (4308:9): [True: 1.54k, False: 4.97k]
  ------------------
 4309|  1.54k|        *instance_layers = settings_layers;
 4310|  1.54k|        memset(&settings_layers, 0, sizeof(struct loader_layer_list));
 4311|  1.54k|        goto out;
 4312|  1.54k|    }
 4313|       |
 4314|  4.97k|    res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &regular_instance_layers);
 4315|  4.97k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4315:9): [True: 0, False: 4.97k]
  ------------------
 4316|      0|        goto out;
 4317|      0|    }
 4318|       |
 4319|       |    // Remove any extraneous override layers.
 4320|  4.97k|    remove_all_non_valid_override_layers(inst, &regular_instance_layers);
 4321|       |
 4322|       |    // Check to see if the override layer is present, and use it's override paths.
 4323|  37.1k|    for (uint32_t i = 0; i < regular_instance_layers.count; i++) {
  ------------------
  |  Branch (4323:26): [True: 32.2k, False: 4.92k]
  ------------------
 4324|  32.2k|        struct loader_layer_properties *prop = &regular_instance_layers.list[i];
 4325|  32.2k|        if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop) && prop->override_paths.count > 0) {
  ------------------
  |  Branch (4325:13): [True: 301, False: 31.9k]
  |  Branch (4325:34): [True: 208, False: 93]
  |  Branch (4325:91): [True: 57, False: 151]
  ------------------
 4326|     57|            res = get_override_layer_override_paths(inst, prop, &override_paths);
 4327|     57|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4327:17): [True: 0, False: 57]
  ------------------
 4328|      0|                goto out;
 4329|      0|            }
 4330|     57|            break;
 4331|     57|        }
 4332|  32.2k|    }
 4333|       |
 4334|       |    // Get a list of manifest files for explicit layers
 4335|  4.97k|    res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, override_paths, &regular_instance_layers);
 4336|  4.97k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (4336:9): [True: 0, False: 4.97k]
  ------------------
 4337|      0|        goto out;
 4338|      0|    }
 4339|       |
 4340|       |    // Verify any meta-layers in the list are valid and all the component layers are
 4341|       |    // actually present in the available layer list
 4342|  4.97k|    res = verify_all_meta_layers(inst, filters, &regular_instance_layers, &override_layer_valid);
 4343|  4.97k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (4343:9): [True: 0, False: 4.97k]
  ------------------
 4344|      0|        return res;
 4345|      0|    }
 4346|       |
 4347|  4.97k|    if (override_layer_valid) {
  ------------------
  |  Branch (4347:9): [True: 168, False: 4.80k]
  ------------------
 4348|    168|        loader_remove_layers_in_blacklist(inst, &regular_instance_layers);
 4349|    168|        if (NULL != inst) {
  ------------------
  |  Branch (4349:13): [True: 168, False: 0]
  ------------------
 4350|    168|            inst->override_layer_present = true;
 4351|    168|        }
 4352|    168|    }
 4353|       |
 4354|       |    // Remove disabled layers
 4355|  36.5k|    for (uint32_t i = 0; i < regular_instance_layers.count; ++i) {
  ------------------
  |  Branch (4355:26): [True: 31.5k, False: 4.97k]
  ------------------
 4356|  31.5k|        if (!loader_layer_is_available(inst, filters, &regular_instance_layers.list[i])) {
  ------------------
  |  Branch (4356:13): [True: 0, False: 31.5k]
  ------------------
 4357|      0|            loader_remove_layer_in_list(inst, &regular_instance_layers, i);
 4358|      0|            i--;
 4359|      0|        }
 4360|  31.5k|    }
 4361|       |
 4362|       |    // Make sure no layers have the same layerName
 4363|  4.97k|    loader_remove_duplicate_layers(inst, &regular_instance_layers);
 4364|       |
 4365|  4.97k|    res = combine_settings_layers_with_regular_layers(inst, &settings_layers, &regular_instance_layers, instance_layers);
 4366|       |
 4367|  6.52k|out:
 4368|  6.52k|    loader_delete_layer_list_and_properties(inst, &settings_layers);
 4369|  6.52k|    loader_delete_layer_list_and_properties(inst, &regular_instance_layers);
 4370|       |
 4371|  6.52k|    loader_instance_heap_free(inst, override_paths);
 4372|  6.52k|    return res;
 4373|  4.97k|}
loader_validate_layers:
 5575|  6.52k|                                const char *const *ppEnabledLayerNames, const struct loader_layer_list *list) {
 5576|  6.52k|    struct loader_layer_properties *prop;
 5577|       |
 5578|  6.52k|    if (layer_count > 0 && ppEnabledLayerNames == NULL) {
  ------------------
  |  Branch (5578:9): [True: 6.52k, False: 0]
  |  Branch (5578:28): [True: 0, False: 6.52k]
  ------------------
 5579|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5580|      0|                   "loader_validate_layers: ppEnabledLayerNames is NULL but enabledLayerCount is greater than zero");
 5581|      0|        return VK_ERROR_LAYER_NOT_PRESENT;
 5582|      0|    }
 5583|       |
 5584|  6.54k|    for (uint32_t i = 0; i < layer_count; i++) {
  ------------------
  |  Branch (5584:26): [True: 6.52k, False: 17]
  ------------------
 5585|  6.52k|        VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]);
 5586|  6.52k|        if (result != VK_STRING_ERROR_NONE) {
  ------------------
  |  Branch (5586:13): [True: 0, False: 6.52k]
  ------------------
 5587|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5588|      0|                       "loader_validate_layers: ppEnabledLayerNames contains string that is too long or is badly formed");
 5589|      0|            return VK_ERROR_LAYER_NOT_PRESENT;
 5590|      0|        }
 5591|       |
 5592|  6.52k|        prop = loader_find_layer_property(ppEnabledLayerNames[i], list);
 5593|  6.52k|        if (NULL == prop) {
  ------------------
  |  Branch (5593:13): [True: 6.50k, False: 17]
  ------------------
 5594|  6.50k|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5595|  6.50k|                       "loader_validate_layers: Layer %d does not exist in the list of available layers", i);
 5596|  6.50k|            return VK_ERROR_LAYER_NOT_PRESENT;
 5597|  6.50k|        }
 5598|     17|        if (inst->settings.settings_active && inst->settings.layer_configurations_active &&
  ------------------
  |  Branch (5598:13): [True: 17, False: 0]
  |  Branch (5598:47): [True: 17, False: 0]
  ------------------
 5599|     17|            prop->settings_control_value != LOADER_SETTINGS_LAYER_CONTROL_ON &&
  ------------------
  |  Branch (5599:13): [True: 17, False: 0]
  ------------------
 5600|     17|            prop->settings_control_value != LOADER_SETTINGS_LAYER_CONTROL_DEFAULT) {
  ------------------
  |  Branch (5600:13): [True: 0, False: 17]
  ------------------
 5601|      0|            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
 5602|      0|                       "loader_validate_layers: Layer %d was explicitly prevented from being enabled by the loader settings file",
 5603|      0|                       i);
 5604|      0|            return VK_ERROR_LAYER_NOT_PRESENT;
 5605|      0|        }
 5606|     17|    }
 5607|     17|    return VK_SUCCESS;
 5608|  6.52k|}
vk_string_validate:
 7504|  6.52k|VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
 7505|  6.52k|    VkStringErrorFlags result = VK_STRING_ERROR_NONE;
 7506|  6.52k|    int num_char_bytes = 0;
 7507|  6.52k|    int i, j;
 7508|       |
 7509|  6.52k|    if (utf8 == NULL) {
  ------------------
  |  Branch (7509:9): [True: 0, False: 6.52k]
  ------------------
 7510|      0|        return VK_STRING_ERROR_NULL_PTR;
 7511|      0|    }
 7512|       |
 7513|   182k|    for (i = 0; i <= max_length; i++) {
  ------------------
  |  Branch (7513:17): [True: 182k, False: 0]
  ------------------
 7514|   182k|        if (utf8[i] == 0) {
  ------------------
  |  Branch (7514:13): [True: 6.52k, False: 176k]
  ------------------
 7515|  6.52k|            break;
 7516|   176k|        } else if (i == max_length) {
  ------------------
  |  Branch (7516:20): [True: 0, False: 176k]
  ------------------
 7517|      0|            result |= VK_STRING_ERROR_LENGTH;
 7518|      0|            break;
 7519|   176k|        } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) {
  ------------------
  |  Branch (7519:20): [True: 176k, False: 0]
  |  Branch (7519:41): [True: 176k, False: 0]
  ------------------
 7520|   176k|            num_char_bytes = 0;
 7521|   176k|        } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) {
  ------------------
  |  Branch (7521:20): [True: 0, False: 0]
  ------------------
 7522|      0|            num_char_bytes = 1;
 7523|      0|        } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) {
  ------------------
  |  Branch (7523:20): [True: 0, False: 0]
  ------------------
 7524|      0|            num_char_bytes = 2;
 7525|      0|        } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
  ------------------
  |  Branch (7525:20): [True: 0, False: 0]
  ------------------
 7526|      0|            num_char_bytes = 3;
 7527|      0|        } else {
 7528|      0|            result = VK_STRING_ERROR_BAD_DATA;
 7529|      0|        }
 7530|       |
 7531|       |        // Validate the following num_char_bytes of data
 7532|   176k|        for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
  ------------------
  |  Branch (7532:21): [True: 0, False: 176k]
  |  Branch (7532:45): [True: 0, False: 0]
  ------------------
 7533|      0|            if (++i == max_length) {
  ------------------
  |  Branch (7533:17): [True: 0, False: 0]
  ------------------
 7534|      0|                result |= VK_STRING_ERROR_LENGTH;
 7535|      0|                break;
 7536|      0|            }
 7537|      0|            if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
  ------------------
  |  Branch (7537:17): [True: 0, False: 0]
  ------------------
 7538|      0|                result |= VK_STRING_ERROR_BAD_DATA;
 7539|      0|            }
 7540|      0|        }
 7541|   176k|    }
 7542|  6.52k|    return result;
 7543|  6.52k|}

loader_getenv:
   43|    542|char *loader_getenv(const char *name, const struct loader_instance *inst) {
   44|    542|    if (NULL == name) return NULL;
  ------------------
  |  Branch (44:9): [True: 0, False: 542]
  ------------------
   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|    542|    (void)inst;
   48|    542|    return getenv(name);
   49|    542|}
loader_secure_getenv:
   51|   122k|char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
   52|       |#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
   53|       |    // Apple does not appear to have a secure getenv implementation.
   54|       |    // The main difference between secure getenv and getenv is that secure getenv
   55|       |    // returns NULL if the process is being run with elevated privileges by a normal user.
   56|       |    // The idea is to prevent the reading of malicious environment variables by a process
   57|       |    // that can do damage.
   58|       |    // This algorithm is derived from glibc code that sets an internal
   59|       |    // variable (__libc_enable_secure) if the process is running under setuid or setgid.
   60|       |    return is_high_integrity() ? NULL : loader_getenv(name, inst);
   61|       |#elif defined(__Fuchsia__)
   62|       |    return loader_getenv(name, inst);
   63|       |#else
   64|       |    // Linux
   65|   122k|    char *out;
   66|   122k|#if defined(HAVE_SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   67|   122k|    (void)inst;
   68|   122k|    out = secure_getenv(name);
   69|       |#elif defined(HAVE___SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   70|       |    (void)inst;
   71|       |    out = __secure_getenv(name);
   72|       |#else
   73|       |    out = loader_getenv(name, inst);
   74|       |#if !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
   75|       |    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
   76|       |#endif
   77|       |#endif
   78|   122k|    return out;
   79|   122k|#endif
   80|   122k|}
loader_free_getenv:
   82|  93.3k|void loader_free_getenv(char *val, const struct loader_instance *inst) {
   83|       |    // No freeing of memory necessary for Linux, but we should at least touch
   84|       |    // the val and inst pointers to get rid of compiler warnings.
   85|  93.3k|    (void)val;
   86|  93.3k|    (void)inst;
   87|  93.3k|}
determine_filter_type:
  192|  6.52k|                           size_t *new_length) {
  193|  6.52k|    size_t filter_length = strlen(filter_string);
  194|  6.52k|    bool star_begin = false;
  195|  6.52k|    bool star_end = false;
  196|  6.52k|    if ('~' == filter_string[0]) {
  ------------------
  |  Branch (196:9): [True: 0, False: 6.52k]
  ------------------
  197|       |        // One of the special identifiers like: ~all~, ~implicit~, or ~explicit~
  198|      0|        *filter_type = FILTER_STRING_SPECIAL;
  199|      0|        *new_start = filter_string;
  200|      0|        *new_length = filter_length;
  201|  6.52k|    } else {
  202|  6.52k|        if ('*' == filter_string[0]) {
  ------------------
  |  Branch (202:13): [True: 0, False: 6.52k]
  ------------------
  203|       |            // Only the * means everything
  204|      0|            if (filter_length == 1) {
  ------------------
  |  Branch (204:17): [True: 0, False: 0]
  ------------------
  205|      0|                *filter_type = FILTER_STRING_SPECIAL;
  206|      0|                *new_start = filter_string;
  207|      0|                *new_length = filter_length;
  208|      0|            } else {
  209|      0|                star_begin = true;
  210|      0|            }
  211|      0|        }
  212|  6.52k|        if ('*' == filter_string[filter_length - 1]) {
  ------------------
  |  Branch (212:13): [True: 0, False: 6.52k]
  ------------------
  213|       |            // Not really valid, but just catch this case so if someone accidentally types "**" it will also mean everything
  214|      0|            if (filter_length == 2) {
  ------------------
  |  Branch (214:17): [True: 0, False: 0]
  ------------------
  215|      0|                *filter_type = FILTER_STRING_SPECIAL;
  216|      0|                *new_start = filter_string;
  217|      0|                *new_length = filter_length;
  218|      0|            } else {
  219|      0|                star_end = true;
  220|      0|            }
  221|      0|        }
  222|  6.52k|        if (star_begin && star_end) {
  ------------------
  |  Branch (222:13): [True: 0, False: 6.52k]
  |  Branch (222:27): [True: 0, False: 0]
  ------------------
  223|      0|            *filter_type = FILTER_STRING_SUBSTRING;
  224|      0|            *new_start = &filter_string[1];
  225|      0|            *new_length = filter_length - 2;
  226|  6.52k|        } else if (star_begin) {
  ------------------
  |  Branch (226:20): [True: 0, False: 6.52k]
  ------------------
  227|      0|            *new_start = &filter_string[1];
  228|      0|            *new_length = filter_length - 1;
  229|      0|            *filter_type = FILTER_STRING_SUFFIX;
  230|  6.52k|        } else if (star_end) {
  ------------------
  |  Branch (230:20): [True: 0, False: 6.52k]
  ------------------
  231|      0|            *filter_type = FILTER_STRING_PREFIX;
  232|      0|            *new_start = filter_string;
  233|      0|            *new_length = filter_length - 1;
  234|  6.52k|        } else {
  235|  6.52k|            *filter_type = FILTER_STRING_FULLNAME;
  236|  6.52k|            *new_start = filter_string;
  237|  6.52k|            *new_length = filter_length;
  238|  6.52k|        }
  239|  6.52k|    }
  240|  6.52k|}
parse_generic_filter_environment_var:
  245|  13.0k|                                              struct loader_envvar_filter *filter_struct) {
  246|  13.0k|    VkResult result = VK_SUCCESS;
  247|  13.0k|    memset(filter_struct, 0, sizeof(struct loader_envvar_filter));
  248|  13.0k|    char *parsing_string = NULL;
  249|  13.0k|    char *env_var_value = loader_secure_getenv(env_var_name, inst);
  250|  13.0k|    if (NULL == env_var_value) {
  ------------------
  |  Branch (250:9): [True: 6.55k, False: 6.52k]
  ------------------
  251|  6.55k|        return result;
  252|  6.55k|    }
  253|  6.52k|    const size_t env_var_len = strlen(env_var_value);
  254|  6.52k|    if (env_var_len == 0) {
  ------------------
  |  Branch (254:9): [True: 0, False: 6.52k]
  ------------------
  255|      0|        goto out;
  256|      0|    }
  257|       |    // Allocate a separate string since scan_for_next_comma modifies the original string
  258|  6.52k|    parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  259|  6.52k|    if (NULL == parsing_string) {
  ------------------
  |  Branch (259:9): [True: 0, False: 6.52k]
  ------------------
  260|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
  261|      0|                   "parse_generic_filter_environment_var: Failed to allocate space for parsing env var \'%s\'", env_var_name);
  262|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
  263|      0|        goto out;
  264|      0|    }
  265|       |
  266|  26.0k|    for (uint32_t iii = 0; iii < env_var_len; ++iii) {
  ------------------
  |  Branch (266:28): [True: 19.5k, False: 6.52k]
  ------------------
  267|  19.5k|        parsing_string[iii] = (char)tolower(env_var_value[iii]);
  ------------------
  |  Branch (267:37): [True: 0, False: 0]
  |  Branch (267:37): [True: 0, False: 0]
  |  Branch (267:37): [Folded, False: 19.5k]
  ------------------
  268|  19.5k|    }
  269|  6.52k|    parsing_string[env_var_len] = '\0';
  270|       |
  271|  6.52k|    char *context = NULL;
  272|  6.52k|    char *token = thread_safe_strtok(parsing_string, ",", &context);
  273|  13.0k|    while (NULL != token) {
  ------------------
  |  Branch (273:12): [True: 6.52k, False: 6.52k]
  ------------------
  274|  6.52k|        enum loader_filter_string_type cur_filter_type;
  275|  6.52k|        const char *actual_start;
  276|  6.52k|        size_t actual_len;
  277|  6.52k|        determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
  278|  6.52k|        if (actual_len > VK_MAX_EXTENSION_NAME_SIZE) {
  ------------------
  |  Branch (278:13): [True: 0, False: 6.52k]
  ------------------
  279|      0|            loader_strncpy(filter_struct->filters[filter_struct->count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start,
  280|      0|                           VK_MAX_EXTENSION_NAME_SIZE);
  281|  6.52k|        } else {
  282|  6.52k|            loader_strncpy(filter_struct->filters[filter_struct->count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start,
  283|  6.52k|                           actual_len);
  284|  6.52k|        }
  285|  6.52k|        filter_struct->filters[filter_struct->count].length = actual_len;
  286|  6.52k|        filter_struct->filters[filter_struct->count++].type = cur_filter_type;
  287|  6.52k|        if (filter_struct->count >= MAX_ADDITIONAL_FILTERS) {
  ------------------
  |  |  507|  6.52k|#define MAX_ADDITIONAL_FILTERS 16
  ------------------
  |  Branch (287:13): [True: 0, False: 6.52k]
  ------------------
  288|      0|            break;
  289|      0|        }
  290|  6.52k|        token = thread_safe_strtok(NULL, ",", &context);
  291|  6.52k|    }
  292|       |
  293|  6.52k|out:
  294|       |
  295|  6.52k|    loader_instance_heap_free(inst, parsing_string);
  296|  6.52k|    loader_free_getenv(env_var_value, inst);
  297|  6.52k|    return result;
  298|  6.52k|}
parse_layers_disable_filter_environment_var:
  304|  6.52k|                                                     struct loader_envvar_disable_layers_filter *disable_struct) {
  305|  6.52k|    VkResult result = VK_SUCCESS;
  306|  6.52k|    memset(disable_struct, 0, sizeof(struct loader_envvar_disable_layers_filter));
  307|  6.52k|    char *parsing_string = NULL;
  308|  6.52k|    char *env_var_value = loader_secure_getenv(VK_LAYERS_DISABLE_ENV_VAR, inst);
  ------------------
  |  |  120|  6.52k|#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
  ------------------
  309|  6.52k|    if (NULL == env_var_value) {
  ------------------
  |  Branch (309:9): [True: 6.52k, False: 0]
  ------------------
  310|  6.52k|        goto out;
  311|  6.52k|    }
  312|      0|    const size_t env_var_len = strlen(env_var_value);
  313|      0|    if (env_var_len == 0) {
  ------------------
  |  Branch (313:9): [True: 0, False: 0]
  ------------------
  314|      0|        goto out;
  315|      0|    }
  316|       |    // Allocate a separate string since scan_for_next_comma modifies the original string
  317|      0|    parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  318|      0|    if (NULL == parsing_string) {
  ------------------
  |  Branch (318:9): [True: 0, False: 0]
  ------------------
  319|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
  320|      0|                   "parse_layers_disable_filter_environment_var: Failed to allocate space for parsing env var "
  321|      0|                   "\'VK_LAYERS_DISABLE_ENV_VAR\'");
  322|      0|        result = VK_ERROR_OUT_OF_HOST_MEMORY;
  323|      0|        goto out;
  324|      0|    }
  325|       |
  326|      0|    for (uint32_t iii = 0; iii < env_var_len; ++iii) {
  ------------------
  |  Branch (326:28): [True: 0, False: 0]
  ------------------
  327|      0|        parsing_string[iii] = (char)tolower(env_var_value[iii]);
  ------------------
  |  Branch (327:37): [True: 0, False: 0]
  |  Branch (327:37): [True: 0, False: 0]
  |  Branch (327:37): [Folded, False: 0]
  ------------------
  328|      0|    }
  329|      0|    parsing_string[env_var_len] = '\0';
  330|       |
  331|      0|    char *context = NULL;
  332|      0|    char *token = thread_safe_strtok(parsing_string, ",", &context);
  333|      0|    while (NULL != token) {
  ------------------
  |  Branch (333:12): [True: 0, False: 0]
  ------------------
  334|      0|        uint32_t cur_count = disable_struct->additional_filters.count;
  335|      0|        enum loader_filter_string_type cur_filter_type;
  336|      0|        const char *actual_start;
  337|      0|        size_t actual_len;
  338|      0|        determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
  339|      0|        if (cur_filter_type == FILTER_STRING_SPECIAL) {
  ------------------
  |  Branch (339:13): [True: 0, False: 0]
  ------------------
  340|      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 (340:17): [True: 0, False: 0]
  |  Branch (340:71): [True: 0, False: 0]
  ------------------
  341|      0|                !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, token)) {
  ------------------
  |  |  126|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
  ------------------
  |  Branch (341:17): [True: 0, False: 0]
  ------------------
  342|      0|                disable_struct->disable_all = true;
  343|      0|            } else if (!strcmp(VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR, token)) {
  ------------------
  |  |  127|      0|#define VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR "~implicit~"
  ------------------
  |  Branch (343:24): [True: 0, False: 0]
  ------------------
  344|      0|                disable_struct->disable_all_implicit = true;
  345|      0|            } else if (!strcmp(VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR, token)) {
  ------------------
  |  |  128|      0|#define VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR "~explicit~"
  ------------------
  |  Branch (345:24): [True: 0, False: 0]
  ------------------
  346|      0|                disable_struct->disable_all_explicit = true;
  347|      0|            }
  348|      0|        } else {
  349|      0|            if (actual_len > VK_MAX_EXTENSION_NAME_SIZE) {
  ------------------
  |  Branch (349:17): [True: 0, False: 0]
  ------------------
  350|      0|                loader_strncpy(disable_struct->additional_filters.filters[cur_count].value, VK_MAX_EXTENSION_NAME_SIZE,
  351|      0|                               actual_start, VK_MAX_EXTENSION_NAME_SIZE);
  352|      0|            } else {
  353|      0|                loader_strncpy(disable_struct->additional_filters.filters[cur_count].value, VK_MAX_EXTENSION_NAME_SIZE,
  354|      0|                               actual_start, actual_len);
  355|      0|            }
  356|      0|            disable_struct->additional_filters.filters[cur_count].length = actual_len;
  357|      0|            disable_struct->additional_filters.filters[cur_count].type = cur_filter_type;
  358|      0|            disable_struct->additional_filters.count++;
  359|      0|            if (disable_struct->additional_filters.count >= MAX_ADDITIONAL_FILTERS) {
  ------------------
  |  |  507|      0|#define MAX_ADDITIONAL_FILTERS 16
  ------------------
  |  Branch (359:17): [True: 0, False: 0]
  ------------------
  360|      0|                break;
  361|      0|            }
  362|      0|        }
  363|      0|        token = thread_safe_strtok(NULL, ",", &context);
  364|      0|    }
  365|  6.52k|out:
  366|  6.52k|    loader_instance_heap_free(inst, parsing_string);
  367|  6.52k|    loader_free_getenv(env_var_value, inst);
  368|  6.52k|    return result;
  369|      0|}
parse_layer_environment_var_filters:
  372|  6.52k|VkResult parse_layer_environment_var_filters(const struct loader_instance *inst, struct loader_envvar_all_filters *layer_filters) {
  373|  6.52k|    VkResult res = parse_generic_filter_environment_var(inst, VK_LAYERS_ENABLE_ENV_VAR, &layer_filters->enable_filter);
  ------------------
  |  |  119|  6.52k|#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
  ------------------
  374|  6.52k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (374:9): [True: 0, False: 6.52k]
  ------------------
  375|      0|        return res;
  376|      0|    }
  377|  6.52k|    res = parse_layers_disable_filter_environment_var(inst, &layer_filters->disable_filter);
  378|  6.52k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (378:9): [True: 0, False: 6.52k]
  ------------------
  379|      0|        return res;
  380|      0|    }
  381|  6.52k|    res = parse_generic_filter_environment_var(inst, VK_LAYERS_ALLOW_ENV_VAR, &layer_filters->allow_filter);
  ------------------
  |  |  121|  6.52k|#define VK_LAYERS_ALLOW_ENV_VAR "VK_LOADER_LAYERS_ALLOW"
  ------------------
  382|  6.52k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (382:9): [True: 0, False: 6.52k]
  ------------------
  383|      0|        return res;
  384|      0|    }
  385|  6.52k|    return res;
  386|  6.52k|}
check_name_matches_filter_environment_var:
  394|  64.1k|bool check_name_matches_filter_environment_var(const char *name, const struct loader_envvar_filter *filter_struct) {
  395|  64.1k|    bool ret_value = false;
  396|  64.1k|    const size_t name_len = strlen(name);
  397|  64.1k|    char lower_name[VK_MAX_EXTENSION_NAME_SIZE];
  398|   380k|    for (uint32_t iii = 0; iii < name_len; ++iii) {
  ------------------
  |  Branch (398:28): [True: 316k, False: 64.1k]
  ------------------
  399|   316k|        lower_name[iii] = (char)tolower(name[iii]);
  ------------------
  |  Branch (399:33): [True: 0, False: 0]
  |  Branch (399:33): [True: 0, False: 0]
  |  Branch (399:33): [Folded, False: 316k]
  ------------------
  400|   316k|    }
  401|  64.1k|    lower_name[name_len] = '\0';
  402|  96.0k|    for (uint32_t filt = 0; filt < filter_struct->count; ++filt) {
  ------------------
  |  Branch (402:29): [True: 32.0k, False: 63.9k]
  ------------------
  403|       |        // Check if the filter name is longer (this is with all special characters removed), and if it is
  404|       |        // continue since it can't match.
  405|  32.0k|        if (filter_struct->filters[filt].length > name_len) {
  ------------------
  |  Branch (405:13): [True: 25.3k, False: 6.71k]
  ------------------
  406|  25.3k|            continue;
  407|  25.3k|        }
  408|  6.71k|        switch (filter_struct->filters[filt].type) {
  ------------------
  |  Branch (408:17): [True: 6.71k, False: 0]
  ------------------
  409|      0|            case FILTER_STRING_SPECIAL:
  ------------------
  |  Branch (409:13): [True: 0, False: 6.71k]
  ------------------
  410|      0|                if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, filter_struct->filters[filt].value) ||
  ------------------
  |  |  124|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
  ------------------
  |  Branch (410:21): [True: 0, False: 0]
  ------------------
  411|      0|                    !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, filter_struct->filters[filt].value) ||
  ------------------
  |  |  125|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
  ------------------
  |  Branch (411:21): [True: 0, False: 0]
  ------------------
  412|      0|                    !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, filter_struct->filters[filt].value)) {
  ------------------
  |  |  126|      0|#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
  ------------------
  |  Branch (412:21): [True: 0, False: 0]
  ------------------
  413|      0|                    ret_value = true;
  414|      0|                }
  415|      0|                break;
  416|       |
  417|      0|            case FILTER_STRING_SUBSTRING:
  ------------------
  |  Branch (417:13): [True: 0, False: 6.71k]
  ------------------
  418|      0|                if (NULL != strstr(lower_name, filter_struct->filters[filt].value)) {
  ------------------
  |  Branch (418:21): [True: 0, False: 0]
  ------------------
  419|      0|                    ret_value = true;
  420|      0|                }
  421|      0|                break;
  422|       |
  423|      0|            case FILTER_STRING_SUFFIX:
  ------------------
  |  Branch (423:13): [True: 0, False: 6.71k]
  ------------------
  424|      0|                if (0 == strncmp(lower_name + name_len - filter_struct->filters[filt].length, filter_struct->filters[filt].value,
  ------------------
  |  Branch (424:21): [True: 0, False: 0]
  ------------------
  425|      0|                                 filter_struct->filters[filt].length)) {
  426|      0|                    ret_value = true;
  427|      0|                }
  428|      0|                break;
  429|       |
  430|      0|            case FILTER_STRING_PREFIX:
  ------------------
  |  Branch (430:13): [True: 0, False: 6.71k]
  ------------------
  431|      0|                if (0 == strncmp(lower_name, filter_struct->filters[filt].value, filter_struct->filters[filt].length)) {
  ------------------
  |  Branch (431:21): [True: 0, False: 0]
  ------------------
  432|      0|                    ret_value = true;
  433|      0|                }
  434|      0|                break;
  435|       |
  436|  6.71k|            case FILTER_STRING_FULLNAME:
  ------------------
  |  Branch (436:13): [True: 6.71k, False: 0]
  ------------------
  437|  6.71k|                if (0 == strncmp(lower_name, filter_struct->filters[filt].value, name_len)) {
  ------------------
  |  Branch (437:21): [True: 185, False: 6.53k]
  ------------------
  438|    185|                    ret_value = true;
  439|    185|                }
  440|  6.71k|                break;
  441|  6.71k|        }
  442|  6.71k|        if (ret_value) {
  ------------------
  |  Branch (442:13): [True: 185, False: 6.53k]
  ------------------
  443|    185|            break;
  444|    185|        }
  445|  6.71k|    }
  446|  64.1k|    return ret_value;
  447|  64.1k|}

loader_get_json:
  148|  19.4k|TEST_FUNCTION_EXPORT VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) {
  149|  19.4k|    char *json_buf = NULL;
  150|  19.4k|    VkResult res = VK_SUCCESS;
  151|       |
  152|  19.4k|    assert(json != NULL);
  153|       |
  154|  19.4k|    size_t json_len = 0;
  155|  19.4k|    *json = NULL;
  156|  19.4k|    res = loader_read_entire_file(inst, filename, &json_len, &json_buf);
  157|  19.4k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (157:9): [True: 251, False: 19.1k]
  ------------------
  158|    251|        goto out;
  159|    251|    }
  160|  19.4k|    bool out_of_memory = false;
  161|       |    // Parse text from file
  162|  19.1k|    *json = loader_cJSON_ParseWithLength(inst ? &inst->alloc_callbacks : NULL, json_buf, json_len, &out_of_memory);
  ------------------
  |  Branch (162:42): [True: 19.1k, False: 0]
  ------------------
  163|  19.1k|    if (out_of_memory) {
  ------------------
  |  Branch (163:9): [True: 0, False: 19.1k]
  ------------------
  164|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Out of Memory error occurred while parsing JSON file %s.",
  165|      0|                   filename);
  166|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  167|      0|        goto out;
  168|  19.1k|    } else if (*json == NULL) {
  ------------------
  |  Branch (168:16): [True: 7.21k, False: 11.9k]
  ------------------
  169|  7.21k|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Invalid JSON file %s.", filename);
  170|  7.21k|        goto out;
  171|  7.21k|    }
  172|       |
  173|  19.4k|out:
  174|  19.4k|    loader_instance_heap_free(inst, json_buf);
  175|  19.4k|    if (res != VK_SUCCESS && *json != NULL) {
  ------------------
  |  Branch (175:9): [True: 251, False: 19.1k]
  |  Branch (175:30): [True: 0, False: 251]
  ------------------
  176|      0|        loader_cJSON_Delete(*json);
  177|      0|        *json = NULL;
  178|      0|    }
  179|       |
  180|  19.4k|    return res;
  181|  19.1k|}
loader_parse_json_string_to_existing_str:
  183|   382k|VkResult loader_parse_json_string_to_existing_str(cJSON *object, const char *key, size_t out_str_len, char *out_string) {
  184|   382k|    if (NULL == key) {
  ------------------
  |  Branch (184:9): [True: 0, False: 382k]
  ------------------
  185|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  186|      0|    }
  187|   382k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  188|   382k|    if (NULL == item) {
  ------------------
  |  Branch (188:9): [True: 51.2k, False: 330k]
  ------------------
  189|  51.2k|        return VK_ERROR_INITIALIZATION_FAILED;
  190|  51.2k|    }
  191|       |
  192|   330k|    if (item->type != cJSON_String || item->valuestring == NULL) {
  ------------------
  |  |  101|   661k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (192:9): [True: 28.9k, False: 301k]
  |  Branch (192:39): [True: 0, False: 301k]
  ------------------
  193|  28.9k|        return VK_ERROR_INITIALIZATION_FAILED;
  194|  28.9k|    }
  195|   330k|    bool out_of_memory = false;
  196|   301k|    bool success = loader_cJSON_PrintPreallocated(item, out_string, (int)out_str_len, cJSON_False);
  ------------------
  |  |   97|   301k|#define cJSON_False (1 << 0)
  ------------------
  197|   301k|    if (out_of_memory) {
  ------------------
  |  Branch (197:9): [True: 0, False: 301k]
  ------------------
  198|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  199|      0|    }
  200|   301k|    if (!success) {
  ------------------
  |  Branch (200:9): [True: 1.26k, False: 300k]
  ------------------
  201|  1.26k|        return VK_ERROR_INITIALIZATION_FAILED;
  202|  1.26k|    }
  203|   300k|    return VK_SUCCESS;
  204|   301k|}
loader_parse_json_string:
  206|  67.4k|VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string) {
  207|  67.4k|    if (NULL == key) {
  ------------------
  |  Branch (207:9): [True: 0, False: 67.4k]
  ------------------
  208|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  209|      0|    }
  210|       |
  211|  67.4k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  212|  67.4k|    if (NULL == item || NULL == item->valuestring) {
  ------------------
  |  Branch (212:9): [True: 26.6k, False: 40.8k]
  |  Branch (212:25): [True: 545, False: 40.2k]
  ------------------
  213|  27.2k|        return VK_ERROR_INITIALIZATION_FAILED;
  214|  27.2k|    }
  215|       |
  216|  67.4k|    bool out_of_memory = false;
  217|  40.2k|    char *str = loader_cJSON_Print(item, &out_of_memory);
  218|  40.2k|    if (out_of_memory || NULL == str) {
  ------------------
  |  Branch (218:9): [True: 0, False: 40.2k]
  |  Branch (218:26): [True: 0, False: 40.2k]
  ------------------
  219|      0|        return VK_ERROR_OUT_OF_HOST_MEMORY;
  220|      0|    }
  221|  40.2k|    if (NULL != out_string) {
  ------------------
  |  Branch (221:9): [True: 40.2k, False: 0]
  ------------------
  222|  40.2k|        *out_string = str;
  223|  40.2k|    }
  224|  40.2k|    return VK_SUCCESS;
  225|  40.2k|}
loader_parse_json_array_of_strings:
  227|  30.7k|                                            struct loader_string_list *string_list) {
  228|  30.7k|    if (NULL == key) {
  ------------------
  |  Branch (228:9): [True: 0, False: 30.7k]
  ------------------
  229|      0|        return VK_ERROR_INITIALIZATION_FAILED;
  230|      0|    }
  231|  30.7k|    cJSON *item = loader_cJSON_GetObjectItem(object, key);
  232|  30.7k|    if (NULL == item) {
  ------------------
  |  Branch (232:9): [True: 18.1k, False: 12.5k]
  ------------------
  233|  18.1k|        return VK_ERROR_INITIALIZATION_FAILED;
  234|  18.1k|    }
  235|       |
  236|  12.5k|    uint32_t count = loader_cJSON_GetArraySize(item);
  237|  12.5k|    if (count == 0) {
  ------------------
  |  Branch (237:9): [True: 985, False: 11.5k]
  ------------------
  238|    985|        return VK_SUCCESS;
  239|    985|    }
  240|       |
  241|  11.5k|    VkResult res = create_string_list(inst, count, string_list);
  242|  11.5k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (242:9): [True: 0, False: 11.5k]
  ------------------
  243|      0|        goto out;
  244|      0|    }
  245|  11.5k|    cJSON *element = NULL;
  246|  87.2k|    cJSON_ArrayForEach(element, item) {
  ------------------
  |  |  213|  96.7k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 11.5k, False: 0]
  |  |  |  Branch (213:61): [True: 87.2k, False: 9.47k]
  |  |  ------------------
  ------------------
  247|  87.2k|        if (element->type != cJSON_String) {
  ------------------
  |  |  101|  87.2k|#define cJSON_String (1 << 4)
  ------------------
  |  Branch (247:13): [True: 2.06k, False: 85.1k]
  ------------------
  248|  2.06k|            return VK_ERROR_INITIALIZATION_FAILED;
  249|  2.06k|        }
  250|  87.2k|        bool out_of_memory = false;
  251|  85.1k|        char *out_data = loader_cJSON_Print(element, &out_of_memory);
  252|  85.1k|        if (out_of_memory) {
  ------------------
  |  Branch (252:13): [True: 0, False: 85.1k]
  ------------------
  253|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  254|      0|            goto out;
  255|      0|        }
  256|  85.1k|        res = append_str_to_string_list(inst, string_list, out_data);
  257|  85.1k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (257:13): [True: 0, False: 85.1k]
  ------------------
  258|      0|            goto out;
  259|      0|        }
  260|  85.1k|    }
  261|  9.47k|out:
  262|  9.47k|    if (res == VK_ERROR_OUT_OF_HOST_MEMORY && NULL != string_list->list) {
  ------------------
  |  Branch (262:9): [True: 0, False: 9.47k]
  |  Branch (262:47): [True: 0, False: 0]
  ------------------
  263|      0|        free_string_list(inst, string_list);
  264|      0|    }
  265|       |
  266|  9.47k|    return res;
  267|  11.5k|}
loader_json.c:loader_read_entire_file:
   98|  19.4k|                                        char **out_buff) {
   99|  19.4k|    FILE *file = NULL;
  100|  19.4k|    struct stat stats = {0};
  101|  19.4k|    VkResult res = VK_SUCCESS;
  102|       |
  103|       |    // fprintf(stderr, "loader_get_json: Reading JSON file %s\n", filename);
  104|  19.4k|    file = fopen(filename, "rb");
  105|  19.4k|#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  106|  19.4k|    if (file == NULL) {
  ------------------
  |  Branch (106:9): [True: 5.23k, False: 14.2k]
  ------------------
  107|  5.23k|        create_callback_file(filename);
  108|  5.23k|        file = fopen(filename, "rb");
  109|  5.23k|    }
  110|  19.4k|#endif
  111|  19.4k|    if (NULL == file) {
  ------------------
  |  Branch (111:9): [True: 188, False: 19.2k]
  ------------------
  112|    188|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to open JSON file %s", filename);
  113|    188|        res = VK_ERROR_INITIALIZATION_FAILED;
  114|    188|        goto out;
  115|    188|    }
  116|  19.2k|    if (-1 == fstat(fileno(file), &stats)) {
  ------------------
  |  Branch (116:9): [True: 0, False: 19.2k]
  ------------------
  117|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read file size of JSON file %s", filename);
  118|      0|        res = VK_ERROR_INITIALIZATION_FAILED;
  119|      0|        goto out;
  120|      0|    }
  121|  19.2k|    *out_buff = (char *)loader_instance_heap_calloc(inst, stats.st_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  122|  19.2k|    if (NULL == *out_buff) {
  ------------------
  |  Branch (122:9): [True: 0, False: 19.2k]
  ------------------
  123|      0|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to allocate memory to read JSON file %s", filename);
  124|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  125|      0|        goto out;
  126|      0|    }
  127|  19.2k|    if (stats.st_size != (long int)fread(*out_buff, sizeof(char), stats.st_size, file)) {
  ------------------
  |  Branch (127:9): [True: 63, False: 19.1k]
  ------------------
  128|     63|        loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_get_json: Failed to read entire JSON file %s", filename);
  129|     63|        res = VK_ERROR_INITIALIZATION_FAILED;
  130|     63|        goto out;
  131|     63|    }
  132|  19.1k|    *out_len = stats.st_size + 1;
  133|  19.1k|    (*out_buff)[stats.st_size] = '\0';
  134|       |
  135|  19.4k|out:
  136|  19.4k|    if (NULL != file) {
  ------------------
  |  Branch (136:9): [True: 19.2k, False: 188]
  ------------------
  137|  19.2k|        fclose(file);
  138|  19.2k|    }
  139|  19.4k|    return res;
  140|  19.1k|}

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

free_layer_configuration:
   41|  10.9k|void free_layer_configuration(const struct loader_instance* inst, loader_settings_layer_configuration* layer_configuration) {
   42|  10.9k|    loader_instance_heap_free(inst, layer_configuration->name);
   43|  10.9k|    loader_instance_heap_free(inst, layer_configuration->path);
   44|  10.9k|    memset(layer_configuration, 0, sizeof(loader_settings_layer_configuration));
   45|  10.9k|}
free_loader_settings:
   57|  6.52k|void free_loader_settings(const struct loader_instance* inst, loader_settings* settings) {
   58|  6.52k|    if (NULL != settings->layer_configurations) {
  ------------------
  |  Branch (58:9): [True: 2.09k, False: 4.43k]
  ------------------
   59|  12.1k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (59:30): [True: 10.0k, False: 2.09k]
  ------------------
   60|  10.0k|            free_layer_configuration(inst, &settings->layer_configurations[i]);
   61|  10.0k|        }
   62|  2.09k|        loader_instance_heap_free(inst, settings->layer_configurations);
   63|  2.09k|    }
   64|  6.52k|    if (NULL != settings->additional_drivers) {
  ------------------
  |  Branch (64:9): [True: 0, False: 6.52k]
  ------------------
   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|  6.52k|    if (NULL != settings->device_configurations) {
  ------------------
  |  Branch (70:9): [True: 0, False: 6.52k]
  ------------------
   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|  6.52k|    loader_instance_heap_free(inst, settings->settings_file_path);
   77|  6.52k|    memset(settings, 0, sizeof(loader_settings));
   78|  6.52k|}
parse_control_string:
   80|  10.3k|loader_settings_layer_control parse_control_string(char* control_string) {
   81|  10.3k|    loader_settings_layer_control layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   82|  10.3k|    if (strcmp(control_string, "auto") == 0)
  ------------------
  |  Branch (82:9): [True: 1.36k, False: 8.96k]
  ------------------
   83|  1.36k|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
   84|  8.96k|    else if (strcmp(control_string, "on") == 0)
  ------------------
  |  Branch (84:14): [True: 107, False: 8.85k]
  ------------------
   85|    107|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_ON;
   86|  8.85k|    else if (strcmp(control_string, "off") == 0)
  ------------------
  |  Branch (86:14): [True: 367, False: 8.49k]
  ------------------
   87|    367|        layer_control = LOADER_SETTINGS_LAYER_CONTROL_OFF;
   88|  8.49k|    else if (strcmp(control_string, "unordered_layer_location") == 0)
  ------------------
  |  Branch (88:14): [True: 645, False: 7.84k]
  ------------------
   89|    645|        layer_control = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
   90|  10.3k|    return layer_control;
   91|  10.3k|}
loader_settings_layer_control_to_string:
   93|  10.0k|const char* loader_settings_layer_control_to_string(loader_settings_layer_control control) {
   94|  10.0k|    switch (control) {
   95|  8.97k|        case (LOADER_SETTINGS_LAYER_CONTROL_DEFAULT):
  ------------------
  |  Branch (95:9): [True: 8.97k, False: 1.09k]
  ------------------
   96|  8.97k|            return "auto";
   97|     86|        case (LOADER_SETTINGS_LAYER_CONTROL_ON):
  ------------------
  |  Branch (97:9): [True: 86, False: 9.98k]
  ------------------
   98|     86|            return "on";
   99|    364|        case (LOADER_SETTINGS_LAYER_CONTROL_OFF):
  ------------------
  |  Branch (99:9): [True: 364, False: 9.70k]
  ------------------
  100|    364|            return "off";
  101|    644|        case (LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION):
  ------------------
  |  Branch (101:9): [True: 644, False: 9.42k]
  ------------------
  102|    644|            return "unordered_layer_location";
  103|      0|        default:
  ------------------
  |  Branch (103:9): [True: 0, False: 10.0k]
  ------------------
  104|      0|            return "UNKNOWN_LAYER_CONTROl";
  105|  10.0k|    }
  106|  10.0k|}
parse_log_filters_from_strings:
  108|    404|uint32_t parse_log_filters_from_strings(struct loader_string_list* log_filters) {
  109|    404|    uint32_t filters = 0;
  110|  4.47k|    for (uint32_t i = 0; i < log_filters->count; i++) {
  ------------------
  |  Branch (110:26): [True: 4.06k, False: 404]
  ------------------
  111|  4.06k|        if (strcmp(log_filters->list[i], "all") == 0)
  ------------------
  |  Branch (111:13): [True: 121, False: 3.94k]
  ------------------
  112|    121|            filters |= VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_PERF_BIT | VULKAN_LOADER_ERROR_BIT |
  113|    121|                       VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT | VULKAN_LOADER_VALIDATION_BIT;
  114|  3.94k|        else if (strcmp(log_filters->list[i], "info") == 0)
  ------------------
  |  Branch (114:18): [True: 265, False: 3.68k]
  ------------------
  115|    265|            filters |= VULKAN_LOADER_INFO_BIT;
  116|  3.68k|        else if (strcmp(log_filters->list[i], "warn") == 0)
  ------------------
  |  Branch (116:18): [True: 187, False: 3.49k]
  ------------------
  117|    187|            filters |= VULKAN_LOADER_WARN_BIT;
  118|  3.49k|        else if (strcmp(log_filters->list[i], "perf") == 0)
  ------------------
  |  Branch (118:18): [True: 388, False: 3.10k]
  ------------------
  119|    388|            filters |= VULKAN_LOADER_PERF_BIT;
  120|  3.10k|        else if (strcmp(log_filters->list[i], "error") == 0)
  ------------------
  |  Branch (120:18): [True: 55, False: 3.05k]
  ------------------
  121|     55|            filters |= VULKAN_LOADER_ERROR_BIT;
  122|  3.05k|        else if (strcmp(log_filters->list[i], "debug") == 0)
  ------------------
  |  Branch (122:18): [True: 256, False: 2.79k]
  ------------------
  123|    256|            filters |= VULKAN_LOADER_DEBUG_BIT;
  124|  2.79k|        else if (strcmp(log_filters->list[i], "layer") == 0)
  ------------------
  |  Branch (124:18): [True: 211, False: 2.58k]
  ------------------
  125|    211|            filters |= VULKAN_LOADER_LAYER_BIT;
  126|  2.58k|        else if (strcmp(log_filters->list[i], "driver") == 0)
  ------------------
  |  Branch (126:18): [True: 193, False: 2.39k]
  ------------------
  127|    193|            filters |= VULKAN_LOADER_DRIVER_BIT;
  128|  2.39k|        else if (strcmp(log_filters->list[i], "validation") == 0)
  ------------------
  |  Branch (128:18): [True: 34, False: 2.35k]
  ------------------
  129|     34|            filters |= VULKAN_LOADER_VALIDATION_BIT;
  130|  4.06k|    }
  131|    404|    return filters;
  132|    404|}
parse_layer_configuration:
  147|  10.3k|                                   loader_settings_layer_configuration* layer_configuration) {
  148|  10.3k|    char* control_string = NULL;
  149|  10.3k|    VkResult res = loader_parse_json_string(layer_configuration_json, "control", &control_string);
  150|  10.3k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (150:9): [True: 9, False: 10.3k]
  ------------------
  151|      9|        goto out;
  152|      9|    }
  153|  10.3k|    layer_configuration->control = parse_control_string(control_string);
  154|  10.3k|    loader_instance_heap_free(inst, control_string);
  155|       |
  156|       |    // If that is the only value - do no further parsing
  157|  10.3k|    if (layer_configuration->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (157:9): [True: 645, False: 9.68k]
  ------------------
  158|    645|        goto out;
  159|    645|    }
  160|       |
  161|  9.68k|    res = loader_parse_json_string(layer_configuration_json, "name", &(layer_configuration->name));
  162|  9.68k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (162:9): [True: 71, False: 9.61k]
  ------------------
  163|     71|        goto out;
  164|     71|    }
  165|       |
  166|  9.61k|    res = loader_parse_json_string(layer_configuration_json, "path", &(layer_configuration->path));
  167|  9.61k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (167:9): [True: 15, False: 9.59k]
  ------------------
  168|     15|        goto out;
  169|     15|    }
  170|       |
  171|  9.59k|    cJSON* treat_as_implicit_manifest = loader_cJSON_GetObjectItem(layer_configuration_json, "treat_as_implicit_manifest");
  172|  9.59k|    if (treat_as_implicit_manifest && treat_as_implicit_manifest->type == cJSON_True) {
  ------------------
  |  |   98|    391|#define cJSON_True (1 << 1)
  ------------------
  |  Branch (172:9): [True: 391, False: 9.20k]
  |  Branch (172:39): [True: 371, False: 20]
  ------------------
  173|    371|        layer_configuration->treat_as_implicit_manifest = true;
  174|    371|    }
  175|  10.3k|out:
  176|  10.3k|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (176:9): [True: 95, False: 10.2k]
  ------------------
  177|     95|        free_layer_configuration(inst, layer_configuration);
  178|     95|    }
  179|  10.3k|    return res;
  180|  9.59k|}
parse_layer_configurations:
  182|  2.50k|VkResult parse_layer_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  183|  2.50k|    VkResult res = VK_SUCCESS;
  184|       |
  185|  2.50k|    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|  2.50k|    if (NULL == layer_configurations) {
  ------------------
  |  Branch (187:9): [True: 311, False: 2.19k]
  ------------------
  188|    311|        return VK_SUCCESS;
  189|    311|    }
  190|       |
  191|  2.19k|    uint32_t layer_configurations_count = loader_cJSON_GetArraySize(layer_configurations);
  192|  2.19k|    if (layer_configurations_count == 0) {
  ------------------
  |  Branch (192:9): [True: 4, False: 2.19k]
  ------------------
  193|      4|        loader_settings->layer_configurations_active = true;
  194|      4|        return VK_SUCCESS;
  195|      4|    }
  196|       |
  197|  2.19k|    loader_settings->layer_configuration_count = layer_configurations_count;
  198|       |
  199|  2.19k|    loader_settings->layer_configurations = loader_instance_heap_calloc(
  200|  2.19k|        inst, sizeof(loader_settings_layer_configuration) * layer_configurations_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  201|  2.19k|    if (NULL == loader_settings->layer_configurations) {
  ------------------
  |  Branch (201:9): [True: 0, False: 2.19k]
  ------------------
  202|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  203|      0|        goto out;
  204|      0|    }
  205|       |
  206|  2.19k|    cJSON* layer = NULL;
  207|  2.19k|    size_t i = 0;
  208|  10.3k|    cJSON_ArrayForEach(layer, layer_configurations) {
  ------------------
  |  |  213|  12.4k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 2.19k, False: 0]
  |  |  |  Branch (213:61): [True: 10.3k, False: 2.09k]
  |  |  ------------------
  ------------------
  209|  10.3k|        if (layer->type != cJSON_Object) {
  ------------------
  |  |  103|  10.3k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (209:13): [True: 7, False: 10.3k]
  ------------------
  210|      7|            res = VK_ERROR_INITIALIZATION_FAILED;
  211|      7|            goto out;
  212|      7|        }
  213|  10.3k|        res = parse_layer_configuration(inst, layer, &(loader_settings->layer_configurations[i++]));
  214|  10.3k|        if (VK_SUCCESS != res) {
  ------------------
  |  Branch (214:13): [True: 95, False: 10.2k]
  ------------------
  215|     95|            goto out;
  216|     95|        }
  217|  10.3k|    }
  218|  2.09k|    loader_settings->layer_configurations_active = true;
  219|  2.19k|out:
  220|  2.19k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (220:9): [True: 102, False: 2.09k]
  ------------------
  221|    102|        if (loader_settings->layer_configurations) {
  ------------------
  |  Branch (221:13): [True: 102, False: 0]
  ------------------
  222|    841|            for (size_t index = 0; index < loader_settings->layer_configuration_count; index++) {
  ------------------
  |  Branch (222:36): [True: 739, False: 102]
  ------------------
  223|    739|                free_layer_configuration(inst, &(loader_settings->layer_configurations[index]));
  224|    739|            }
  225|    102|            loader_settings->layer_configuration_count = 0;
  226|    102|            loader_instance_heap_free(inst, loader_settings->layer_configurations);
  227|    102|            loader_settings->layer_configurations = NULL;
  228|    102|        }
  229|    102|    }
  230|       |
  231|  2.19k|    return res;
  232|  2.09k|}
parse_additional_drivers:
  248|  2.50k|VkResult parse_additional_drivers(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  249|  2.50k|    VkResult res = VK_SUCCESS;
  250|       |
  251|  2.50k|    cJSON* additional_drivers_use_exclusively_json =
  252|  2.50k|        loader_cJSON_GetObjectItem(settings_object, "additional_drivers_use_exclusively");
  253|  2.50k|    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: 2.50k]
  |  Branch (253:52): [True: 0, False: 0]
  ------------------
  254|      0|        loader_settings->additional_drivers_use_exclusively = true;
  255|      0|    }
  256|       |
  257|  2.50k|    cJSON* additional_drivers_json = loader_cJSON_GetObjectItem(settings_object, "additional_drivers");
  258|  2.50k|    if (NULL == additional_drivers_json) {
  ------------------
  |  Branch (258:9): [True: 2.50k, False: 0]
  ------------------
  259|  2.50k|        return VK_SUCCESS;
  260|  2.50k|    }
  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_layer_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:
  375|  2.50k|VkResult parse_device_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
  376|  2.50k|    VkResult res = VK_SUCCESS;
  377|       |
  378|  2.50k|    cJSON* device_configurations = loader_cJSON_GetObjectItem(settings_object, "device_configurations");
  379|  2.50k|    if (NULL == device_configurations) {
  ------------------
  |  Branch (379:9): [True: 2.50k, False: 0]
  ------------------
  380|  2.50k|        return VK_SUCCESS;
  381|  2.50k|    }
  382|       |
  383|      0|    uint32_t device_configuration_count = loader_cJSON_GetArraySize(device_configurations);
  384|      0|    if (device_configuration_count == 0) {
  ------------------
  |  Branch (384:9): [True: 0, False: 0]
  ------------------
  385|      0|        loader_settings->device_configurations_active = true;
  386|      0|        return VK_SUCCESS;
  387|      0|    }
  388|       |
  389|      0|    loader_settings->device_configuration_count = device_configuration_count;
  390|       |
  391|      0|    loader_settings->device_configurations = loader_instance_heap_calloc(
  392|      0|        inst, sizeof(loader_settings_device_configuration) * device_configuration_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
  393|      0|    if (NULL == loader_settings->device_configurations) {
  ------------------
  |  Branch (393:9): [True: 0, False: 0]
  ------------------
  394|      0|        res = VK_ERROR_OUT_OF_HOST_MEMORY;
  395|      0|        goto out;
  396|      0|    }
  397|       |
  398|      0|    cJSON* device = NULL;
  399|      0|    size_t i = 0;
  400|      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]
  |  |  ------------------
  ------------------
  401|      0|        if (device->type != cJSON_Object) {
  ------------------
  |  |  103|      0|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (401:13): [True: 0, False: 0]
  ------------------
  402|      0|            res = VK_ERROR_INITIALIZATION_FAILED;
  403|      0|            goto out;
  404|      0|        }
  405|      0|        res = parse_device_configuration(inst, device, &(loader_settings->device_configurations[i]));
  406|      0|        if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (406:13): [True: 0, False: 0]
  ------------------
  407|      0|            goto out;
  408|      0|        } else if (res != VK_SUCCESS) {
  ------------------
  |  Branch (408:20): [True: 0, False: 0]
  ------------------
  409|      0|            continue;
  410|      0|        }
  411|      0|        i++;
  412|      0|    }
  413|      0|    loader_settings->device_configurations_active = true;
  414|      0|out:
  415|      0|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (415:9): [True: 0, False: 0]
  ------------------
  416|      0|        if (loader_settings->device_configurations) {
  ------------------
  |  Branch (416:13): [True: 0, False: 0]
  ------------------
  417|      0|            for (size_t index = 0; index < loader_settings->device_configuration_count; index++) {
  ------------------
  |  Branch (417:36): [True: 0, False: 0]
  ------------------
  418|      0|                free_device_configuration(inst, &(loader_settings->device_configurations[index]));
  419|      0|            }
  420|      0|            loader_settings->device_configuration_count = 0;
  421|      0|            loader_instance_heap_free(inst, loader_settings->device_configurations);
  422|       |            loader_settings->device_configurations = NULL;
  423|      0|        }
  424|      0|    }
  425|      0|    return res;
  426|      0|}
check_if_settings_path_exists:
  433|  28.6k|                                       char** settings_file_path) {
  434|  28.6k|    if (NULL == base || NULL == suffix) {
  ------------------
  |  Branch (434:9): [True: 13.0k, False: 15.6k]
  |  Branch (434:25): [True: 0, False: 15.6k]
  ------------------
  435|  13.0k|        return VK_ERROR_INITIALIZATION_FAILED;
  436|  13.0k|    }
  437|       |
  438|  15.6k|    size_t base_len = strlen(base);
  439|  15.6k|    size_t suffix_len = strlen(suffix);
  440|       |
  441|  15.6k|    uint32_t start = 0;
  442|  15.6k|    uint32_t stop = 0;
  443|  26.0k|    while (base[start] != '\0' && start < base_len && stop < base_len) {
  ------------------
  |  Branch (443:12): [True: 26.0k, False: 0]
  |  Branch (443:35): [True: 26.0k, False: 0]
  |  Branch (443:55): [True: 16.2k, False: 9.76k]
  ------------------
  444|  16.2k|        start = stop;
  445|  16.2k|        stop = start + 1;
  446|  86.5k|        while (base[stop] != PATH_SEPARATOR && base[stop] != '\0' && stop < base_len) {
  ------------------
  |  |  150|   173k|#define PATH_SEPARATOR ':'
  ------------------
  |  Branch (446:16): [True: 85.8k, False: 648]
  |  Branch (446:48): [True: 70.2k, False: 15.6k]
  |  Branch (446:70): [True: 70.2k, False: 0]
  ------------------
  447|  70.2k|            stop++;
  448|  70.2k|        }
  449|       |
  450|  16.2k|        size_t segment_len = (stop - start);
  451|  16.2k|        if (segment_len <= 1) {
  ------------------
  |  Branch (451:13): [True: 0, False: 16.2k]
  ------------------
  452|       |            // segment is *just* a PATH_SEPARATOR, skip it
  453|      0|            continue;
  454|      0|        }
  455|  16.2k|        size_t path_len = segment_len + suffix_len + 1;
  456|  16.2k|        *settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
  457|  16.2k|        if (NULL == *settings_file_path) {
  ------------------
  |  Branch (457:13): [True: 0, False: 16.2k]
  ------------------
  458|      0|            return VK_ERROR_OUT_OF_HOST_MEMORY;
  459|      0|        }
  460|  16.2k|        loader_strncpy(*settings_file_path, path_len, base + start, segment_len);
  461|  16.2k|        loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
  462|       |
  463|  16.2k|        if (loader_platform_file_exists(*settings_file_path)) {
  ------------------
  |  Branch (463:13): [True: 5.87k, False: 10.4k]
  ------------------
  464|  5.87k|            return VK_SUCCESS;
  465|  5.87k|        }
  466|  10.4k|        loader_instance_heap_free(inst, *settings_file_path);
  467|  10.4k|        *settings_file_path = NULL;
  468|  10.4k|    }
  469|       |
  470|  9.76k|    return VK_ERROR_INITIALIZATION_FAILED;
  471|  15.6k|}
get_unix_settings_path:
  474|  6.52k|VkResult get_unix_settings_path(const struct loader_instance* inst, char** settings_file_path) {
  475|       |    // First, get XDG env-vars we use. Don't need to worry about free'ing because on linux getenv is non-allocating
  476|  6.52k|    char* xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
  477|  6.52k|    char* xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
  478|  6.52k|    char* xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
  479|  6.52k|    char* xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
  480|       |
  481|       |    // Use fallback directories for xdg_config_dirs and xdg_data_dirs if they are NULL.
  482|  6.52k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  483|  6.52k|    if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
  ------------------
  |  Branch (483:9): [True: 6.52k, False: 0]
  |  Branch (483:36): [True: 0, False: 0]
  ------------------
  484|  6.52k|        xdg_config_dirs = FALLBACK_CONFIG_DIRS;
  485|  6.52k|    }
  486|  6.52k|#endif
  487|       |
  488|  6.52k|#if !defined(__Fuchsia__) && !defined(__QNX__)
  489|  6.52k|    if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
  ------------------
  |  Branch (489:9): [True: 6.52k, False: 0]
  |  Branch (489:34): [True: 0, False: 0]
  ------------------
  490|  6.52k|        xdg_data_dirs = FALLBACK_DATA_DIRS;
  491|  6.52k|    }
  492|  6.52k|#endif
  493|       |
  494|  6.52k|    VkResult res = check_if_settings_path_exists(
  495|  6.52k|        inst, xdg_config_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  6.52k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  496|  6.52k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (496:9): [True: 0, False: 6.52k]
  ------------------
  497|      0|        return res;
  498|      0|    }
  499|       |
  500|  6.52k|    res = check_if_settings_path_exists(inst, xdg_data_home, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|  6.52k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  501|  6.52k|                                        settings_file_path);
  502|  6.52k|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (502:9): [True: 0, False: 6.52k]
  ------------------
  503|      0|        return res;
  504|      0|    }
  505|       |
  506|       |    // Check home if either xdg_config_home or xdg_data_home wasn't set
  507|  6.52k|    char* home = loader_secure_getenv("HOME", inst);
  508|  6.52k|    if (home != NULL) {
  ------------------
  |  Branch (508:9): [True: 6.52k, False: 0]
  ------------------
  509|  6.52k|        if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
  ------------------
  |  Branch (509:13): [True: 6.52k, False: 0]
  |  Branch (509:40): [True: 0, False: 0]
  ------------------
  510|  6.52k|            res = check_if_settings_path_exists(
  511|  6.52k|                inst, home, "/.config/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  6.52k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  512|  6.52k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (512:17): [True: 0, False: 6.52k]
  ------------------
  513|      0|                return res;
  514|      0|            }
  515|  6.52k|        }
  516|  6.52k|        if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
  ------------------
  |  Branch (516:13): [True: 6.52k, False: 0]
  |  Branch (516:38): [True: 0, False: 0]
  ------------------
  517|  6.52k|            res = check_if_settings_path_exists(
  518|  6.52k|                inst, home, "/.local/share/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
  ------------------
  |  |  141|  6.52k|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  519|  6.52k|            if (res == VK_SUCCESS) {
  ------------------
  |  Branch (519:17): [True: 5.87k, False: 648]
  ------------------
  520|  5.87k|                return res;
  521|  5.87k|            }
  522|  6.52k|        }
  523|  6.52k|    }
  524|       |
  525|    648|    res = check_if_settings_path_exists(inst, xdg_config_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|    648|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  526|    648|                                        settings_file_path);
  527|    648|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (527:9): [True: 0, False: 648]
  ------------------
  528|      0|        return res;
  529|      0|    }
  530|       |
  531|    648|    res = check_if_settings_path_exists(inst, SYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|    648|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  532|    648|                                        settings_file_path);
  533|    648|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (533:9): [True: 0, False: 648]
  ------------------
  534|      0|        return res;
  535|      0|    }
  536|    648|#if defined(EXTRASYSCONFDIR)
  537|       |
  538|    648|    res = check_if_settings_path_exists(inst, EXTRASYSCONFDIR, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|    648|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  539|    648|                                        settings_file_path);
  540|    648|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (540:9): [True: 0, False: 648]
  ------------------
  541|      0|        return res;
  542|      0|    }
  543|    648|#endif
  544|    648|    res = check_if_settings_path_exists(inst, xdg_data_dirs, "/" VULKAN_DIR "/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
  ------------------
  |  |  141|    648|#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
  ------------------
  545|    648|                                        settings_file_path);
  546|    648|    if (res == VK_SUCCESS) {
  ------------------
  |  Branch (546:9): [True: 0, False: 648]
  ------------------
  547|      0|        return res;
  548|      0|    }
  549|       |
  550|    648|    return VK_ERROR_INITIALIZATION_FAILED;
  551|    648|}
log_settings:
  610|  2.17k|void log_settings(const struct loader_instance* inst, loader_settings* settings) {
  611|  2.17k|    if (settings == NULL) {
  ------------------
  |  Branch (611:9): [True: 0, False: 2.17k]
  ------------------
  612|      0|        return;
  613|      0|    }
  614|  2.17k|    loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Using layer configurations found in loader settings from %s",
  615|  2.17k|               settings->settings_file_path);
  616|       |
  617|  2.17k|    char cmd_line_msg[64] = {0};
  618|  2.17k|    size_t cmd_line_size = sizeof(cmd_line_msg);
  619|       |
  620|  2.17k|    cmd_line_msg[0] = '\0';
  621|       |
  622|  2.17k|    generate_debug_flag_str(settings->debug_level, cmd_line_size, cmd_line_msg);
  623|  2.17k|    if (strlen(cmd_line_msg)) {
  ------------------
  |  Branch (623:9): [True: 178, False: 2.00k]
  ------------------
  624|    178|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Loader Settings Filters for Logging to Standard Error: %s", cmd_line_msg);
  625|    178|    }
  626|  2.17k|    if (settings->layer_configurations_active) {
  ------------------
  |  Branch (626:9): [True: 2.09k, False: 82]
  ------------------
  627|  2.09k|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Configurations count = %d", settings->layer_configuration_count);
  628|  12.1k|        for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (628:30): [True: 10.0k, False: 2.09k]
  ------------------
  629|  10.0k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Layer Configuration [%d] ----", i);
  630|  10.0k|            if (settings->layer_configurations[i].control != LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (630:17): [True: 9.42k, False: 644]
  ------------------
  631|  9.42k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Name: %s", settings->layer_configurations[i].name);
  632|  9.42k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->layer_configurations[i].path);
  633|  9.42k|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Type: %s",
  634|  9.42k|                           settings->layer_configurations[i].treat_as_implicit_manifest ? "Implicit" : "Explicit");
  ------------------
  |  Branch (634:28): [True: 345, False: 9.07k]
  ------------------
  635|  9.42k|            }
  636|  10.0k|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Control: %s",
  637|  10.0k|                       loader_settings_layer_control_to_string(settings->layer_configurations[i].control));
  638|  10.0k|        }
  639|  2.09k|    }
  640|  2.17k|    if (settings->additional_driver_count > 0) {
  ------------------
  |  Branch (640:9): [True: 0, False: 2.17k]
  ------------------
  641|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  642|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Use Additional Drivers Exclusively = %s",
  643|      0|                   settings->additional_drivers_use_exclusively ? "true" : "false");
  ------------------
  |  Branch (643:20): [True: 0, False: 0]
  ------------------
  644|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Additional Driver Configurations count = %d",
  645|      0|                   settings->additional_driver_count);
  646|      0|        for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (646:30): [True: 0, False: 0]
  ------------------
  647|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Driver Configuration [%d] ----", i);
  648|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->additional_drivers[i].path);
  649|      0|        }
  650|      0|    }
  651|  2.17k|    if (settings->device_configurations_active) {
  ------------------
  |  Branch (651:9): [True: 0, False: 2.17k]
  ------------------
  652|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "----");
  653|      0|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Device Configurations count = %d", settings->device_configuration_count);
  654|      0|        for (uint32_t i = 0; i < settings->device_configuration_count; i++) {
  ------------------
  |  Branch (654:30): [True: 0, False: 0]
  ------------------
  655|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Device Configuration [%d] ----", i);
  656|      0|            char device_uuid_str[UUID_STR_LEN] = {0};
  657|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].deviceUUID, device_uuid_str);
  658|      0|            char driver_uuid_str[UUID_STR_LEN] = {0};
  659|      0|            loader_log_generate_uuid_string(settings->device_configurations[i].driverUUID, driver_uuid_str);
  660|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceUUID: %s", device_uuid_str);
  661|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverUUID: %s", driver_uuid_str);
  662|      0|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverVersion: %d", settings->device_configurations[i].driverVersion);
  663|      0|            if ('\0' != settings->device_configurations[i].deviceName[0]) {
  ------------------
  |  Branch (663:17): [True: 0, False: 0]
  ------------------
  664|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "deviceName: %s", settings->device_configurations[i].deviceName);
  665|      0|            }
  666|      0|            if ('\0' != settings->device_configurations[i].driverName[0]) {
  ------------------
  |  Branch (666:17): [True: 0, False: 0]
  ------------------
  667|      0|                loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "driverName: %s", settings->device_configurations[i].driverName);
  668|      0|            }
  669|      0|        }
  670|      0|    }
  671|  2.17k|    loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------");
  672|  2.17k|}
get_loader_settings:
  677|  6.52k|VkResult get_loader_settings(const struct loader_instance* inst, loader_settings* loader_settings) {
  678|  6.52k|    VkResult res = VK_SUCCESS;
  679|  6.52k|    cJSON* json = NULL;
  680|  6.52k|    char* file_format_version_string = NULL;
  681|  6.52k|    char* settings_file_path = NULL;
  682|       |#if defined(WIN32)
  683|       |    res = windows_get_loader_settings_file_path(inst, &settings_file_path);
  684|       |    if (res != VK_SUCCESS) {
  685|       |        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  686|       |                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  687|       |        goto out;
  688|       |    }
  689|       |
  690|       |#elif COMMON_UNIX_PLATFORMS
  691|       |    res = get_unix_settings_path(inst, &settings_file_path);
  692|  6.52k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (692:9): [True: 648, False: 5.87k]
  ------------------
  693|    648|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  694|    648|                   "No valid vk_loader_settings.json file found, no loader settings will be active");
  695|    648|        goto out;
  696|    648|    }
  697|       |#else
  698|       |#warning "Unsupported platform - must specify platform specific location for vk_loader_settings.json"
  699|       |#endif
  700|       |
  701|  5.87k|    res = loader_get_json(inst, settings_file_path, &json);
  702|       |    // Make sure sure the top level json value is an object
  703|  5.87k|    if (res != VK_SUCCESS || NULL == json || json->type != cJSON_Object) {
  ------------------
  |  |  103|  3.16k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (703:9): [True: 52, False: 5.82k]
  |  Branch (703:30): [True: 2.65k, False: 3.16k]
  |  Branch (703:46): [True: 181, False: 2.98k]
  ------------------
  704|  2.89k|        goto out;
  705|  2.89k|    }
  706|       |
  707|  2.98k|    res = loader_parse_json_string(json, "file_format_version", &file_format_version_string);
  708|  2.98k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (708:9): [True: 21, False: 2.96k]
  ------------------
  709|     21|        if (res != VK_ERROR_OUT_OF_HOST_MEMORY) {
  ------------------
  |  Branch (709:13): [True: 21, False: 0]
  ------------------
  710|     21|            loader_log(
  711|     21|                inst, VULKAN_LOADER_DEBUG_BIT, 0,
  712|     21|                "Loader settings file from %s missing required field file_format_version - no loader settings will be active",
  713|     21|                settings_file_path);
  714|     21|        }
  715|     21|        goto out;
  716|     21|    }
  717|       |
  718|       |    // Because the file may contain either a "settings_array" or a single "settings" object, we need to create a cJSON so that we
  719|       |    // can iterate on both cases with common code
  720|  2.96k|    cJSON settings_iter_parent = {0};
  721|       |
  722|  2.96k|    cJSON* settings_array = loader_cJSON_GetObjectItem(json, "settings_array");
  723|  2.96k|    cJSON* single_settings_object = loader_cJSON_GetObjectItem(json, "settings");
  724|  2.96k|    if (NULL != settings_array) {
  ------------------
  |  Branch (724:9): [True: 2.58k, False: 376]
  ------------------
  725|  2.58k|        memcpy(&settings_iter_parent, settings_array, sizeof(cJSON));
  726|  2.58k|    } else if (NULL != single_settings_object) {
  ------------------
  |  Branch (726:16): [True: 33, False: 343]
  ------------------
  727|     33|        settings_iter_parent.child = single_settings_object;
  728|    343|    } else {
  729|    343|        loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  730|    343|                   "Loader settings file from %s missing required settings objects: Either one of the \"settings\" or "
  731|    343|                   "\"settings_array\" objects must be present - no loader settings will be active",
  732|    343|                   settings_file_path);
  733|    343|        res = VK_ERROR_INITIALIZATION_FAILED;
  734|    343|        goto out;
  735|    343|    }
  736|       |
  737|       |    // Corresponds to the settings object that has no app keys
  738|  2.62k|    cJSON* global_settings = NULL;
  739|       |    // Corresponds to the settings object which has a matching app key
  740|  2.62k|    cJSON* settings_to_use = NULL;
  741|       |
  742|  2.62k|    char current_process_path[1024];
  743|  2.62k|    bool valid_exe_path = NULL != loader_platform_executable_path(current_process_path, 1024);
  744|       |
  745|  2.62k|    cJSON* settings_object_iter = NULL;
  746|  4.12k|    cJSON_ArrayForEach(settings_object_iter, &settings_iter_parent) {
  ------------------
  |  |  213|  6.65k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 2.62k, Folded]
  |  |  |  Branch (213:61): [True: 4.12k, False: 2.53k]
  |  |  ------------------
  ------------------
  747|  4.12k|        if (settings_object_iter->type != cJSON_Object) {
  ------------------
  |  |  103|  4.12k|#define cJSON_Object (1 << 6)
  ------------------
  |  Branch (747:13): [True: 88, False: 4.03k]
  ------------------
  748|     88|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  749|     88|                       "Loader settings file from %s has a settings element that is not an object", settings_file_path);
  750|     88|            break;
  751|     88|        }
  752|       |
  753|  4.03k|        cJSON* app_keys = loader_cJSON_GetObjectItem(settings_object_iter, "app_keys");
  754|  4.03k|        if (NULL == app_keys) {
  ------------------
  |  Branch (754:13): [True: 3.60k, False: 428]
  ------------------
  755|       |            // use the first 'global' settings that has no app keys as the global one
  756|  3.60k|            if (global_settings == NULL) {
  ------------------
  |  Branch (756:17): [True: 2.50k, False: 1.09k]
  ------------------
  757|  2.50k|                global_settings = settings_object_iter;
  758|  2.50k|            }
  759|  3.60k|            continue;
  760|  3.60k|        }
  761|       |        // No sense iterating if we couldn't get the executable path
  762|    428|        if (!valid_exe_path) {
  ------------------
  |  Branch (762:13): [True: 0, False: 428]
  ------------------
  763|      0|            break;
  764|      0|        }
  765|    428|        cJSON* app_key = NULL;
  766|    911|        cJSON_ArrayForEach(app_key, app_keys) {
  ------------------
  |  |  213|  1.33k|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 428, False: 0]
  |  |  |  Branch (213:61): [True: 911, False: 428]
  |  |  ------------------
  ------------------
  767|    911|            char* app_key_str = loader_cJSON_GetStringValue(app_key);
  768|    911|            if (app_key_str && strcmp(current_process_path, app_key_str) == 0) {
  ------------------
  |  Branch (768:17): [True: 511, False: 400]
  |  Branch (768:32): [True: 0, False: 511]
  ------------------
  769|      0|                settings_to_use = settings_object_iter;
  770|      0|                break;
  771|      0|            }
  772|    911|        }
  773|       |
  774|       |        // Break if we have found a matching current_process_path
  775|    428|        if (NULL != settings_to_use) {
  ------------------
  |  Branch (775:13): [True: 0, False: 428]
  ------------------
  776|      0|            break;
  777|      0|        }
  778|    428|    }
  779|       |
  780|       |    // No app specific settings match - either use global settings or exit
  781|  2.62k|    if (settings_to_use == NULL) {
  ------------------
  |  Branch (781:9): [True: 2.62k, False: 0]
  ------------------
  782|  2.62k|        if (global_settings == NULL) {
  ------------------
  |  Branch (782:13): [True: 112, False: 2.50k]
  ------------------
  783|    112|            loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0,
  784|    112|                       "Loader settings file from %s missing global settings and none of the app specific settings matched the "
  785|    112|                       "current application - no loader settings will be active",
  786|    112|                       settings_file_path);
  787|    112|            goto out;  // No global settings were found - exit
  788|  2.50k|        } else {
  789|  2.50k|            settings_to_use = global_settings;  // Global settings are present - use it
  790|  2.50k|        }
  791|  2.62k|    }
  792|       |
  793|       |    // optional
  794|  2.50k|    cJSON* stderr_filter = loader_cJSON_GetObjectItem(settings_to_use, "stderr_log");
  795|  2.50k|    if (NULL != stderr_filter) {
  ------------------
  |  Branch (795:9): [True: 404, False: 2.10k]
  ------------------
  796|    404|        struct loader_string_list stderr_log = {0};
  797|    404|        VkResult stderr_log_result = VK_SUCCESS;
  798|    404|        stderr_log_result = loader_parse_json_array_of_strings(inst, settings_to_use, "stderr_log", &stderr_log);
  799|    404|        if (VK_ERROR_OUT_OF_HOST_MEMORY == stderr_log_result) {
  ------------------
  |  Branch (799:13): [True: 0, False: 404]
  ------------------
  800|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  801|      0|            goto out;
  802|      0|        }
  803|    404|        loader_settings->debug_level = parse_log_filters_from_strings(&stderr_log);
  804|    404|        free_string_list(inst, &stderr_log);
  805|    404|    }
  806|       |
  807|       |    // optional
  808|  2.50k|    cJSON* logs_to_use = loader_cJSON_GetObjectItem(settings_to_use, "log_locations");
  809|  2.50k|    if (NULL != logs_to_use) {
  ------------------
  |  Branch (809:9): [True: 48, False: 2.46k]
  ------------------
  810|     48|        cJSON* log_element = NULL;
  811|    334|        cJSON_ArrayForEach(log_element, logs_to_use) {
  ------------------
  |  |  213|    382|    for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  |  |  ------------------
  |  |  |  Branch (213:20): [True: 48, False: 0]
  |  |  |  Branch (213:61): [True: 334, False: 48]
  |  |  ------------------
  ------------------
  812|       |            // bool is_valid = true;
  813|    334|            struct loader_string_list log_destinations = {0};
  814|    334|            VkResult parse_dest_res = loader_parse_json_array_of_strings(inst, log_element, "destinations", &log_destinations);
  815|    334|            if (parse_dest_res != VK_SUCCESS) {
  ------------------
  |  Branch (815:17): [True: 329, False: 5]
  ------------------
  816|       |                // is_valid = false;
  817|    329|            }
  818|    334|            free_string_list(inst, &log_destinations);
  819|    334|            struct loader_string_list log_filters = {0};
  820|    334|            VkResult parse_filters_res = loader_parse_json_array_of_strings(inst, log_element, "filters", &log_filters);
  821|    334|            if (parse_filters_res != VK_SUCCESS) {
  ------------------
  |  Branch (821:17): [True: 320, False: 14]
  ------------------
  822|       |                // is_valid = false;
  823|    320|            }
  824|    334|            free_string_list(inst, &log_filters);
  825|    334|        }
  826|     48|    }
  827|       |
  828|  2.50k|    VkResult layer_configurations_res = parse_layer_configurations(inst, settings_to_use, loader_settings);
  829|  2.50k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == layer_configurations_res) {
  ------------------
  |  Branch (829:9): [True: 0, False: 2.50k]
  ------------------
  830|      0|        res = layer_configurations_res;
  831|      0|        goto out;
  832|      0|    }
  833|       |
  834|       |    // Determine if there exists a layer configuration indicating where to put layers not contained in the settings file
  835|       |    // LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION
  836|  11.1k|    for (uint32_t i = 0; i < loader_settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (836:26): [True: 9.20k, False: 1.95k]
  ------------------
  837|  9.20k|        if (loader_settings->layer_configurations[i].control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (837:13): [True: 550, False: 8.65k]
  ------------------
  838|    550|            loader_settings->has_unordered_layer_location = true;
  839|    550|            break;
  840|    550|        }
  841|  9.20k|    }
  842|       |
  843|  2.50k|    VkResult additional_drivers_res = parse_additional_drivers(inst, settings_to_use, loader_settings);
  844|  2.50k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == additional_drivers_res) {
  ------------------
  |  Branch (844:9): [True: 0, False: 2.50k]
  ------------------
  845|      0|        res = additional_drivers_res;
  846|      0|        goto out;
  847|      0|    }
  848|       |
  849|  2.50k|    VkResult device_configurations_res = parse_device_configurations(inst, settings_to_use, loader_settings);
  850|  2.50k|    if (VK_ERROR_OUT_OF_HOST_MEMORY == device_configurations_res) {
  ------------------
  |  Branch (850:9): [True: 0, False: 2.50k]
  ------------------
  851|      0|        res = device_configurations_res;
  852|      0|        goto out;
  853|      0|    }
  854|       |
  855|       |    // Only consider the settings active if there is at least one "setting" active.
  856|       |    // Those are either logging, layers, additional_drivers, or device_configurations.
  857|  2.50k|    if (loader_settings->debug_level != 0 || loader_settings->layer_configurations_active ||
  ------------------
  |  Branch (857:9): [True: 180, False: 2.32k]
  |  Branch (857:46): [True: 1.99k, False: 331]
  ------------------
  858|  2.17k|        loader_settings->additional_driver_count != 0 || loader_settings->device_configurations_active) {
  ------------------
  |  Branch (858:9): [True: 0, False: 331]
  |  Branch (858:58): [True: 0, False: 331]
  ------------------
  859|  2.17k|        loader_settings->settings_file_path = settings_file_path;
  860|  2.17k|        settings_file_path = NULL;
  861|  2.17k|        loader_settings->settings_active = true;
  862|  2.17k|    } else {
  863|    331|        loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
  864|    331|                   "vk_loader_settings.json file found at \"%s\" but did not contain any valid settings.", settings_file_path);
  865|    331|    }
  866|  6.52k|out:
  867|  6.52k|    if (NULL != json) {
  ------------------
  |  Branch (867:9): [True: 3.16k, False: 3.35k]
  ------------------
  868|  3.16k|        loader_cJSON_Delete(json);
  869|  3.16k|    }
  870|       |
  871|  6.52k|    loader_instance_heap_free(inst, settings_file_path);
  872|       |
  873|  6.52k|    loader_instance_heap_free(inst, file_format_version_string);
  874|  6.52k|    return res;
  875|  2.50k|}
init_global_loader_settings:
  896|      2|void init_global_loader_settings(void) {
  897|      2|    loader_platform_thread_create_mutex(&global_loader_settings_lock);
  898|       |    // Free out the global settings in case the process was loaded & unloaded
  899|       |    free_loader_settings(NULL, &global_loader_settings);
  900|      2|}
get_current_settings_and_lock:
  916|  6.57k|const loader_settings* get_current_settings_and_lock(const struct loader_instance* inst) {
  917|  6.57k|    if (inst) {
  ------------------
  |  Branch (917:9): [True: 6.57k, False: 0]
  ------------------
  918|  6.57k|        return &inst->settings;
  919|  6.57k|    }
  920|      0|    loader_platform_thread_lock_mutex(&global_loader_settings_lock);
  921|      0|    return &global_loader_settings;
  922|  6.57k|}
release_current_settings_lock:
  924|  6.57k|void release_current_settings_lock(const struct loader_instance* inst) {
  925|  6.57k|    if (inst == NULL) {
  ------------------
  |  Branch (925:9): [True: 0, False: 6.57k]
  ------------------
  926|      0|        loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
  927|      0|    }
  928|  6.57k|}
get_settings_layers:
  931|  6.52k|                                                  bool* should_search_for_other_layers) {
  932|  6.52k|    VkResult res = VK_SUCCESS;
  933|  6.52k|    *should_search_for_other_layers = true;  // default to true
  934|       |
  935|  6.52k|    const loader_settings* settings = get_current_settings_and_lock(inst);
  936|       |
  937|  6.52k|    if (NULL == settings || !settings->settings_active || !settings->layer_configurations_active) {
  ------------------
  |  Branch (937:9): [True: 0, False: 6.52k]
  |  Branch (937:29): [True: 4.34k, False: 2.17k]
  |  Branch (937:59): [True: 82, False: 2.09k]
  ------------------
  938|  4.42k|        goto out;
  939|  4.42k|    }
  940|       |
  941|       |    // Assume the list doesn't contain LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION at first
  942|  2.09k|    *should_search_for_other_layers = false;
  943|       |
  944|  12.1k|    for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
  ------------------
  |  Branch (944:26): [True: 10.0k, False: 2.09k]
  ------------------
  945|  10.0k|        loader_settings_layer_configuration* layer_config = &settings->layer_configurations[i];
  946|       |
  947|       |        // If we encountered a layer that should be forced off, we add it to the settings_layers list but only
  948|       |        // with the data required to compare it with layers not in the settings file (aka name and manifest path)
  949|  10.0k|        if (layer_config->control == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (949:13): [True: 364, False: 9.70k]
  ------------------
  950|    364|            struct loader_layer_properties props = {0};
  951|    364|            props.settings_control_value = LOADER_SETTINGS_LAYER_CONTROL_OFF;
  952|    364|            loader_strncpy(props.info.layerName, VK_MAX_EXTENSION_NAME_SIZE, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE);
  953|    364|            props.info.layerName[VK_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
  954|    364|            res = loader_copy_to_new_str(inst, layer_config->path, &props.manifest_file_name);
  955|    364|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (955:17): [True: 0, False: 364]
  ------------------
  956|      0|                goto out;
  957|      0|            }
  958|    364|            res = loader_append_layer_property(inst, settings_layers, &props);
  959|    364|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (959:17): [True: 0, False: 364]
  ------------------
  960|      0|                loader_free_layer_properties(inst, &props);
  961|      0|                goto out;
  962|      0|            }
  963|    364|            continue;
  964|    364|        }
  965|       |
  966|       |        // The special layer location that indicates where unordered layers should go only should have the
  967|       |        // settings_control_value set - everything else should be NULL
  968|  9.70k|        if (layer_config->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (968:13): [True: 644, False: 9.06k]
  ------------------
  969|    644|            struct loader_layer_properties props = {0};
  970|    644|            props.settings_control_value = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
  971|    644|            res = loader_append_layer_property(inst, settings_layers, &props);
  972|    644|            if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
  ------------------
  |  Branch (972:17): [True: 0, False: 644]
  ------------------
  973|      0|                loader_free_layer_properties(inst, &props);
  974|      0|                goto out;
  975|      0|            }
  976|    644|            *should_search_for_other_layers = true;
  977|    644|            continue;
  978|    644|        }
  979|       |
  980|  9.06k|        if (layer_config->path == NULL) {
  ------------------
  |  Branch (980:13): [True: 0, False: 9.06k]
  ------------------
  981|      0|            continue;
  982|      0|        }
  983|       |
  984|  9.06k|        cJSON* json = NULL;
  985|  9.06k|        VkResult local_res = loader_get_json(inst, layer_config->path, &json);
  986|  9.06k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (986:13): [True: 0, False: 9.06k]
  ------------------
  987|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
  988|      0|            goto out;
  989|  9.06k|        } else if (VK_SUCCESS != local_res || NULL == json) {
  ------------------
  |  Branch (989:20): [True: 173, False: 8.88k]
  |  Branch (989:47): [True: 3.23k, False: 5.64k]
  ------------------
  990|  3.41k|            continue;
  991|  3.41k|        }
  992|       |
  993|       |        // Makes it possible to know if a new layer was added or not, since the only return value is VkResult
  994|  5.64k|        uint32_t count_before_adding = settings_layers->count;
  995|       |
  996|  5.64k|        local_res =
  997|  5.64k|            loader_add_layer_properties(inst, settings_layers, json, layer_config->treat_as_implicit_manifest, layer_config->path);
  998|  5.64k|        loader_cJSON_Delete(json);
  999|       |
 1000|       |        // If the error is anything other than out of memory we still want to try to load the other layers
 1001|  5.64k|        if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
  ------------------
  |  Branch (1001:13): [True: 0, False: 5.64k]
  ------------------
 1002|      0|            res = VK_ERROR_OUT_OF_HOST_MEMORY;
 1003|      0|            goto out;
 1004|  5.64k|        } else if (local_res != VK_SUCCESS || count_before_adding == settings_layers->count) {
  ------------------
  |  Branch (1004:20): [True: 3.46k, False: 2.18k]
  |  Branch (1004:47): [True: 0, False: 2.18k]
  ------------------
 1005|       |            // Indicates something was wrong with the layer, can't add it to the list
 1006|  3.46k|            continue;
 1007|  3.46k|        }
 1008|       |
 1009|  29.2k|        for (uint32_t j = count_before_adding; j < settings_layers->count; j++) {
  ------------------
  |  Branch (1009:48): [True: 27.0k, False: 2.18k]
  ------------------
 1010|  27.0k|            struct loader_layer_properties* newly_added_layer = &settings_layers->list[j];
 1011|  27.0k|            newly_added_layer->settings_control_value = layer_config->control;
 1012|       |            // If the manifest file found has a name that differs from the one in the settings, remove this layer from
 1013|       |            // consideration
 1014|  27.0k|            if (strncmp(newly_added_layer->info.layerName, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE) != 0) {
  ------------------
  |  Branch (1014:17): [True: 25.3k, False: 1.73k]
  ------------------
 1015|  25.3k|                loader_remove_layer_in_list(inst, settings_layers, j);
 1016|  25.3k|                j--;
 1017|  25.3k|                continue;
 1018|  25.3k|            }
 1019|  27.0k|            bool should_remove = false;
 1020|       |            // Make sure the layer isn't already in the list
 1021|  16.2k|            for (uint32_t k = 0; k < j; k++) {
  ------------------
  |  Branch (1021:34): [True: 15.2k, False: 1.01k]
  ------------------
 1022|  15.2k|                if (0 == strncmp(settings_layers->list[k].info.layerName, newly_added_layer->info.layerName,
  ------------------
  |  Branch (1022:21): [True: 14.5k, False: 662]
  ------------------
 1023|  15.2k|                                 VK_MAX_EXTENSION_NAME_SIZE)) {
 1024|  14.5k|                    if (0 == (newly_added_layer->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) &&
  ------------------
  |  Branch (1024:25): [True: 14.0k, False: 518]
  ------------------
 1025|  14.0k|                        settings_layers->list[k].lib_name != NULL && newly_added_layer->lib_name != NULL &&
  ------------------
  |  Branch (1025:25): [True: 1.93k, False: 12.1k]
  |  Branch (1025:70): [True: 1.59k, False: 335]
  ------------------
 1026|  1.59k|                        strcmp(settings_layers->list[k].lib_name, newly_added_layer->lib_name) == 0) {
  ------------------
  |  Branch (1026:25): [True: 724, False: 873]
  ------------------
 1027|    724|                        should_remove = true;
 1028|    724|                        break;
 1029|    724|                    }
 1030|  14.5k|                }
 1031|  15.2k|            }
 1032|  1.73k|            if (should_remove) {
  ------------------
  |  Branch (1032:17): [True: 724, False: 1.01k]
  ------------------
 1033|    724|                loader_remove_layer_in_list(inst, settings_layers, j);
 1034|    724|                j--;
 1035|    724|            }
 1036|  1.73k|        }
 1037|  2.18k|    }
 1038|       |
 1039|  6.52k|out:
 1040|  6.52k|    release_current_settings_lock(inst);
 1041|  6.52k|    return res;
 1042|  2.09k|}
check_if_layer_is_in_list:
 1053|  64.4k|                               bool consider_lib_path) {
 1054|       |    // If the layer is a meta layer, just check against the name
 1055|   309M|    for (uint32_t i = 0; i < layer_list->count; i++) {
  ------------------
  |  Branch (1055:26): [True: 309M, False: 42.7k]
  ------------------
 1056|   309M|        if (0 == strncmp(layer_list->list[i].info.layerName, layer_property->info.layerName, VK_MAX_EXTENSION_NAME_SIZE)) {
  ------------------
  |  Branch (1056:13): [True: 162M, False: 146M]
  ------------------
 1057|   162M|            if (layer_list->list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
  ------------------
  |  Branch (1057:17): [True: 9.47k, False: 162M]
  ------------------
 1058|  9.47k|                return true;
 1059|  9.47k|            }
 1060|   162M|            if (VK_LAYER_TYPE_FLAG_META_LAYER == (layer_property->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
  ------------------
  |  Branch (1060:17): [True: 167, False: 162M]
  ------------------
 1061|    167|                return true;
 1062|    167|            }
 1063|   162M|            if (!consider_lib_path) {
  ------------------
  |  Branch (1063:17): [True: 10.7k, False: 162M]
  ------------------
 1064|  10.7k|                return true;
 1065|  10.7k|            }
 1066|   162M|            if (layer_list->list[i].lib_name && layer_property->lib_name) {
  ------------------
  |  Branch (1066:17): [True: 11.8k, False: 162M]
  |  Branch (1066:49): [True: 1.37k, False: 10.4k]
  ------------------
 1067|  1.37k|                return strcmp(layer_list->list[i].lib_name, layer_property->lib_name) == 0;
 1068|  1.37k|            }
 1069|   162M|        }
 1070|   309M|    }
 1071|  42.7k|    return false;
 1072|  64.4k|}
combine_settings_layers_with_regular_layers:
 1076|  4.97k|                                                     struct loader_layer_list* output_layers) {
 1077|  4.97k|    VkResult res = VK_SUCCESS;
 1078|  4.97k|    bool has_unordered_layer_location = false;
 1079|  4.97k|    uint32_t unordered_layer_location_index = 0;
 1080|       |    // Location to put layers that aren't known to the settings file
 1081|       |    // Find it here so we dont have to pass in a loader_settings struct
 1082|  63.2k|    for (uint32_t i = 0; i < settings_layers->count; i++) {
  ------------------
  |  Branch (1082:26): [True: 58.7k, False: 4.42k]
  ------------------
 1083|  58.7k|        if (settings_layers->list[i].settings_control_value == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
  ------------------
  |  Branch (1083:13): [True: 550, False: 58.2k]
  ------------------
 1084|    550|            has_unordered_layer_location = true;
 1085|    550|            unordered_layer_location_index = i;
 1086|    550|            break;
 1087|    550|        }
 1088|  58.7k|    }
 1089|       |
 1090|  4.97k|    if (settings_layers->count == 0 && regular_layers->count == 0) {
  ------------------
  |  Branch (1090:9): [True: 4.42k, False: 550]
  |  Branch (1090:40): [True: 3.15k, False: 1.27k]
  ------------------
 1091|       |        // No layers to combine
 1092|  3.15k|        goto out;
 1093|  3.15k|    } else if (settings_layers->count == 0) {
  ------------------
  |  Branch (1093:16): [True: 1.27k, False: 550]
  ------------------
 1094|       |        // No settings layers - just copy regular to output_layers - memset regular layers to prevent double frees
 1095|  1.27k|        *output_layers = *regular_layers;
 1096|  1.27k|        memset(regular_layers, 0, sizeof(struct loader_layer_list));
 1097|  1.27k|        goto out;
 1098|  1.27k|    } else if (regular_layers->count == 0 || !has_unordered_layer_location) {
  ------------------
  |  Branch (1098:16): [True: 244, False: 306]
  |  Branch (1098:46): [True: 0, False: 306]
  ------------------
 1099|       |        // No regular layers or has_unordered_layer_location is false - just copy settings to output_layers -
 1100|       |        // memset settings layers to prevent double frees
 1101|    244|        *output_layers = *settings_layers;
 1102|    244|        memset(settings_layers, 0, sizeof(struct loader_layer_list));
 1103|    244|        goto out;
 1104|    244|    }
 1105|       |
 1106|    306|    res = loader_init_generic_list(inst, (struct loader_generic_list*)output_layers,
 1107|    306|                                   (settings_layers->count + regular_layers->count) * sizeof(struct loader_layer_properties));
 1108|    306|    if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1108:9): [True: 0, False: 306]
  ------------------
 1109|      0|        goto out;
 1110|      0|    }
 1111|       |
 1112|       |    // Insert the settings layers into output_layers up to unordered_layer_index
 1113|  34.2k|    for (uint32_t i = 0; i < unordered_layer_location_index; i++) {
  ------------------
  |  Branch (1113:26): [True: 33.9k, False: 306]
  ------------------
 1114|  33.9k|        if (!check_if_layer_is_in_list(output_layers, &settings_layers->list[i], true)) {
  ------------------
  |  Branch (1114:13): [True: 27.8k, False: 6.09k]
  ------------------
 1115|  27.8k|            res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
 1116|  27.8k|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1116:17): [True: 0, False: 27.8k]
  ------------------
 1117|      0|                goto out;
 1118|      0|            }
 1119|  27.8k|        }
 1120|  33.9k|    }
 1121|       |
 1122|  12.0k|    for (uint32_t i = 0; i < regular_layers->count; i++) {
  ------------------
  |  Branch (1122:26): [True: 11.7k, False: 306]
  ------------------
 1123|       |        // Check if its already been put in the output_layers list as well as the remaining settings_layers
 1124|  11.7k|        bool regular_layer_is_ordered = check_if_layer_is_in_list(output_layers, &regular_layers->list[i], false) ||
  ------------------
  |  Branch (1124:41): [True: 10.6k, False: 1.14k]
  ------------------
 1125|  1.14k|                                        check_if_layer_is_in_list(settings_layers, &regular_layers->list[i], false);
  ------------------
  |  Branch (1125:41): [True: 115, False: 1.03k]
  ------------------
 1126|       |        // If it isn't found, add it
 1127|  11.7k|        if (!regular_layer_is_ordered) {
  ------------------
  |  Branch (1127:13): [True: 1.03k, False: 10.7k]
  ------------------
 1128|  1.03k|            res = loader_append_layer_property(inst, output_layers, &regular_layers->list[i]);
 1129|  1.03k|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1129:17): [True: 0, False: 1.03k]
  ------------------
 1130|      0|                goto out;
 1131|      0|            }
 1132|  10.7k|        } else {
 1133|       |            // layer is already ordered and can be safely freed
 1134|  10.7k|            loader_free_layer_properties(inst, &regular_layers->list[i]);
 1135|  10.7k|        }
 1136|  11.7k|    }
 1137|       |
 1138|       |    // Insert the rest of the settings layers into combined_layers from  unordered_layer_index to the end
 1139|       |    // start at one after the unordered_layer_index
 1140|  17.8k|    for (uint32_t i = unordered_layer_location_index + 1; i < settings_layers->count; i++) {
  ------------------
  |  Branch (1140:59): [True: 17.5k, False: 306]
  ------------------
 1141|  17.5k|        if (!check_if_layer_is_in_list(output_layers, &settings_layers->list[i], true)) {
  ------------------
  |  Branch (1141:13): [True: 13.4k, False: 4.12k]
  ------------------
 1142|  13.4k|            res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
 1143|  13.4k|            if (VK_SUCCESS != res) {
  ------------------
  |  Branch (1143:17): [True: 0, False: 13.4k]
  ------------------
 1144|      0|                goto out;
 1145|      0|            }
 1146|  13.4k|        }
 1147|  17.5k|    }
 1148|       |
 1149|  4.97k|out:
 1150|  4.97k|    if (res != VK_SUCCESS) {
  ------------------
  |  Branch (1150:9): [True: 0, False: 4.97k]
  ------------------
 1151|      0|        loader_delete_layer_list_and_properties(inst, output_layers);
 1152|      0|    }
 1153|       |
 1154|  4.97k|    return res;
 1155|    306|}
loader_settings_get_additional_driver_files:
 1271|     17|VkResult loader_settings_get_additional_driver_files(const struct loader_instance* inst, struct loader_string_list* out_files) {
 1272|     17|    VkResult res = VK_SUCCESS;
 1273|       |
 1274|     17|    const loader_settings* settings = get_current_settings_and_lock(inst);
 1275|       |
 1276|     17|    if (NULL == settings || !settings->settings_active) {
  ------------------
  |  Branch (1276:9): [True: 0, False: 17]
  |  Branch (1276:29): [True: 0, False: 17]
  ------------------
 1277|      0|        goto out;
 1278|      0|    }
 1279|       |
 1280|     17|    if (settings->additional_drivers_use_exclusively) {
  ------------------
  |  Branch (1280:9): [True: 0, False: 17]
  ------------------
 1281|      0|        free_string_list(inst, out_files);
 1282|      0|    }
 1283|       |
 1284|     17|    for (uint32_t i = 0; i < settings->additional_driver_count; i++) {
  ------------------
  |  Branch (1284:26): [True: 0, False: 17]
  ------------------
 1285|      0|        res = prepend_if_manifest_file(inst, settings->additional_drivers[i].path, out_files);
 1286|      0|    }
 1287|       |
 1288|     17|out:
 1289|     17|    release_current_settings_lock(inst);
 1290|     17|    return res;
 1291|     17|}
loader_settings_should_use_driver_environment_variables:
 1293|     34|bool loader_settings_should_use_driver_environment_variables(const struct loader_instance* inst) {
 1294|     34|    bool should_use = true;
 1295|     34|    const loader_settings* settings = get_current_settings_and_lock(inst);
 1296|     34|    if (NULL == settings || !settings->settings_active) {
  ------------------
  |  Branch (1296:9): [True: 0, False: 34]
  |  Branch (1296:29): [True: 0, False: 34]
  ------------------
 1297|      0|        goto out;
 1298|      0|    }
 1299|     34|    if (settings->device_configurations_active) {
  ------------------
  |  Branch (1299:9): [True: 0, False: 34]
  ------------------
 1300|      0|        should_use = false;
 1301|      0|    }
 1302|     34|out:
 1303|     34|    release_current_settings_lock(inst);
 1304|     34|    return should_use;
 1305|     34|}

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

trampoline.c:loader_platform_thread_lock_mutex:
  450|  6.52k|static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
trampoline.c:loader_platform_thread_unlock_mutex:
  451|  6.52k|static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
loader.c:loader_strncpy:
  461|   386k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  462|   386k|    (void)dest_sz;
  463|   386k|    return strncpy(dest, src, count);
  464|   386k|}
loader.c:thread_safe_strtok:
  454|  77.4k|static inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
loader.c:loader_platform_thread_create_mutex:
  444|      4|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  445|      4|    pthread_mutexattr_t attr;
  446|      4|    pthread_mutexattr_init(&attr);
  447|      4|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  448|      4|    pthread_mutex_init(pMutex, &attr);
  449|      4|}
loader.c:loader_platform_is_path_absolute:
  294|  6.70k|static inline bool loader_platform_is_path_absolute(const char *path) {
  295|  6.70k|    if (path[0] == '/')
  ------------------
  |  Branch (295:9): [True: 371, False: 6.33k]
  ------------------
  296|    371|        return true;
  297|  6.33k|    else
  298|  6.33k|        return false;
  299|  6.70k|}
loader.c:loader_platform_is_path:
  248|  16.3k|static inline bool loader_platform_is_path(const char *path) { return strchr(path, DIRECTORY_SYMBOL) != NULL; }
  ------------------
  |  |  151|  16.3k|#define DIRECTORY_SYMBOL '/'
  ------------------
loader.c:loader_platform_file_exists:
  285|  16.3k|static inline bool loader_platform_file_exists(const char *path) {
  286|  16.3k|    if (access(path, F_OK))
  ------------------
  |  Branch (286:9): [True: 190, False: 16.1k]
  ------------------
  287|    190|        return false;
  288|  16.1k|    else
  289|  16.1k|        return true;
  290|  16.3k|}
loader.c:loader_platform_executable_path:
  306|  4.97k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  307|  4.97k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  308|  4.97k|    if (count == -1) return NULL;
  ------------------
  |  Branch (308:9): [True: 0, False: 4.97k]
  ------------------
  309|  4.97k|    if (count == 0) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 4.97k]
  ------------------
  310|  4.97k|    buffer[count] = '\0';
  311|  4.97k|    return buffer;
  312|  4.97k|}
loader_environment.c:thread_safe_strtok:
  454|  13.0k|static inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
loader_environment.c:loader_strncpy:
  461|  6.52k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  462|  6.52k|    (void)dest_sz;
  463|  6.52k|    return strncpy(dest, src, count);
  464|  6.52k|}
log.c:loader_strncat:
  457|   443k|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  458|   443k|    (void)dest_sz;
  459|   443k|    return strncat(dest, src, count);
  460|   443k|}
settings.c:loader_strncpy:
  461|  16.6k|static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
  462|  16.6k|    (void)dest_sz;
  463|  16.6k|    return strncpy(dest, src, count);
  464|  16.6k|}
settings.c:loader_strncat:
  457|  16.2k|static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
  458|  16.2k|    (void)dest_sz;
  459|  16.2k|    return strncat(dest, src, count);
  460|  16.2k|}
settings.c:loader_platform_file_exists:
  285|  16.2k|static inline bool loader_platform_file_exists(const char *path) {
  286|  16.2k|    if (access(path, F_OK))
  ------------------
  |  Branch (286:9): [True: 10.4k, False: 5.87k]
  ------------------
  287|  10.4k|        return false;
  288|  5.87k|    else
  289|  5.87k|        return true;
  290|  16.2k|}
settings.c:loader_platform_executable_path:
  306|  2.62k|static inline char *loader_platform_executable_path(char *buffer, size_t size) {
  307|  2.62k|    ssize_t count = readlink("/proc/self/exe", buffer, size);
  308|  2.62k|    if (count == -1) return NULL;
  ------------------
  |  Branch (308:9): [True: 0, False: 2.62k]
  ------------------
  309|  2.62k|    if (count == 0) return NULL;
  ------------------
  |  Branch (309:9): [True: 0, False: 2.62k]
  ------------------
  310|  2.62k|    buffer[count] = '\0';
  311|  2.62k|    return buffer;
  312|  2.62k|}
settings.c:loader_platform_thread_create_mutex:
  444|      2|static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
  445|      2|    pthread_mutexattr_t attr;
  446|      2|    pthread_mutexattr_init(&attr);
  447|      2|    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  448|      2|    pthread_mutex_init(pMutex, &attr);
  449|      2|}

wsi_unsupported_instance_extension:
  273|  10.8k|bool wsi_unsupported_instance_extension(const VkExtensionProperties *ext_prop) {
  274|       |#if !defined(VK_USE_PLATFORM_WAYLAND_KHR)
  275|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_wayland_surface")) return true;
  276|       |#endif  // VK_USE_PLATFORM_WAYLAND_KHR
  277|       |#if !defined(VK_USE_PLATFORM_XCB_KHR)
  278|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xcb_surface")) return true;
  279|       |#endif  // VK_USE_PLATFORM_XCB_KHR
  280|       |#if !defined(VK_USE_PLATFORM_XLIB_KHR)
  281|       |    if (!strcmp(ext_prop->extensionName, "VK_KHR_xlib_surface")) return true;
  282|       |#endif  // VK_USE_PLATFORM_XLIB_KHR
  283|  10.8k|#if !defined(VK_USE_PLATFORM_DIRECTFB_EXT)
  284|  10.8k|    if (!strcmp(ext_prop->extensionName, "VK_EXT_directfb_surface")) return true;
  ------------------
  |  Branch (284:9): [True: 70, False: 10.7k]
  ------------------
  285|  10.7k|#endif  // VK_USE_PLATFORM_DIRECTFB_EXT
  286|  10.7k|#if !defined(VK_USE_PLATFORM_SCREEN_QNX)
  287|  10.7k|    if (!strcmp(ext_prop->extensionName, "VK_QNX_screen_surface")) return true;
  ------------------
  |  Branch (287:9): [True: 120, False: 10.6k]
  ------------------
  288|  10.6k|#endif  // VK_USE_PLATFORM_SCREEN_QNX
  289|       |
  290|  10.6k|    return false;
  291|  10.7k|}

