From 3437c80c13aacda6a3cf7c8574530fb5aab5acf7 Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Mon, 13 Oct 2025 14:31:11 -0500 Subject: [PATCH] Rewrite assembly to not need codegen The original assembly relied on a build-time generated "gen_defines.asm" that contains various values and struct offsets needed by the assembly. This creates a lot of friction, as this build step must account for the numerous build environments and configurations that are possible, on top of needing an alternative path to handle cross-compilation. By modifying the assembly to no use extern variables, asm_offsets.c can contain all the necessary values as a compile-time value, such that at link time the values are available to the assembler. This does slightly increase runtime as we are replacing constants with variables, but the added benefits of simplifying the build step outweighs it. Doing the above required splitting the marmasm into separate files, one for 32 and the other for 64 bit. This is because there is no straight forward support for multiple architectures in a single file. Without codegen, determining which architecture to use was easiest by creating separate files. --- loader/CMakeLists.txt | 89 +- loader/asm_offset.c | 172 ---- loader/asm_offsets.c | 48 + loader/unknown_ext_chain_gas_aarch.S | 163 ++-- loader/unknown_ext_chain_gas_x86.S | 79 +- loader/unknown_ext_chain_marmasm32.asm | 870 ++++++++++++++++++ ...sm.asm => unknown_ext_chain_marmasm64.asm} | 106 +-- loader/unknown_ext_chain_masm.asm | 92 +- scripts/parse_asm_values.py | 135 --- 9 files changed, 1197 insertions(+), 557 deletions(-) delete mode 100644 loader/asm_offset.c create mode 100644 loader/asm_offsets.c create mode 100644 loader/unknown_ext_chain_marmasm32.asm rename loader/{unknown_ext_chain_marmasm.asm => unknown_ext_chain_marmasm64.asm} (83%) delete mode 100644 scripts/parse_asm_values.py diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 008b71da4..12edad1ab 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -68,6 +68,7 @@ endif() set(NORMAL_LOADER_SRCS allocation.c allocation.h + asm_offsets.c cJSON.c cJSON.h debug_utils.c @@ -215,30 +216,12 @@ end endif() if(ASM_COMPILER_WORKS) - add_executable(asm_offset asm_offset.c) - target_link_libraries(asm_offset PRIVATE loader_specific_options) - # If am emulator is provided (Like Wine), or running on native, run asm_offset to generate gen_defines.asm - if (CMAKE_CROSSCOMPILING_EMULATOR OR NOT CMAKE_CROSSCOMPILING) - add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset ${LOADER_ASM_DIALECT}) - else() - # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it. - target_compile_options(asm_offset PRIVATE "/Fa$/asm_offset.asm" /FA) - # Force off optimization so that the output assembly includes all the necessary info - optimizer would get rid of it otherwise. - target_compile_options(asm_offset PRIVATE /Od) - - find_package(Python3 REQUIRED QUIET) - # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on - add_custom_command(TARGET asm_offset POST_BUILD - COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm" - "$/asm_offset.asm" "${LOADER_ASM_DIALECT}" "${CMAKE_C_COMPILER_ID}" "${SYSTEM_PROCESSOR}" - BYPRODUCTS gen_defines.asm - ) - endif() - add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) - set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LOADER_HELPER_FOLDER}) - if(SYSTEM_PROCESSOR MATCHES "arm") - list(APPEND OPT_LOADER_SRCS unknown_ext_chain_marmasm.asm) + if(SYSTEM_PROCESSOR MATCHES "aarch64|arm64") + list(APPEND OPT_LOADER_SRCS unknown_ext_chain_marmasm64.asm) + else() + list(APPEND OPT_LOADER_SRCS unknown_ext_chain_marmasm32.asm) + endif() else() list(APPEND OPT_LOADER_SRCS unknown_ext_chain_masm.asm) endif() @@ -296,67 +279,14 @@ elseif(UNIX OR MINGW OR (WIN32 AND USE_GAS)) # i.e.: Linux & Apple & MinGW & Win endif() endif() - # When compiling for x86 on x64, we can't use CMAKE_SYSTEM_PROCESSOR to determine which architecture to use, - # Instead, check the size of void* and if its 4, set ASM_OFFSET_SYSTEM_PROCESSOR to x86 if we aren't on arm - if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(ASM_OFFSET_SYSTEM_PROCESSOR ${SYSTEM_PROCESSOR}) # x86_64 or aarch64/arm64 - string(REPLACE amd64 x86_64 ASM_OFFSET_SYSTEM_PROCESSOR "${ASM_OFFSET_SYSTEM_PROCESSOR}") - else() - if(${SYSTEM_PROCESSOR} MATCHES "86") - set(ASM_OFFSET_SYSTEM_PROCESSOR "x86") - else() - set(ASM_OFFSET_SYSTEM_PROCESSOR ${SYSTEM_PROCESSOR}) - endif() - endif() - if(ASSEMBLER_WORKS) - add_executable(asm_offset asm_offset.c) - target_link_libraries(asm_offset loader_specific_options) - # If not cross compiling, run asm_offset to generate gen_defines.asm - if (NOT CMAKE_CROSSCOMPILING) - add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset GAS) - else() - # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it. - # If with lto, compiler will output IR instead of asm, so we need to explicitly disable lto here. - if(CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(asm_offset PRIVATE -save-temps=obj -fno-lto) - elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") - target_compile_options(asm_offset PRIVATE -save-temps=obj -fno-lto -fno-whole-program-vtables -fno-virtual-function-elimination) - else() - target_compile_options(asm_offset PRIVATE -save-temps=obj) - endif() - if(CMAKE_C_COMPILER_ID STREQUAL "GNU") - set(ASM_OFFSET_EXECUTABLE_LOCATION "$/gen_defines.asm") - set(ASM_OFFSET_INTERMEDIATE_LOCATION "$/CMakeFiles/asm_offset.dir/asm_offset.c.s") - elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") - set(ASM_OFFSET_EXECUTABLE_LOCATION "$/gen_defines.asm") - set(ASM_OFFSET_INTERMEDIATE_LOCATION "$/CMakeFiles/asm_offset.dir/asm_offset.s") - elseif(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") - # Need to use the current binary dir since the asm_offset.s file is in that folder rather than the bundle - set(ASM_OFFSET_EXECUTABLE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm") - set(ASM_OFFSET_INTERMEDIATE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/asm_offset.dir/asm_offset.s") - else() - message(FATAL_ERROR "C_COMPILER_ID not supported!") - endif() - message(STATUS "CMAKE_CROSSCOMPILING FALSE") - - find_package(Python3 REQUIRED QUIET) - # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on - add_custom_command(TARGET asm_offset POST_BUILD - COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${ASM_OFFSET_EXECUTABLE_LOCATION}" - "${ASM_OFFSET_INTERMEDIATE_LOCATION}" "GAS" "${CMAKE_C_COMPILER_ID}" "${ASM_OFFSET_SYSTEM_PROCESSOR}" - BYPRODUCTS gen_defines.asm - ) - endif() - add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm) - if (APPLE) set(MODIFY_UNKNOWN_FUNCTION_DECLS ON) endif() set(UNKNOWN_FUNCTIONS_SUPPORTED ON) else() if(USE_GAS) - message(WARNING "Could not find working ${ASM_OFFSET_SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}") + message(WARNING "Could not find working ${SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}") else() message(WARNING "Assembly sources have been disabled\n${ASM_FAILURE_MSG}") endif() @@ -455,10 +385,6 @@ else() add_library(vulkan-framework SHARED) target_sources(vulkan-framework PRIVATE ${NORMAL_LOADER_SRCS} ${FRAMEWORK_HEADERS}) - if (UNKNOWN_FUNCTIONS_SUPPORTED) - add_dependencies(vulkan-framework loader_asm_gen_files) - endif() - target_link_libraries(vulkan-framework ${CMAKE_DL_LIBS} Threads::Threads -lm "-framework CoreFoundation") target_link_libraries(vulkan-framework loader_specific_options) @@ -514,7 +440,6 @@ add_library(Vulkan::Loader ALIAS vulkan) if (UNKNOWN_FUNCTIONS_SUPPORTED) target_compile_definitions(vulkan PRIVATE UNKNOWN_FUNCTIONS_SUPPORTED) - add_dependencies(vulkan loader_asm_gen_files) endif() if (BUILD_TESTS) diff --git a/loader/asm_offset.c b/loader/asm_offset.c deleted file mode 100644 index 4d01f8bfc..000000000 --- a/loader/asm_offset.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2017-2024 The Khronos Group Inc. - * Copyright (c) 2017-2024 Valve Corporation - * Copyright (c) 2017-2024 LunarG, Inc. - * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Lenny Komow - * Author: Charles Giessen - */ - -// This code generates an assembly file which provides offsets to get struct members from assembly code. - -// __USE_MINGW_ANSI_STDIO is needed to use the %zu format specifier with mingw-w64. -// Otherwise the compiler will complain about an unknown format specifier. -#if defined(__MINGW32__) && !defined(__USE_MINGW_ANSI_STDIO) -#define __USE_MINGW_ANSI_STDIO 1 -#endif - -#include -#include "loader_common.h" -#include "log.h" - -#if defined(__GNUC__) || defined(__clang__) -void produce_asm_define() { - // GCC and clang make it easy to print easy to regex for values - __asm__("# VULKAN_LOADER_ERROR_BIT = %c0" : : "i"(VULKAN_LOADER_ERROR_BIT)); - __asm__("# PTR_SIZE = %c0" : : "i"(sizeof(void *))); - __asm__("# CHAR_PTR_SIZE = %c0" : : "i"(sizeof(char *))); - __asm__("# FUNCTION_OFFSET_INSTANCE = %c0" : : "i"(offsetof(struct loader_instance, phys_dev_ext_disp_functions))); - __asm__("# PHYS_DEV_OFFSET_INST_DISPATCH = %c0" : : "i"(offsetof(struct loader_instance_dispatch_table, phys_dev_ext))); - __asm__("# PHYS_DEV_OFFSET_PHYS_DEV_TRAMP = %c0" : : "i"(offsetof(struct loader_physical_device_tramp, phys_dev))); - __asm__("# ICD_TERM_OFFSET_PHYS_DEV_TERM = %c0" : : "i"(offsetof(struct loader_physical_device_term, this_icd_term))); - __asm__("# PHYS_DEV_OFFSET_PHYS_DEV_TERM = %c0" : : "i"(offsetof(struct loader_physical_device_term, phys_dev))); - __asm__("# INSTANCE_OFFSET_ICD_TERM = %c0" : : "i"(offsetof(struct loader_icd_term, this_instance))); - __asm__("# DISPATCH_OFFSET_ICD_TERM = %c0" : : "i"(offsetof(struct loader_icd_term, phys_dev_ext))); - __asm__("# EXT_OFFSET_DEVICE_DISPATCH = %c0" : : "i"(offsetof(struct loader_dev_dispatch_table, ext_dispatch))); -} -#elif defined(_WIN32) -// MSVC will print the name of the value and the value in hex -// Must disable optimization for this translation unit, otherwise the compiler strips out the variables -static const uint32_t PTR_SIZE = sizeof(void *); -static const uint32_t CHAR_PTR_SIZE = sizeof(char *); -static const uint32_t FUNCTION_OFFSET_INSTANCE = offsetof(struct loader_instance, phys_dev_ext_disp_functions); -static const uint32_t PHYS_DEV_OFFSET_INST_DISPATCH = offsetof(struct loader_instance_dispatch_table, phys_dev_ext); -static const uint32_t PHYS_DEV_OFFSET_PHYS_DEV_TRAMP = offsetof(struct loader_physical_device_tramp, phys_dev); -static const uint32_t ICD_TERM_OFFSET_PHYS_DEV_TERM = offsetof(struct loader_physical_device_term, this_icd_term); -static const uint32_t PHYS_DEV_OFFSET_PHYS_DEV_TERM = offsetof(struct loader_physical_device_term, phys_dev); -static const uint32_t INSTANCE_OFFSET_ICD_TERM = offsetof(struct loader_icd_term, this_instance); -static const uint32_t DISPATCH_OFFSET_ICD_TERM = offsetof(struct loader_icd_term, phys_dev_ext); -static const uint32_t EXT_OFFSET_DEVICE_DISPATCH = offsetof(struct loader_dev_dispatch_table, ext_dispatch); -#else -#warning asm_offset.c variable declarations need to be defined for this platform -#endif - -#if !defined(_MSC_VER) || (_MSC_VER >= 1900) -#define SIZE_T_FMT "%-8zu" -#elif defined(__GNUC__) || defined(__clang__) -#define SIZE_T_FMT "%-8lu" -#else -#warning asm_offset.c SIZE_T_FMT must be defined for this platform -#endif - -struct ValueInfo { - const char *name; - size_t value; - const char *comment; -}; - -enum Assembler { - UNKNOWN = 0, - MASM = 1, - MARMASM = 2, - GAS = 3, -}; - -// This file can both be executed to produce gen_defines.asm and contains all the relevant data which -// the parse_asm_values.py script needs to write gen_defines.asm, necessary for cross compilation -int main(int argc, char **argv) { - enum Assembler assembler = UNKNOWN; - for (int i = 0; i < argc; ++i) { - if (!strcmp(argv[i], "MASM")) { - assembler = MASM; - } else if (!strcmp(argv[i], "MARMASM")) { - assembler = MARMASM; - } else if (!strcmp(argv[i], "GAS")) { - assembler = GAS; - } - } - if (assembler == UNKNOWN) { - return -1; - } - - struct ValueInfo values[] = { - // clang-format off - { .name = "VULKAN_LOADER_ERROR_BIT", .value = (size_t) VULKAN_LOADER_ERROR_BIT, - .comment = "The numerical value of the enum value 'VULKAN_LOADER_ERROR_BIT'" }, - { .name = "PTR_SIZE", .value = sizeof(void*), - .comment = "The size of a pointer" }, - { .name = "CHAR_PTR_SIZE", .value = sizeof(char *), - .comment = "The size of a 'const char *' struct" }, - { .name = "FUNCTION_OFFSET_INSTANCE", .value = offsetof(struct loader_instance, phys_dev_ext_disp_functions), - .comment = "The offset of 'phys_dev_ext_disp_functions' within a 'loader_instance' struct" }, - { .name = "PHYS_DEV_OFFSET_INST_DISPATCH", .value = offsetof(struct loader_instance_dispatch_table, phys_dev_ext), - .comment = "The offset of 'phys_dev_ext' within in 'loader_instance_dispatch_table' struct" }, - { .name = "PHYS_DEV_OFFSET_PHYS_DEV_TRAMP", .value = offsetof(struct loader_physical_device_tramp, phys_dev), - .comment = "The offset of 'phys_dev' within a 'loader_physical_device_tramp' struct" }, - { .name = "ICD_TERM_OFFSET_PHYS_DEV_TERM", .value = offsetof(struct loader_physical_device_term, this_icd_term), - .comment = "The offset of 'this_icd_term' within a 'loader_physical_device_term' struct" }, - { .name = "PHYS_DEV_OFFSET_PHYS_DEV_TERM", .value = offsetof(struct loader_physical_device_term, phys_dev), - .comment = "The offset of 'phys_dev' within a 'loader_physical_device_term' struct" }, - { .name = "INSTANCE_OFFSET_ICD_TERM", .value = offsetof(struct loader_icd_term, this_instance), - .comment = "The offset of 'this_instance' within a 'loader_icd_term' struct" }, - { .name = "DISPATCH_OFFSET_ICD_TERM", .value = offsetof(struct loader_icd_term, phys_dev_ext), - .comment = "The offset of 'phys_dev_ext' within a 'loader_icd_term' struct" }, - { .name = "EXT_OFFSET_DEVICE_DISPATCH", .value = offsetof(struct loader_dev_dispatch_table, ext_dispatch), - .comment = "The offset of 'ext_dispatch' within a 'loader_dev_dispatch_table' struct" }, - // clang-format on - }; - - FILE *file = loader_fopen("gen_defines.asm", "w"); - fprintf(file, "\n"); - if (assembler == MASM) { - for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) { - fprintf(file, "%-32s equ " SIZE_T_FMT "; %s\n", values[i].name, values[i].value, values[i].comment); - } - } else if (assembler == MARMASM) { - fprintf(file, " AREA loader_structs_details, DATA,READONLY\n"); -#if defined(__aarch64__) || defined(_M_ARM64) - fprintf(file, "AARCH_64 EQU 1\n"); -#else - fprintf(file, "AARCH_64 EQU 0\n"); -#endif - for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) { - fprintf(file, "%-32s EQU " SIZE_T_FMT "; %s\n", values[i].name, values[i].value, values[i].comment); - } - fprintf(file, " END\n"); - } else if (assembler == GAS) { -#if defined(__x86_64__) || defined(__i386__) - const char *comment_delimiter = "#"; -#if defined(__x86_64__) - fprintf(file, ".set X86_64, 1\n"); -#endif // defined(__x86_64__) -#elif defined(__aarch64__) || defined(__arm__) - const char *comment_delimiter = "//"; -#if defined(__aarch64__) - fprintf(file, ".set AARCH_64, 1\n"); -#else - fprintf(file, ".set AARCH_64, 0\n"); -#endif -#else - // Default comment delimiter - const char *comment_delimiter = "#"; -#endif - for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) { - fprintf(file, ".set %-32s, " SIZE_T_FMT "%s %s\n", values[i].name, values[i].value, comment_delimiter, - values[i].comment); - } - } - return fclose(file); -} diff --git a/loader/asm_offsets.c b/loader/asm_offsets.c new file mode 100644 index 000000000..bee9edfd5 --- /dev/null +++ b/loader/asm_offsets.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2024 The Khronos Group Inc. + * Copyright (c) 2017-2024 Valve Corporation + * Copyright (c) 2017-2024 LunarG, Inc. + * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Charles Giessen + */ + +#include +#include "loader_common.h" +#include "log.h" + +#if VK_USE_64_BIT_PTR_DEFINES == 1 +#define INT_TYPE uint64_t +#else +#define INT_TYPE uint32_t +#endif + +// Apple's ABI is to prefix the symbol with an underscore. Because we are using the symbols in assembly, we don't want to have to +// worry about it. The fix is to use `foo __asm__("foo")` in order to change the symbol name as it appears to the linker. +#if defined(__APPLE__) +#define DEF(x) x __asm__(#x) +#else +#define DEF(x) x +#endif + +const INT_TYPE DEF(VULKAN_LOADER_ERROR_BIT_VALUE) = VULKAN_LOADER_ERROR_BIT; +const INT_TYPE DEF(FUNCTION_OFFSET_INSTANCE) = offsetof(struct loader_instance, phys_dev_ext_disp_functions); +const INT_TYPE DEF(PHYS_DEV_OFFSET_INST_DISPATCH) = offsetof(struct loader_instance_dispatch_table, phys_dev_ext); +const INT_TYPE DEF(PHYS_DEV_OFFSET_PHYS_DEV_TRAMP) = offsetof(struct loader_physical_device_tramp, phys_dev); +const INT_TYPE DEF(ICD_TERM_OFFSET_PHYS_DEV_TERM) = offsetof(struct loader_physical_device_term, this_icd_term); +const INT_TYPE DEF(PHYS_DEV_OFFSET_PHYS_DEV_TERM) = offsetof(struct loader_physical_device_term, phys_dev); +const INT_TYPE DEF(INSTANCE_OFFSET_ICD_TERM) = offsetof(struct loader_icd_term, this_instance); +const INT_TYPE DEF(DISPATCH_OFFSET_ICD_TERM) = offsetof(struct loader_icd_term, phys_dev_ext); +const INT_TYPE DEF(EXT_OFFSET_DEVICE_DISPATCH) = offsetof(struct loader_dev_dispatch_table, ext_dispatch); diff --git a/loader/unknown_ext_chain_gas_aarch.S b/loader/unknown_ext_chain_gas_aarch.S index a78a32d34..e736f7931 100644 --- a/loader/unknown_ext_chain_gas_aarch.S +++ b/loader/unknown_ext_chain_gas_aarch.S @@ -24,7 +24,15 @@ // VkPhysicalDevice or a dispatchable object it can unwrap the object, possibly overwriting the wrapped physical device, and then // jump to the next function in the call chain -#include "gen_defines.asm" +.extern VULKAN_LOADER_ERROR_BIT_VALUE +.extern FUNCTION_OFFSET_INSTANCE +.extern PHYS_DEV_OFFSET_INST_DISPATCH +.extern PHYS_DEV_OFFSET_PHYS_DEV_TRAMP +.extern ICD_TERM_OFFSET_PHYS_DEV_TERM +.extern PHYS_DEV_OFFSET_PHYS_DEV_TERM +.extern INSTANCE_OFFSET_ICD_TERM +.extern DISPATCH_OFFSET_ICD_TERM +.extern EXT_OFFSET_DEVICE_DISPATCH /* * References: @@ -51,7 +59,26 @@ #define GNU_PROPERTY_AARCH64_POINTER_AUTH 0 #endif -.if AARCH_64 +#ifdef __aarch64__ + +.set PTR_SIZE, 8 +.set CHAR_PTR_SIZE, 8 + +// Loads the specified symol into the register. +// Necessary to account for differences in linux and apple platforms +.macro LOAD_SYMBOL register symbol num +#if defined(__APPLE__) +L1\register\symbol\num: + adrp \register, :got:\symbol@PAGE +L2\register\symbol\num: + ldr \register, [\register, :got:\symbol@PAGEOFF] + // Optimization if the offset to the symbol is small enough (and turn it into an adr+nop) + .loh AdrpLdr L1\register\symbol\num, L2\register\symbol\num +#else + ldr \register, \symbol +#endif + +.endm .macro PhysDevExtTramp num .global vkPhysDevExtTramp\num @@ -68,11 +95,13 @@ */ vkPhysDevExtTramp\num: BTI_C - ldr x9, [x0] // Load the loader_instance_dispatch_table* into x9 - ldr x0, [x0, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] // Load the unwrapped VkPhysicalDevice into x0 - mov x10, (PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * \num)) // Put the offset of the entry in the dispatch table for the function - ldr x16, [x9, x10] // Load the address to branch to out of the dispatch table - br x16 // Branch to the next member of the dispatch chain + ldr x9, [x0] // Load the loader_instance_dispatch_table* into x9 + LOAD_SYMBOL x10, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP, \num // Load the offset of the physical device into x10 + ldr x0, [x0, x10] // Load the unwrapped VkPhysicalDevice into x0 using the offset in x10 + LOAD_SYMBOL x11, PHYS_DEV_OFFSET_INST_DISPATCH, \num // Load the offset of the instance dispatch table into x11 + add x11, x11, (PTR_SIZE * \num) // Add the offset of the entry in the dispatch table for the function + ldr x16, [x9, x11] // Load the address to branch to out of the dispatch table + br x16 // Branch to the next member of the dispatch chain .endm .macro PhysDevExtTermin num @@ -84,23 +113,27 @@ vkPhysDevExtTramp\num: .balign 4 vkPhysDevExtTermin\num: BTI_C - ldr x9, [x0, ICD_TERM_OFFSET_PHYS_DEV_TERM] // Load the loader_icd_term* in x9 - mov x11, (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num)) // Put the offset into the dispatch table in x11 - ldr x16, [x9, x11] // Load the address of the next function in the dispatch chain - cbz x16, terminError\num // Go to the error section if the next function in the chain is NULL - ldr x0, [x0, PHYS_DEV_OFFSET_PHYS_DEV_TERM] // Unwrap the VkPhysicalDevice in x0 + LOAD_SYMBOL x9, ICD_TERM_OFFSET_PHYS_DEV_TERM, \num // Load the offset of the loader_icd_term into x9 + ldr x9, [x0, x9] // Load the loader_icd_term* in x9 from the VkPhysicalDevice in x0 + LOAD_SYMBOL x11, DISPATCH_OFFSET_ICD_TERM, \num // Load the offset of the dispatch table in the loader_icd_term into x11 + add x11, x11, (PTR_SIZE * \num) // Add the function offset into the dispatch table in x11 + ldr x16, [x9, x11] // Load the address of the next function in the dispatch chain + cbz x16, terminError\num // Go to the error section if the next function in the chain is NULL + LOAD_SYMBOL x11, PHYS_DEV_OFFSET_PHYS_DEV_TERM, \num // Load the offset of the wrapped physical device in loader_icd_term + ldr x0, [x0, x11] // Unwrap the VkPhysicalDevice in x0 br x16 // Jump to the next function in the chain terminError\num: BTI_J - mov x10, (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * \num)) // Offset of the function name string in the instance - ldr x11, [x9, INSTANCE_OFFSET_ICD_TERM] // Load the instance pointer - mov x0, x11 // Vulkan instance pointer (first arg) - mov x1, VULKAN_LOADER_ERROR_BIT // The error logging bit (second arg) - mov x2, #0 // Zero (third arg) - ldr x3, [x11, x10] // The function name (fourth arg) - bl loader_log_asm_function_not_supported // Log the error message before we crash + LOAD_SYMBOL x10, FUNCTION_OFFSET_INSTANCE, \num // Load the offset of the function name string in the sintance + add x10, x10, (CHAR_PTR_SIZE * \num) // Add the offset of the entry into x10 + LOAD_SYMBOL x12, INSTANCE_OFFSET_ICD_TERM, \num // Load the offset of the instance in the loader_icd_term + ldr x0, [x9, x12] // Load the Vulkan instance pointer into x0 (first arg) + LOAD_SYMBOL x1, VULKAN_LOADER_ERROR_BIT_VALUE, \num // The error logging bit (second arg) + mov x2, #0 // Zero (third arg) + ldr x3, [x0, x10] // The function name (fourth arg) is instance pointer + function name string offset + bl loader_log_asm_function_not_supported // Log the error message before we crash mov x0, #0 - br x0 // Crash intentionally by jumping to address zero + br x0 // Crash intentionally by jumping to address zero .endm .macro DevExtTramp num @@ -111,13 +144,17 @@ terminError\num: .balign 4 vkdev_ext\num: BTI_C - ldr x9, [x0] // Load the loader_instance_dispatch_table* into x9 - mov x10, (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * \num)) // Offset of the desired function in the dispatch table - ldr x16, [x9, x10] // Load the function address + ldr x9, [x0] // Load the loader_instance_dispatch_table* into x9 + LOAD_SYMBOL x10, EXT_OFFSET_DEVICE_DISPATCH, \num // Load the offset of the device dispatch table into x10 + add x10, x10, (PTR_SIZE * \num) // Offset of the desired function in the dispatch table + ldr x16, [x9, x10] // Load the function address br x16 .endm -.else // AARCH_32 +#else // AARCH_32 + +.set PTR_SIZE, 4 +.set CHAR_PTR_SIZE, 4 .macro PhysDevExtTramp num .global vkPhysDevExtTramp\num @@ -125,14 +162,19 @@ vkdev_ext\num: .hidden vkPhysDevExtTramp\num #endif .balign 4 - -vkPhysDevExtTrampDispatchEntry\num: .word PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * \num) +.ltorg +vkPhysDevExtTrampDispatchEntry\num: .word PTR_SIZE * \num vkPhysDevExtTramp\num: - ldr r4, [r0] // Load the loader_instance_dispatch_table* into r4 - ldr r0, [r0, #PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] // Load the unwrapped VkPhysicalDevice into r0 - ldr r5, vkPhysDevExtTrampDispatchEntry\num // Put the offset of the entry in the dispatch table for the function - ldr r6, [r4, r5] // Load the address to branch to out of the dispatch table - bx r6 // Branch to the next member of the dispatch chain + ldr r4, [r0] // Load the loader_instance_dispatch_table* into r4 + ldr r5, =PHYS_DEV_OFFSET_PHYS_DEV_TRAMP // Load the address of PHYS_DEV_OFFSET_PHYS_DEV_TRAMP into r5 + ldr r5, [r5] // Deref to put the offset of the unwrapped VkPhysicalDevice into r5 + ldr r0, [r0, r5] // Load the unwrapped VkPhysicalDevice into r0 + ldr r5, =PHYS_DEV_OFFSET_INST_DISPATCH // Load the address of PHYS_DEV_OFFSET_INST_DISPATCH into r5 + ldr r5, [r5] // Deref to put the offset of the Instance dispatch table into r5 + ldr r6, vkPhysDevExtTrampDispatchEntry\num // Load the offset of the entry in the dispatch table into r6 + add r5, r5, r6 // Add the offset of the entry in the dispatch table for the function + ldr r6, [r4, r5] // Load the address to branch to out of the dispatch table + bx r6 // Branch to the next member of the dispatch chain .endm @@ -142,26 +184,39 @@ vkPhysDevExtTramp\num: .hidden vkPhysDevExtTermin\num #endif .balign 4 -vkPhysDevExtTerminDispatchEntry\num: .word DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num) -vkPhysDevExtTerminFunctionNameEntry\num: .word FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * \num) +.ltorg +vkPhysDevExtTerminDispatchEntry\num: .word PTR_SIZE * \num +vkPhysDevExtTerminFunctionNameEntry\num: .word CHAR_PTR_SIZE * \num vkPhysDevExtTermin\num: - ldr r4, [r0, #ICD_TERM_OFFSET_PHYS_DEV_TERM] // Load the loader_icd_term* in r4 - ldr r6, vkPhysDevExtTerminDispatchEntry\num // Put the offset into the dispatch table in r6 - ldr r5, [r4, r6] // Load the address of the next function in the dispatch chain - cmp r5, #0 - beq terminError\num // Go to the error section if the next function in the chain is NULL - ldr r0, [r0, #PHYS_DEV_OFFSET_PHYS_DEV_TERM] // Unwrap the VkPhysicalDevice in r0 + ldr r4, =ICD_TERM_OFFSET_PHYS_DEV_TERM // Load the address of ICD_TERM_OFFSET_PHYS_DEV_TERM into r4 + ldr r4, [r4] // Deref to put the offset of the loader_icd_term* + ldr r4, [r0, r4] // Deref the VkPhysicalDevice in r0 with the offset to get the loader_icd_term* in r4 + ldr r6, =DISPATCH_OFFSET_ICD_TERM // Load the address of DISPATCH_OFFSET_ICD_TERM + ldr r6, [r6] // Deref to get the offset of the dispatch table + ldr r5, vkPhysDevExtTerminDispatchEntry\num // Load the offset of this entry in r5 + add r5, r5, r6 // Add DISPATCH_OFFSET_ICD_TERM + vkPhysDevExtTerminDispatchEntry to get the offset of the next function in the dispatch chain + ldr r5, [r4, r5] // Deref to get the address of the next function in the dispatch chain + cmp r5, #0 // Check if the next function is NULL + beq terminError\num // Go to the error section if the next function in the chain is NULL + ldr r6, =PHYS_DEV_OFFSET_PHYS_DEV_TERM // Load the address of PHYS_DEV_OFFSET_PHYS_DEV_TERM inro r6 + ldr r6, [r6] // Deref to put the offset of the unwrapped VkPhysicalDevice into r6 + ldr r0, [r0, r6] // Load the unwrapped VkPhysicalDevice using the offset into r0 bx r5 // Jump to the next function in the chain terminError\num: - ldr r5, vkPhysDevExtTerminFunctionNameEntry\num // Offset of the function name string in the instance - ldr r6, [r4, #INSTANCE_OFFSET_ICD_TERM] // Load the instance pointer - mov r0, r6 // Vulkan instance pointer (first arg) - mov r1, #VULKAN_LOADER_ERROR_BIT // The error logging bit (second arg) - mov r2, #0 // Zero (third arg) - ldr r3, [r6, r5] // The function name (fourth arg) - bl loader_log_asm_function_not_supported // Log the error message before we crash + ldr r5, =FUNCTION_OFFSET_INSTANCE // Load the address of FUNCTION_OFFSET_INSTANCE in r5 + ldr r5, [r5] // Deref to put the base of the function name string list in r5 + ldr r6, vkPhysDevExtTerminFunctionNameEntry\num // Load the offset of the function name string in the instance for this entry + add r5, r5, r6 // Add the base and offset + ldr r6, =INSTANCE_OFFSET_ICD_TERM // Load the address of INSTANCE_OFFSET_ICD_TERM + ldr r6, [r6] // Deref to put the offset of the VkInstance for the loader_icd_term in r6 + ldr r0, [r4, r6] // Load the Vulkan instance pointer (first arg) + ldr r1, =VULKAN_LOADER_ERROR_BIT_VALUE // Load the address of the error bit value + ldr r1, [r1] // Deref to put the error logging bit (second arg) + mov r2, #0 // Zero (third arg) + ldr r3, [r0, r5] // The function name (fourth arg) + bl loader_log_asm_function_not_supported // Log the error message before we crash mov r0, #0 - bx r0 // Crash intentionally by jumping to address zero + bx r0 // Crash intentionally by jumping to address zero .endm .macro DevExtTramp num @@ -170,15 +225,19 @@ terminError\num: .hidden vkdev_ext\num #endif .balign 4 -vkdev_ext_dispatch_entry\num: .word EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * \num) +.ltorg +vkdev_ext_dispatch_entry\num: .word PTR_SIZE * \num vkdev_ext\num: - ldr r4, [r0] // Load the loader_instance_dispatch_table* into r4 - ldr r5, vkdev_ext_dispatch_entry\num // Offset of the desired function in the dispatch table - ldr r6, [r4, r5] // Load the function address + ldr r4, [r0] // Load the loader_instance_dispatch_table* into r4 + ldr r5, =EXT_OFFSET_DEVICE_DISPATCH // Load the address of EXT_OFFSET_DEVICE_DISPATCH + ldr r5, [r5] // Deref to get the offset into the device dispatch table + ldr r6, vkdev_ext_dispatch_entry\num // Load the offset for current function in the table + add r5, r5, r6 // Add the EXT_OFFSET_DEVICE_DISPATCH and current entry offset + ldr r6, [r4, r5] // Load the function address at loader_instance_dispatch_table + offset bx r6 .endm -.endif +#endif #if defined(__ELF__) .section .note.GNU-stack,"",%progbits diff --git a/loader/unknown_ext_chain_gas_x86.S b/loader/unknown_ext_chain_gas_x86.S index 2a9bb81b3..778e8fb43 100644 --- a/loader/unknown_ext_chain_gas_x86.S +++ b/loader/unknown_ext_chain_gas_x86.S @@ -33,9 +33,11 @@ #endif .intel_syntax noprefix -#include "gen_defines.asm" -.ifdef X86_64 +#ifdef __x86_64__ + +.set PTR_SIZE , 8 # The size of a pointer +.set CHAR_PTR_SIZE , 8 # The size of a 'const char *' struct .macro PhysDevExtTramp num .global vkPhysDevExtTramp\num @@ -44,9 +46,11 @@ #endif vkPhysDevExtTramp\num: _CET_ENDBR - mov rax, [rdi] - mov rdi, [rdi + PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] - jmp [rax + (PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * \num))] + mov rax, [rdi] # rdi contains the wrapped VkPhysicalDevice, deref and put loader_physical_device_tramp* into rax + add rdi, [rip + PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] # + mov rdi, [rdi] # deref to get unwrapped VkPhysicalDevice + add rax, [rip + PHYS_DEV_OFFSET_INST_DISPATCH] + jmp [rax + (PTR_SIZE * \num)] .endm .macro PhysDevExtTermin num @@ -56,18 +60,27 @@ vkPhysDevExtTramp\num: #endif vkPhysDevExtTermin\num: _CET_ENDBR - mov rax, [rdi + ICD_TERM_OFFSET_PHYS_DEV_TERM] # Store the loader_icd_term* in rax - cmp qword ptr [rax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num))], 0 # Check if the next function in the chain is NULL + add rdi, [rip + ICD_TERM_OFFSET_PHYS_DEV_TERM] + mov rax, [rdi] # Store the loader_icd_term* in rax + add rax, [rip + DISPATCH_OFFSET_ICD_TERM] + cmp qword ptr [rax + (PTR_SIZE * \num)], 0 # Check if the next function in the chain is NULL je terminError\num # Go to the error section if it is NULL - mov rdi, [rdi + PHYS_DEV_OFFSET_PHYS_DEV_TERM] # Load the unwrapped VkPhysicalDevice into the first arg - jmp [rax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num))] # Jump to the next function in the chain + sub rdi, [rip + ICD_TERM_OFFSET_PHYS_DEV_TERM] + add rdi, [rip + PHYS_DEV_OFFSET_PHYS_DEV_TERM] + mov rdi, [rdi] # Load the unwrapped VkPhysicalDevice into the first arg + jmp [rax + (PTR_SIZE * \num)] # Jump to the next function in the chain terminError\num: sub rsp, 56 # Create the stack frame - mov rdi, [rax + INSTANCE_OFFSET_ICD_TERM] # Load the loader_instance into rdi (first arg) - lea rsi, [VULKAN_LOADER_ERROR_BIT] # Write the error logging bit to rsi (second arg) + sub rax, [rip + DISPATCH_OFFSET_ICD_TERM] + add rax, [rip + INSTANCE_OFFSET_ICD_TERM] + mov rdi, [rax] # Load the loader_instance into rdi (first arg) + sub rax, [rip + INSTANCE_OFFSET_ICD_TERM] + lea rsi, [rip + VULKAN_LOADER_ERROR_BIT_VALUE] # Write the error logging bit to rsi (second arg) xor rdx, rdx # Set rdx to zero (third arg) lea rcx, [rip + termin_error_string] # Load the error string into rcx (fourth arg) - mov r8, [rdi + (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * \num))] # Load the func name into r8 (fifth arg) + add rdi, [rip + FUNCTION_OFFSET_INSTANCE] + mov r8, [rdi + (CHAR_PTR_SIZE * \num)] # Load the func name into r8 (fifth arg) + sub rdi, [rip + FUNCTION_OFFSET_INSTANCE] call loader_log # Log the error message before we crash add rsp, 56 # Clean up the stack frame mov rax, 0 @@ -82,10 +95,14 @@ terminError\num: vkdev_ext\num: _CET_ENDBR mov rax, [rdi] # Dereference the handle to get the dispatch table - jmp [rax + (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * \num))] # Jump to the appropriate call chain + add rax, [rip + EXT_OFFSET_DEVICE_DISPATCH] + jmp [rax + (PTR_SIZE * \num)] # Jump to the appropriate call chain .endm -.else +#else + +.set PTR_SIZE , 4 # The size of a pointer +.set CHAR_PTR_SIZE , 4 # The size of a 'const char *' struct .macro PhysDevExtTramp num #if defined(_WIN32) @@ -100,10 +117,13 @@ vkPhysDevExtTramp\num: #endif _CET_ENDBR mov eax, [esp + 4] # Load the wrapped VkPhysicalDevice into eax - mov ecx, [eax + PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] # Load the unwrapped VkPhysicalDevice into ecx + add eax, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP + mov ecx, [eax] # Load the unwrapped VkPhysicalDevice into ecx + sub eax, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP mov [esp + 4], ecx # Overwrite the wrapped VkPhysicalDevice with the unwrapped one (on the stack) mov eax, [eax] # Dereference the wrapped VkPhysicalDevice to get the dispatch table in eax - jmp [eax + (PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * \num))] # Dereference the wrapped VkPhysicalDevice to get the dispatch table in eax + add eax, PHYS_DEV_OFFSET_INST_DISPATCH + jmp [eax + (PTR_SIZE * \num)] # Dereference the wrapped VkPhysicalDevice to get the dispatch table in eax .endm .macro PhysDevExtTermin num @@ -119,17 +139,25 @@ vkPhysDevExtTermin\num: #endif _CET_ENDBR mov ecx, [esp + 4] # Move the wrapped VkPhysicalDevice into ecx - mov eax, [ecx + ICD_TERM_OFFSET_PHYS_DEV_TERM] # Store the loader_icd_term* in eax - cmp dword ptr [eax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num))], 0 # Check if the next function in the chain is NULL + add ecx, ICD_TERM_OFFSET_PHYS_DEV_TERM + mov eax, [ecx] # Store the loader_icd_term* in eax + add eax, DISPATCH_OFFSET_ICD_TERM + cmp dword ptr [eax + (PTR_SIZE * \num)], 0 # Check if the next function in the chain is NULL je terminError\num # Go to the error section if it is NULL - mov ecx, [ecx + PHYS_DEV_OFFSET_PHYS_DEV_TERM] # Unwrap the VkPhysicalDevice in ecx + sub ecx, ICD_TERM_OFFSET_PHYS_DEV_TERM + add ecx, PHYS_DEV_OFFSET_PHYS_DEV_TERM + mov ecx, [ecx] # Unwrap the VkPhysicalDevice in ecx mov [esp + 4], ecx # Copy the unwrapped VkPhysicalDevice into the first arg - jmp [eax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num))] # Jump to the next function in the chain + jmp [eax + (PTR_SIZE * \num)] # Jump to the next function in the chain terminError\num: - mov eax, dword ptr [eax + INSTANCE_OFFSET_ICD_TERM] # Load the loader_instance into eax - push dword ptr [eax + (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * \num))] # Push the func name (fourth arg) + sub eax, DISPATCH_OFFSET_ICD_TERM + add eax, INSTANCE_OFFSET_ICD_TERM + mov eax, dword ptr [eax] # Load the loader_instance into eax + add eax, FUNCTION_OFFSET_INSTANCE + push dword ptr [eax + (CHAR_PTR_SIZE * \num)] # Push the func name (fourth arg) + sub eax, FUNCTION_OFFSET_INSTANCE push 0 # Push zero (third arg) - push VULKAN_LOADER_ERROR_BIT # Push the error logging bit (second arg) + push VULKAN_LOADER_ERROR_BIT_VALUE # Push the error logging bit (second arg) push eax # Push the loader_instance (first arg) #if defined(_WIN32) call _loader_log_asm_function_not_supported # Log the error message before we crash @@ -155,10 +183,11 @@ vkdev_ext\num: _CET_ENDBR mov eax, dword ptr [esp + 4] # Dereference the handle to get the dispatch table mov eax, dword ptr [eax] # Dereference the chain_device to get the loader_dispatch - jmp dword ptr [eax + (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * \num))] # Jump to the appropriate call chain + add eax, EXT_OFFSET_DEVICE_DISPATCH + jmp dword ptr [eax + (PTR_SIZE * \num)] # Jump to the appropriate call chain .endm -.endif +#endif #if defined(__ELF__) .section .note.GNU-stack,"",%progbits diff --git a/loader/unknown_ext_chain_marmasm32.asm b/loader/unknown_ext_chain_marmasm32.asm new file mode 100644 index 000000000..7cb795cb8 --- /dev/null +++ b/loader/unknown_ext_chain_marmasm32.asm @@ -0,0 +1,870 @@ +; +; Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +; Copyright (c) 2024 Valve Corporation +; Copyright (c) 2024 LunarG, Inc. +; +; Licensed under the Apache License, Version 2.0 (the "License"); +; you may not use this file except in compliance with the License. +; You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +; Unless required by applicable law or agreed to in writing, software +; distributed under the License is distributed on an "AS IS" BASIS, +; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; See the License for the specific language governing permissions and +; limitations under the License. +; +; Author: Eric Sullivan +; Author: Charles Giessen +; + +; This code is used to pass on device (including physical device) extensions through the call chain. It must do this without +; creating a stack frame, because the actual parameters of the call are not known. Since the first parameter is known to be a +; VkPhysicalDevice or a dispatchable object it can unwrap the object, possibly overwriting the wrapped physical device, and then +; jump to the next function in the call chain + + + EXTERN loader_log_asm_function_not_supported + +PTR_SIZE equ 4 ; The size of a pointer +CHAR_PTR_SIZE equ 4 ; The size of a 'const char *' struct + + EXTERN VULKAN_LOADER_ERROR_BIT_VALUE + EXTERN FUNCTION_OFFSET_INSTANCE + EXTERN PHYS_DEV_OFFSET_INST_DISPATCH + EXTERN PHYS_DEV_OFFSET_PHYS_DEV_TRAMP + EXTERN ICD_TERM_OFFSET_PHYS_DEV_TERM + EXTERN PHYS_DEV_OFFSET_PHYS_DEV_TERM + EXTERN INSTANCE_OFFSET_ICD_TERM + EXTERN DISPATCH_OFFSET_ICD_TERM + EXTERN EXT_OFFSET_DEVICE_DISPATCH + + MACRO + PhysDevExtTramp $num + ALIGN + EXPORT vkPhysDevExtTramp$num [FUNC] +vkPhysDevExtTramp$num FUNCTION + ldr r4, [r0] ; Load the loader_instance_dispatch_table* into r4 + ldr r5, =PHYS_DEV_OFFSET_PHYS_DEV_TRAMP + ldr r5, [r5] + ldr r0, [r0, r5] ; Load the unwrapped VkPhysicalDevice into r0 + ldr r5, =PHYS_DEV_OFFSET_INST_DISPATCH + ldr r5, [r5] + add r5, r5, #(PTR_SIZE * $num) ; Put the offset of the entry in the dispatch table for the function + ldr r6, [r4, r5] ; Load the address to branch to out of the dispatch table + bx r6 ; Branch to the next member of the dispatch chain + ENDFUNC + LTORG + MEND + + MACRO +$label PhysDevExtTermin $num + ALIGN + EXPORT vkPhysDevExtTermin$num [FUNC] +vkPhysDevExtTermin$num FUNCTION + ldr r4, =ICD_TERM_OFFSET_PHYS_DEV_TERM + ldr r4, [r4] + ldr r4, [r0, r4] ; Load the loader_icd_term* in r4 + ldr r6, =DISPATCH_OFFSET_ICD_TERM + ldr r6, [r6] + mov r5, #(PTR_SIZE * $num) ; Put the offset into the dispatch table in r6 + add r5, r5, r6 ; Load the address of the next function in the dispatch chain + cbz r5, terminError$num ; Go to the error section if the next function in the chain is NULL + ldr r6, =PHYS_DEV_OFFSET_PHYS_DEV_TERM + ldr r6, [r6] + ldr r0, [r0, r6] ; Unwrap the VkPhysicalDevice in r0 + bx r5 ; Jump to the next function in the chain +terminError$num + ldr r5, =FUNCTION_OFFSET_INSTANCE + ldr r5, [r5] + mov r6, #(CHAR_PTR_SIZE * $num) ; Offset of the function name string in the instance + add r5, r5, r6 + ldr r6, =INSTANCE_OFFSET_ICD_TERM + ldr r0, [r4, r6] ; Load the instance pointer ; Vulkan instance pointer (first arg) + ldr r1, =VULKAN_LOADER_ERROR_BIT_VALUE + ldr r1, [r1] ; The error logging bit (second arg) + mov r2, #0 ; Zero (third arg) + ldr r3, [r0, r5] ; The function name (fourth arg) + bl loader_log_asm_function_not_supported ; Log the error message before we crash + mov r0, #0 + bx r0 ; Crash intentionally by jumping to address zero + ENDFUNC + LTORG + MEND + + MACRO + DevExtTramp $num + ALIGN + EXPORT vkdev_ext$num [FUNC] +vkdev_ext$num FUNCTION + ldr r4, [r0] ; Load the loader_instance_dispatch_table* into r4 + ldr r5, =EXT_OFFSET_DEVICE_DISPATCH + ldr r5, [r5] + mov r6, #(PTR_SIZE * $num) ; Offset of the desired function in the dispatch table + add r5, r5, r6 + ldr r6, [r4, r5] ; Load the function address + bx r6 + ENDFUNC + LTORG + MEND + AREA terminator_string_data, DATA, READONLY + +termin_error_string DCB "Function %s not supported for this physical device", 0 + + AREA UnknownFunctionImpl, CODE, READONLY + + PhysDevExtTramp 0 + PhysDevExtTramp 1 + PhysDevExtTramp 2 + PhysDevExtTramp 3 + PhysDevExtTramp 4 + PhysDevExtTramp 5 + PhysDevExtTramp 6 + PhysDevExtTramp 7 + PhysDevExtTramp 8 + PhysDevExtTramp 9 + PhysDevExtTramp 10 + PhysDevExtTramp 11 + PhysDevExtTramp 12 + PhysDevExtTramp 13 + PhysDevExtTramp 14 + PhysDevExtTramp 15 + PhysDevExtTramp 16 + PhysDevExtTramp 17 + PhysDevExtTramp 18 + PhysDevExtTramp 19 + PhysDevExtTramp 20 + PhysDevExtTramp 21 + PhysDevExtTramp 22 + PhysDevExtTramp 23 + PhysDevExtTramp 24 + PhysDevExtTramp 25 + PhysDevExtTramp 26 + PhysDevExtTramp 27 + PhysDevExtTramp 28 + PhysDevExtTramp 29 + PhysDevExtTramp 30 + PhysDevExtTramp 31 + PhysDevExtTramp 32 + PhysDevExtTramp 33 + PhysDevExtTramp 34 + PhysDevExtTramp 35 + PhysDevExtTramp 36 + PhysDevExtTramp 37 + PhysDevExtTramp 38 + PhysDevExtTramp 39 + PhysDevExtTramp 40 + PhysDevExtTramp 41 + PhysDevExtTramp 42 + PhysDevExtTramp 43 + PhysDevExtTramp 44 + PhysDevExtTramp 45 + PhysDevExtTramp 46 + PhysDevExtTramp 47 + PhysDevExtTramp 48 + PhysDevExtTramp 49 + PhysDevExtTramp 50 + PhysDevExtTramp 51 + PhysDevExtTramp 52 + PhysDevExtTramp 53 + PhysDevExtTramp 54 + PhysDevExtTramp 55 + PhysDevExtTramp 56 + PhysDevExtTramp 57 + PhysDevExtTramp 58 + PhysDevExtTramp 59 + PhysDevExtTramp 60 + PhysDevExtTramp 61 + PhysDevExtTramp 62 + PhysDevExtTramp 63 + PhysDevExtTramp 64 + PhysDevExtTramp 65 + PhysDevExtTramp 66 + PhysDevExtTramp 67 + PhysDevExtTramp 68 + PhysDevExtTramp 69 + PhysDevExtTramp 70 + PhysDevExtTramp 71 + PhysDevExtTramp 72 + PhysDevExtTramp 73 + PhysDevExtTramp 74 + PhysDevExtTramp 75 + PhysDevExtTramp 76 + PhysDevExtTramp 77 + PhysDevExtTramp 78 + PhysDevExtTramp 79 + PhysDevExtTramp 80 + PhysDevExtTramp 81 + PhysDevExtTramp 82 + PhysDevExtTramp 83 + PhysDevExtTramp 84 + PhysDevExtTramp 85 + PhysDevExtTramp 86 + PhysDevExtTramp 87 + PhysDevExtTramp 88 + PhysDevExtTramp 89 + PhysDevExtTramp 90 + PhysDevExtTramp 91 + PhysDevExtTramp 92 + PhysDevExtTramp 93 + PhysDevExtTramp 94 + PhysDevExtTramp 95 + PhysDevExtTramp 96 + PhysDevExtTramp 97 + PhysDevExtTramp 98 + PhysDevExtTramp 99 + PhysDevExtTramp 100 + PhysDevExtTramp 101 + PhysDevExtTramp 102 + PhysDevExtTramp 103 + PhysDevExtTramp 104 + PhysDevExtTramp 105 + PhysDevExtTramp 106 + PhysDevExtTramp 107 + PhysDevExtTramp 108 + PhysDevExtTramp 109 + PhysDevExtTramp 110 + PhysDevExtTramp 111 + PhysDevExtTramp 112 + PhysDevExtTramp 113 + PhysDevExtTramp 114 + PhysDevExtTramp 115 + PhysDevExtTramp 116 + PhysDevExtTramp 117 + PhysDevExtTramp 118 + PhysDevExtTramp 119 + PhysDevExtTramp 120 + PhysDevExtTramp 121 + PhysDevExtTramp 122 + PhysDevExtTramp 123 + PhysDevExtTramp 124 + PhysDevExtTramp 125 + PhysDevExtTramp 126 + PhysDevExtTramp 127 + PhysDevExtTramp 128 + PhysDevExtTramp 129 + PhysDevExtTramp 130 + PhysDevExtTramp 131 + PhysDevExtTramp 132 + PhysDevExtTramp 133 + PhysDevExtTramp 134 + PhysDevExtTramp 135 + PhysDevExtTramp 136 + PhysDevExtTramp 137 + PhysDevExtTramp 138 + PhysDevExtTramp 139 + PhysDevExtTramp 140 + PhysDevExtTramp 141 + PhysDevExtTramp 142 + PhysDevExtTramp 143 + PhysDevExtTramp 144 + PhysDevExtTramp 145 + PhysDevExtTramp 146 + PhysDevExtTramp 147 + PhysDevExtTramp 148 + PhysDevExtTramp 149 + PhysDevExtTramp 150 + PhysDevExtTramp 151 + PhysDevExtTramp 152 + PhysDevExtTramp 153 + PhysDevExtTramp 154 + PhysDevExtTramp 155 + PhysDevExtTramp 156 + PhysDevExtTramp 157 + PhysDevExtTramp 158 + PhysDevExtTramp 159 + PhysDevExtTramp 160 + PhysDevExtTramp 161 + PhysDevExtTramp 162 + PhysDevExtTramp 163 + PhysDevExtTramp 164 + PhysDevExtTramp 165 + PhysDevExtTramp 166 + PhysDevExtTramp 167 + PhysDevExtTramp 168 + PhysDevExtTramp 169 + PhysDevExtTramp 170 + PhysDevExtTramp 171 + PhysDevExtTramp 172 + PhysDevExtTramp 173 + PhysDevExtTramp 174 + PhysDevExtTramp 175 + PhysDevExtTramp 176 + PhysDevExtTramp 177 + PhysDevExtTramp 178 + PhysDevExtTramp 179 + PhysDevExtTramp 180 + PhysDevExtTramp 181 + PhysDevExtTramp 182 + PhysDevExtTramp 183 + PhysDevExtTramp 184 + PhysDevExtTramp 185 + PhysDevExtTramp 186 + PhysDevExtTramp 187 + PhysDevExtTramp 188 + PhysDevExtTramp 189 + PhysDevExtTramp 190 + PhysDevExtTramp 191 + PhysDevExtTramp 192 + PhysDevExtTramp 193 + PhysDevExtTramp 194 + PhysDevExtTramp 195 + PhysDevExtTramp 196 + PhysDevExtTramp 197 + PhysDevExtTramp 198 + PhysDevExtTramp 199 + PhysDevExtTramp 200 + PhysDevExtTramp 201 + PhysDevExtTramp 202 + PhysDevExtTramp 203 + PhysDevExtTramp 204 + PhysDevExtTramp 205 + PhysDevExtTramp 206 + PhysDevExtTramp 207 + PhysDevExtTramp 208 + PhysDevExtTramp 209 + PhysDevExtTramp 210 + PhysDevExtTramp 211 + PhysDevExtTramp 212 + PhysDevExtTramp 213 + PhysDevExtTramp 214 + PhysDevExtTramp 215 + PhysDevExtTramp 216 + PhysDevExtTramp 217 + PhysDevExtTramp 218 + PhysDevExtTramp 219 + PhysDevExtTramp 220 + PhysDevExtTramp 221 + PhysDevExtTramp 222 + PhysDevExtTramp 223 + PhysDevExtTramp 224 + PhysDevExtTramp 225 + PhysDevExtTramp 226 + PhysDevExtTramp 227 + PhysDevExtTramp 228 + PhysDevExtTramp 229 + PhysDevExtTramp 230 + PhysDevExtTramp 231 + PhysDevExtTramp 232 + PhysDevExtTramp 233 + PhysDevExtTramp 234 + PhysDevExtTramp 235 + PhysDevExtTramp 236 + PhysDevExtTramp 237 + PhysDevExtTramp 238 + PhysDevExtTramp 239 + PhysDevExtTramp 240 + PhysDevExtTramp 241 + PhysDevExtTramp 242 + PhysDevExtTramp 243 + PhysDevExtTramp 244 + PhysDevExtTramp 245 + PhysDevExtTramp 246 + PhysDevExtTramp 247 + PhysDevExtTramp 248 + PhysDevExtTramp 249 + + PhysDevExtTermin 0 + PhysDevExtTermin 1 + PhysDevExtTermin 2 + PhysDevExtTermin 3 + PhysDevExtTermin 4 + PhysDevExtTermin 5 + PhysDevExtTermin 6 + PhysDevExtTermin 7 + PhysDevExtTermin 8 + PhysDevExtTermin 9 + PhysDevExtTermin 10 + PhysDevExtTermin 11 + PhysDevExtTermin 12 + PhysDevExtTermin 13 + PhysDevExtTermin 14 + PhysDevExtTermin 15 + PhysDevExtTermin 16 + PhysDevExtTermin 17 + PhysDevExtTermin 18 + PhysDevExtTermin 19 + PhysDevExtTermin 20 + PhysDevExtTermin 21 + PhysDevExtTermin 22 + PhysDevExtTermin 23 + PhysDevExtTermin 24 + PhysDevExtTermin 25 + PhysDevExtTermin 26 + PhysDevExtTermin 27 + PhysDevExtTermin 28 + PhysDevExtTermin 29 + PhysDevExtTermin 30 + PhysDevExtTermin 31 + PhysDevExtTermin 32 + PhysDevExtTermin 33 + PhysDevExtTermin 34 + PhysDevExtTermin 35 + PhysDevExtTermin 36 + PhysDevExtTermin 37 + PhysDevExtTermin 38 + PhysDevExtTermin 39 + PhysDevExtTermin 40 + PhysDevExtTermin 41 + PhysDevExtTermin 42 + PhysDevExtTermin 43 + PhysDevExtTermin 44 + PhysDevExtTermin 45 + PhysDevExtTermin 46 + PhysDevExtTermin 47 + PhysDevExtTermin 48 + PhysDevExtTermin 49 + PhysDevExtTermin 50 + PhysDevExtTermin 51 + PhysDevExtTermin 52 + PhysDevExtTermin 53 + PhysDevExtTermin 54 + PhysDevExtTermin 55 + PhysDevExtTermin 56 + PhysDevExtTermin 57 + PhysDevExtTermin 58 + PhysDevExtTermin 59 + PhysDevExtTermin 60 + PhysDevExtTermin 61 + PhysDevExtTermin 62 + PhysDevExtTermin 63 + PhysDevExtTermin 64 + PhysDevExtTermin 65 + PhysDevExtTermin 66 + PhysDevExtTermin 67 + PhysDevExtTermin 68 + PhysDevExtTermin 69 + PhysDevExtTermin 70 + PhysDevExtTermin 71 + PhysDevExtTermin 72 + PhysDevExtTermin 73 + PhysDevExtTermin 74 + PhysDevExtTermin 75 + PhysDevExtTermin 76 + PhysDevExtTermin 77 + PhysDevExtTermin 78 + PhysDevExtTermin 79 + PhysDevExtTermin 80 + PhysDevExtTermin 81 + PhysDevExtTermin 82 + PhysDevExtTermin 83 + PhysDevExtTermin 84 + PhysDevExtTermin 85 + PhysDevExtTermin 86 + PhysDevExtTermin 87 + PhysDevExtTermin 88 + PhysDevExtTermin 89 + PhysDevExtTermin 90 + PhysDevExtTermin 91 + PhysDevExtTermin 92 + PhysDevExtTermin 93 + PhysDevExtTermin 94 + PhysDevExtTermin 95 + PhysDevExtTermin 96 + PhysDevExtTermin 97 + PhysDevExtTermin 98 + PhysDevExtTermin 99 + PhysDevExtTermin 100 + PhysDevExtTermin 101 + PhysDevExtTermin 102 + PhysDevExtTermin 103 + PhysDevExtTermin 104 + PhysDevExtTermin 105 + PhysDevExtTermin 106 + PhysDevExtTermin 107 + PhysDevExtTermin 108 + PhysDevExtTermin 109 + PhysDevExtTermin 110 + PhysDevExtTermin 111 + PhysDevExtTermin 112 + PhysDevExtTermin 113 + PhysDevExtTermin 114 + PhysDevExtTermin 115 + PhysDevExtTermin 116 + PhysDevExtTermin 117 + PhysDevExtTermin 118 + PhysDevExtTermin 119 + PhysDevExtTermin 120 + PhysDevExtTermin 121 + PhysDevExtTermin 122 + PhysDevExtTermin 123 + PhysDevExtTermin 124 + PhysDevExtTermin 125 + PhysDevExtTermin 126 + PhysDevExtTermin 127 + PhysDevExtTermin 128 + PhysDevExtTermin 129 + PhysDevExtTermin 130 + PhysDevExtTermin 131 + PhysDevExtTermin 132 + PhysDevExtTermin 133 + PhysDevExtTermin 134 + PhysDevExtTermin 135 + PhysDevExtTermin 136 + PhysDevExtTermin 137 + PhysDevExtTermin 138 + PhysDevExtTermin 139 + PhysDevExtTermin 140 + PhysDevExtTermin 141 + PhysDevExtTermin 142 + PhysDevExtTermin 143 + PhysDevExtTermin 144 + PhysDevExtTermin 145 + PhysDevExtTermin 146 + PhysDevExtTermin 147 + PhysDevExtTermin 148 + PhysDevExtTermin 149 + PhysDevExtTermin 150 + PhysDevExtTermin 151 + PhysDevExtTermin 152 + PhysDevExtTermin 153 + PhysDevExtTermin 154 + PhysDevExtTermin 155 + PhysDevExtTermin 156 + PhysDevExtTermin 157 + PhysDevExtTermin 158 + PhysDevExtTermin 159 + PhysDevExtTermin 160 + PhysDevExtTermin 161 + PhysDevExtTermin 162 + PhysDevExtTermin 163 + PhysDevExtTermin 164 + PhysDevExtTermin 165 + PhysDevExtTermin 166 + PhysDevExtTermin 167 + PhysDevExtTermin 168 + PhysDevExtTermin 169 + PhysDevExtTermin 170 + PhysDevExtTermin 171 + PhysDevExtTermin 172 + PhysDevExtTermin 173 + PhysDevExtTermin 174 + PhysDevExtTermin 175 + PhysDevExtTermin 176 + PhysDevExtTermin 177 + PhysDevExtTermin 178 + PhysDevExtTermin 179 + PhysDevExtTermin 180 + PhysDevExtTermin 181 + PhysDevExtTermin 182 + PhysDevExtTermin 183 + PhysDevExtTermin 184 + PhysDevExtTermin 185 + PhysDevExtTermin 186 + PhysDevExtTermin 187 + PhysDevExtTermin 188 + PhysDevExtTermin 189 + PhysDevExtTermin 190 + PhysDevExtTermin 191 + PhysDevExtTermin 192 + PhysDevExtTermin 193 + PhysDevExtTermin 194 + PhysDevExtTermin 195 + PhysDevExtTermin 196 + PhysDevExtTermin 197 + PhysDevExtTermin 198 + PhysDevExtTermin 199 + PhysDevExtTermin 200 + PhysDevExtTermin 201 + PhysDevExtTermin 202 + PhysDevExtTermin 203 + PhysDevExtTermin 204 + PhysDevExtTermin 205 + PhysDevExtTermin 206 + PhysDevExtTermin 207 + PhysDevExtTermin 208 + PhysDevExtTermin 209 + PhysDevExtTermin 210 + PhysDevExtTermin 211 + PhysDevExtTermin 212 + PhysDevExtTermin 213 + PhysDevExtTermin 214 + PhysDevExtTermin 215 + PhysDevExtTermin 216 + PhysDevExtTermin 217 + PhysDevExtTermin 218 + PhysDevExtTermin 219 + PhysDevExtTermin 220 + PhysDevExtTermin 221 + PhysDevExtTermin 222 + PhysDevExtTermin 223 + PhysDevExtTermin 224 + PhysDevExtTermin 225 + PhysDevExtTermin 226 + PhysDevExtTermin 227 + PhysDevExtTermin 228 + PhysDevExtTermin 229 + PhysDevExtTermin 230 + PhysDevExtTermin 231 + PhysDevExtTermin 232 + PhysDevExtTermin 233 + PhysDevExtTermin 234 + PhysDevExtTermin 235 + PhysDevExtTermin 236 + PhysDevExtTermin 237 + PhysDevExtTermin 238 + PhysDevExtTermin 239 + PhysDevExtTermin 240 + PhysDevExtTermin 241 + PhysDevExtTermin 242 + PhysDevExtTermin 243 + PhysDevExtTermin 244 + PhysDevExtTermin 245 + PhysDevExtTermin 246 + PhysDevExtTermin 247 + PhysDevExtTermin 248 + PhysDevExtTermin 249 + + DevExtTramp 0 + DevExtTramp 1 + DevExtTramp 2 + DevExtTramp 3 + DevExtTramp 4 + DevExtTramp 5 + DevExtTramp 6 + DevExtTramp 7 + DevExtTramp 8 + DevExtTramp 9 + DevExtTramp 10 + DevExtTramp 11 + DevExtTramp 12 + DevExtTramp 13 + DevExtTramp 14 + DevExtTramp 15 + DevExtTramp 16 + DevExtTramp 17 + DevExtTramp 18 + DevExtTramp 19 + DevExtTramp 20 + DevExtTramp 21 + DevExtTramp 22 + DevExtTramp 23 + DevExtTramp 24 + DevExtTramp 25 + DevExtTramp 26 + DevExtTramp 27 + DevExtTramp 28 + DevExtTramp 29 + DevExtTramp 30 + DevExtTramp 31 + DevExtTramp 32 + DevExtTramp 33 + DevExtTramp 34 + DevExtTramp 35 + DevExtTramp 36 + DevExtTramp 37 + DevExtTramp 38 + DevExtTramp 39 + DevExtTramp 40 + DevExtTramp 41 + DevExtTramp 42 + DevExtTramp 43 + DevExtTramp 44 + DevExtTramp 45 + DevExtTramp 46 + DevExtTramp 47 + DevExtTramp 48 + DevExtTramp 49 + DevExtTramp 50 + DevExtTramp 51 + DevExtTramp 52 + DevExtTramp 53 + DevExtTramp 54 + DevExtTramp 55 + DevExtTramp 56 + DevExtTramp 57 + DevExtTramp 58 + DevExtTramp 59 + DevExtTramp 60 + DevExtTramp 61 + DevExtTramp 62 + DevExtTramp 63 + DevExtTramp 64 + DevExtTramp 65 + DevExtTramp 66 + DevExtTramp 67 + DevExtTramp 68 + DevExtTramp 69 + DevExtTramp 70 + DevExtTramp 71 + DevExtTramp 72 + DevExtTramp 73 + DevExtTramp 74 + DevExtTramp 75 + DevExtTramp 76 + DevExtTramp 77 + DevExtTramp 78 + DevExtTramp 79 + DevExtTramp 80 + DevExtTramp 81 + DevExtTramp 82 + DevExtTramp 83 + DevExtTramp 84 + DevExtTramp 85 + DevExtTramp 86 + DevExtTramp 87 + DevExtTramp 88 + DevExtTramp 89 + DevExtTramp 90 + DevExtTramp 91 + DevExtTramp 92 + DevExtTramp 93 + DevExtTramp 94 + DevExtTramp 95 + DevExtTramp 96 + DevExtTramp 97 + DevExtTramp 98 + DevExtTramp 99 + DevExtTramp 100 + DevExtTramp 101 + DevExtTramp 102 + DevExtTramp 103 + DevExtTramp 104 + DevExtTramp 105 + DevExtTramp 106 + DevExtTramp 107 + DevExtTramp 108 + DevExtTramp 109 + DevExtTramp 110 + DevExtTramp 111 + DevExtTramp 112 + DevExtTramp 113 + DevExtTramp 114 + DevExtTramp 115 + DevExtTramp 116 + DevExtTramp 117 + DevExtTramp 118 + DevExtTramp 119 + DevExtTramp 120 + DevExtTramp 121 + DevExtTramp 122 + DevExtTramp 123 + DevExtTramp 124 + DevExtTramp 125 + DevExtTramp 126 + DevExtTramp 127 + DevExtTramp 128 + DevExtTramp 129 + DevExtTramp 130 + DevExtTramp 131 + DevExtTramp 132 + DevExtTramp 133 + DevExtTramp 134 + DevExtTramp 135 + DevExtTramp 136 + DevExtTramp 137 + DevExtTramp 138 + DevExtTramp 139 + DevExtTramp 140 + DevExtTramp 141 + DevExtTramp 142 + DevExtTramp 143 + DevExtTramp 144 + DevExtTramp 145 + DevExtTramp 146 + DevExtTramp 147 + DevExtTramp 148 + DevExtTramp 149 + DevExtTramp 150 + DevExtTramp 151 + DevExtTramp 152 + DevExtTramp 153 + DevExtTramp 154 + DevExtTramp 155 + DevExtTramp 156 + DevExtTramp 157 + DevExtTramp 158 + DevExtTramp 159 + DevExtTramp 160 + DevExtTramp 161 + DevExtTramp 162 + DevExtTramp 163 + DevExtTramp 164 + DevExtTramp 165 + DevExtTramp 166 + DevExtTramp 167 + DevExtTramp 168 + DevExtTramp 169 + DevExtTramp 170 + DevExtTramp 171 + DevExtTramp 172 + DevExtTramp 173 + DevExtTramp 174 + DevExtTramp 175 + DevExtTramp 176 + DevExtTramp 177 + DevExtTramp 178 + DevExtTramp 179 + DevExtTramp 180 + DevExtTramp 181 + DevExtTramp 182 + DevExtTramp 183 + DevExtTramp 184 + DevExtTramp 185 + DevExtTramp 186 + DevExtTramp 187 + DevExtTramp 188 + DevExtTramp 189 + DevExtTramp 190 + DevExtTramp 191 + DevExtTramp 192 + DevExtTramp 193 + DevExtTramp 194 + DevExtTramp 195 + DevExtTramp 196 + DevExtTramp 197 + DevExtTramp 198 + DevExtTramp 199 + DevExtTramp 200 + DevExtTramp 201 + DevExtTramp 202 + DevExtTramp 203 + DevExtTramp 204 + DevExtTramp 205 + DevExtTramp 206 + DevExtTramp 207 + DevExtTramp 208 + DevExtTramp 209 + DevExtTramp 210 + DevExtTramp 211 + DevExtTramp 212 + DevExtTramp 213 + DevExtTramp 214 + DevExtTramp 215 + DevExtTramp 216 + DevExtTramp 217 + DevExtTramp 218 + DevExtTramp 219 + DevExtTramp 220 + DevExtTramp 221 + DevExtTramp 222 + DevExtTramp 223 + DevExtTramp 224 + DevExtTramp 225 + DevExtTramp 226 + DevExtTramp 227 + DevExtTramp 228 + DevExtTramp 229 + DevExtTramp 230 + DevExtTramp 231 + DevExtTramp 232 + DevExtTramp 233 + DevExtTramp 234 + DevExtTramp 235 + DevExtTramp 236 + DevExtTramp 237 + DevExtTramp 238 + DevExtTramp 239 + DevExtTramp 240 + DevExtTramp 241 + DevExtTramp 242 + DevExtTramp 243 + DevExtTramp 244 + DevExtTramp 245 + DevExtTramp 246 + DevExtTramp 247 + DevExtTramp 248 + DevExtTramp 249 + + END diff --git a/loader/unknown_ext_chain_marmasm.asm b/loader/unknown_ext_chain_marmasm64.asm similarity index 83% rename from loader/unknown_ext_chain_marmasm.asm rename to loader/unknown_ext_chain_marmasm64.asm index f2f352a17..ab6811862 100644 --- a/loader/unknown_ext_chain_marmasm.asm +++ b/loader/unknown_ext_chain_marmasm64.asm @@ -25,11 +25,19 @@ ; jump to the next function in the call chain - GET gen_defines.asm +PTR_SIZE EQU 8 ; The size of a pointer +CHAR_PTR_SIZE EQU 8 ; The size of a 'const char *' struct EXTERN loader_log_asm_function_not_supported - - IF AARCH_64==1 + EXTERN VULKAN_LOADER_ERROR_BIT_VALUE + EXTERN FUNCTION_OFFSET_INSTANCE + EXTERN PHYS_DEV_OFFSET_INST_DISPATCH + EXTERN PHYS_DEV_OFFSET_PHYS_DEV_TRAMP + EXTERN ICD_TERM_OFFSET_PHYS_DEV_TERM + EXTERN PHYS_DEV_OFFSET_PHYS_DEV_TERM + EXTERN INSTANCE_OFFSET_ICD_TERM + EXTERN DISPATCH_OFFSET_ICD_TERM + EXTERN EXT_OFFSET_DEVICE_DISPATCH MACRO PhysDevExtTramp $num @@ -37,8 +45,12 @@ EXPORT vkPhysDevExtTramp$num [FUNC] vkPhysDevExtTramp$num FUNCTION ldr x9, [x0] ; Load the loader_instance_dispatch_table* into x9 - ldr x0, [x0, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] ; Load the unwrapped VkPhysicalDevice into x0 - mov x10, #(PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * $num)) ; Put the offset of the entry in the dispatch table for the function + ldr x10, =PHYS_DEV_OFFSET_PHYS_DEV_TRAMP + ldr x10, [x10] + ldr x0, [x0, x10] ; Load the unwrapped VkPhysicalDevice into x0 + ldr x10, =PHYS_DEV_OFFSET_INST_DISPATCH + ldr x10, [x10] + add x10, x10, #(PTR_SIZE * $num) ; Put the offset of the entry in the dispatch table for the function ldr x11, [x9, x10] ; Load the address to branch to out of the dispatch table br x11 ; Branch to the next member of the dispatch chain ENDFUNC @@ -49,19 +61,29 @@ $label PhysDevExtTermin $num ALIGN EXPORT vkPhysDevExtTermin$num [FUNC] vkPhysDevExtTermin$num FUNCTION - ldr x9, [x0, ICD_TERM_OFFSET_PHYS_DEV_TERM] ; Load the loader_icd_term* in x9 - mov x11, (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * $num)) ; Put the offset into the dispatch table in x11 + ldr x9, =ICD_TERM_OFFSET_PHYS_DEV_TERM + ldr x9, [x9] + ldr x9, [x0, x9] ; Load the loader_icd_term* in x9 + ldr x11, =DISPATCH_OFFSET_ICD_TERM + ldr x11, [x11] + add x11, x11, (PTR_SIZE * $num) ; Put the offset into the dispatch table in x11 ldr x10, [x9, x11] ; Load the address of the next function in the dispatch chain cbz x10, terminError$num ; Go to the error section if the next function in the chain is NULL - ldr x0, [x0, PHYS_DEV_OFFSET_PHYS_DEV_TERM] ; Unwrap the VkPhysicalDevice in x0 + ldr x11, =PHYS_DEV_OFFSET_PHYS_DEV_TERM + ldr x11, [x11] + ldr x0, [x0, x11] ; Unwrap the VkPhysicalDevice in x0 br x10 ; Jump to the next function in the chain terminError$num - mov x10, (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * $num)) ; Offset of the function name string in the instance - ldr x11, [x9, INSTANCE_OFFSET_ICD_TERM] ; Load the instance pointer - mov x0, x11 ; Vulkan instance pointer (first arg) - mov x1, VULKAN_LOADER_ERROR_BIT ; The error logging bit (second arg) + ldr x10, =FUNCTION_OFFSET_INSTANCE + ldr x10, [x10] + add x10, x10, (CHAR_PTR_SIZE * $num) ; Offset of the function name string in the instance + ldr x11, =INSTANCE_OFFSET_ICD_TERM + ldr x11, [x11] + ldr x0, [x9, x11] ; Load the Vulkan instance pointer (first arg) + ldr x1, =VULKAN_LOADER_ERROR_BIT_VALUE ; The error logging bit (second arg) + ldr x1, [x1] mov x2, #0 ; Zero (third arg) - ldr x3, [x11, x10] ; The function name (fourth arg) + ldr x3, [x0, x10] ; The function name (fourth arg) bl loader_log_asm_function_not_supported ; Log the error message before we crash mov x0, #0 br x0 ; Crash intentionally by jumping to address zero @@ -74,66 +96,14 @@ terminError$num EXPORT vkdev_ext$num [FUNC] vkdev_ext$num FUNCTION ldr x9, [x0] ; Load the loader_instance_dispatch_table* into x9 - mov x10, (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * $num)) ; Offset of the desired function in the dispatch table + ldr x10, =EXT_OFFSET_DEVICE_DISPATCH + ldr x10, [x10] + add x10, x10, (PTR_SIZE * $num) ; Offset of the desired function in the dispatch table ldr x11, [x9, x10] ; Load the function address br x11 ENDFUNC MEND -; 32 bit (armhf) assembly - ELSE - - MACRO - PhysDevExtTramp $num - ALIGN - EXPORT vkPhysDevExtTramp$num [FUNC] -vkPhysDevExtTramp$num FUNCTION - ldr r4, [r0] ; Load the loader_instance_dispatch_table* into r4 - ldr r0, [r0, #PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] ; Load the unwrapped VkPhysicalDevice into r0 - mov r5, #(PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * $num)) ; Put the offset of the entry in the dispatch table for the function - ldr r6, [r4, r5] ; Load the address to branch to out of the dispatch table - bx r6 ; Branch to the next member of the dispatch chain - ENDFUNC - MEND - - MACRO -$label PhysDevExtTermin $num - ALIGN - EXPORT vkPhysDevExtTermin$num [FUNC] -vkPhysDevExtTermin$num FUNCTION - ldr r4, [r0, #ICD_TERM_OFFSET_PHYS_DEV_TERM] ; Load the loader_icd_term* in r4 - mov r6, #(DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * $num)) ; Put the offset into the dispatch table in r6 - ldr r5, [r4, r6] ; Load the address of the next function in the dispatch chain - cbz r5, terminError$num ; Go to the error section if the next function in the chain is NULL - ldr r0, [r0, #PHYS_DEV_OFFSET_PHYS_DEV_TERM] ; Unwrap the VkPhysicalDevice in r0 - bx r5 ; Jump to the next function in the chain -terminError$num - mov r5, #(FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * $num)) ; Offset of the function name string in the instance - ldr r6, [r4, #INSTANCE_OFFSET_ICD_TERM] ; Load the instance pointer - mov r0, r6 ; Vulkan instance pointer (first arg) - mov r1, #VULKAN_LOADER_ERROR_BIT ; The error logging bit (second arg) - mov r2, #0 ; Zero (third arg) - ldr r3, [r6, r5] ; The function name (fourth arg) - bl loader_log_asm_function_not_supported ; Log the error message before we crash - mov r0, #0 - bx r0 ; Crash intentionally by jumping to address zero - ENDFUNC - MEND - - MACRO - DevExtTramp $num - ALIGN - EXPORT vkdev_ext$num [FUNC] -vkdev_ext$num FUNCTION - ldr r4, [r0] ; Load the loader_instance_dispatch_table* into r4 - mov r5, #(EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * $num)) ; Offset of the desired function in the dispatch table - ldr r6, [r4, r5] ; Load the function address - bx r6 - ENDFUNC - MEND - - ENDIF - AREA terminator_string_data, DATA, READONLY termin_error_string DCB "Function %s not supported for this physical device", 0 diff --git a/loader/unknown_ext_chain_masm.asm b/loader/unknown_ext_chain_masm.asm index 46d13de47..7605470cd 100644 --- a/loader/unknown_ext_chain_masm.asm +++ b/loader/unknown_ext_chain_masm.asm @@ -24,38 +24,59 @@ ; VkPhysicalDevice or a dispatchable object it can unwrap the object, possibly overwriting the wrapped physical device, and then ; jump to the next function in the call chain -; Codegen defines a number of values, chiefly offsets of members within structs and sizes of data types within gen_defines.asm. +; asm_offsets.c defines number of values and offsets needed by the assembly code. They are placed in static memory so that the assembly code can access them. ; Struct member offsets are defined in the format "XX_OFFSET_YY" where XX indicates the member within the struct and YY indicates ; the struct type that it is a member of. Data type sizes are defined in the format "XX_SIZE" where XX indicates the data type. -INCLUDE gen_defines.asm ; 64-bit values and macro IFDEF rax +PTR_SIZE equ 8 ; The size of a pointer +CHAR_PTR_SIZE equ 8 ; The size of a 'const char *' struct +EXTERN VULKAN_LOADER_ERROR_BIT_VALUE:QWORD +EXTERN FUNCTION_OFFSET_INSTANCE:QWORD +EXTERN PHYS_DEV_OFFSET_INST_DISPATCH:QWORD +EXTERN PHYS_DEV_OFFSET_PHYS_DEV_TRAMP:QWORD +EXTERN ICD_TERM_OFFSET_PHYS_DEV_TERM:QWORD +EXTERN PHYS_DEV_OFFSET_PHYS_DEV_TERM:QWORD +EXTERN INSTANCE_OFFSET_ICD_TERM:QWORD +EXTERN DISPATCH_OFFSET_ICD_TERM:QWORD +EXTERN EXT_OFFSET_DEVICE_DISPATCH:QWORD + PhysDevExtTramp macro num:req public vkPhysDevExtTramp&num& vkPhysDevExtTramp&num&: mov rax, qword ptr [rcx] ; Dereference the wrapped VkPhysicalDevice to get the dispatch table in rax - mov rcx, qword ptr [rcx + PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] ; Load the unwrapped VkPhysicalDevice into rcx - jmp qword ptr [rax + (PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * num))] ; Jump to the next function in the chain, preserving the args in other registers + add rcx, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP + mov rcx, qword ptr [rcx] ; Load the unwrapped VkPhysicalDevice into rcx + add rax, PHYS_DEV_OFFSET_INST_DISPATCH + jmp qword ptr [rax + PTR_SIZE * num] ; Jump to the next function in the chain, preserving the args in other registers endm PhysDevExtTermin macro num public vkPhysDevExtTermin&num& vkPhysDevExtTermin&num&: - mov rax, qword ptr [rcx + ICD_TERM_OFFSET_PHYS_DEV_TERM] ; Store the loader_icd_term* in rax - cmp qword ptr [rax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * num))], 0 ; Check if the next function in the chain is NULL + add rcx, ICD_TERM_OFFSET_PHYS_DEV_TERM + mov rax, qword ptr [rcx] ; Store the loader_icd_term* in rax + sub rcx, ICD_TERM_OFFSET_PHYS_DEV_TERM + add rax, DISPATCH_OFFSET_ICD_TERM + cmp qword ptr [rax + PTR_SIZE * num], 0 ; Check if the next function in the chain is NULL je terminError&num& ; Go to the error section if it is NULL - mov rcx, qword ptr [rcx + PHYS_DEV_OFFSET_PHYS_DEV_TERM] ; Load the unwrapped VkPhysicalDevice into the first arg - jmp qword ptr [rax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * num))] ; Jump to the next function in the chain + add rcx, PHYS_DEV_OFFSET_PHYS_DEV_TERM + mov rcx, qword ptr [rcx] ; Load the unwrapped VkPhysicalDevice into the first arg + jmp qword ptr [rax + PTR_SIZE * num] ; Jump to the next function in the chain terminError&num&: sub rsp, 56 ; Create the stack frame - mov rcx, qword ptr [rax + INSTANCE_OFFSET_ICD_TERM] ; Load the loader_instance into rcx (first arg) - mov rax, qword ptr [rcx + (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * num))] ; Load the func name into rax + sub rax, DISPATCH_OFFSET_ICD_TERM + add rax, INSTANCE_OFFSET_ICD_TERM + mov rcx, qword ptr [rax] ; Load the loader_instance into rcx (first arg) + add rcx, FUNCTION_OFFSET_INSTANCE + mov rax, qword ptr [rcx + CHAR_PTR_SIZE * num] ; Load the func name into rax + sub rcx, FUNCTION_OFFSET_INSTANCE lea r9, termin_error_string ; Load the error string into r9 (fourth arg) xor r8d, r8d ; Set r8 to zero (third arg) mov qword ptr [rsp + 32], rax ; Move the func name onto the stack (fifth arg) - lea edx, [r8 + VULKAN_LOADER_ERROR_BIT] ; Write the error logging bit to rdx (second arg) + lea edx, VULKAN_LOADER_ERROR_BIT_VALUE ; Write the error logging bit to rdx (second arg) call loader_log ; Log the error message before we crash add rsp, 56 ; Clean up the stack frame mov rax, 0 @@ -66,38 +87,62 @@ DevExtTramp macro num public vkdev_ext&num& vkdev_ext&num&: mov rax, qword ptr [rcx] ; Dereference the handle to get the dispatch table - jmp qword ptr [rax + (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * num))] ; Jump to the appropriate call chain + add rax, EXT_OFFSET_DEVICE_DISPATCH + jmp qword ptr [rax + PTR_SIZE * num] ; Jump to the appropriate call chain endm ; 32-bit values and macro ELSE +PTR_SIZE equ 4 ; The size of a pointer +CHAR_PTR_SIZE equ 4 ; The size of a 'const char *' struct +EXTERN C VULKAN_LOADER_ERROR_BIT_VALUE:DWORD +EXTERN C FUNCTION_OFFSET_INSTANCE:DWORD +EXTERN C PHYS_DEV_OFFSET_INST_DISPATCH:DWORD +EXTERN C PHYS_DEV_OFFSET_PHYS_DEV_TRAMP:DWORD +EXTERN C ICD_TERM_OFFSET_PHYS_DEV_TERM:DWORD +EXTERN C PHYS_DEV_OFFSET_PHYS_DEV_TERM:DWORD +EXTERN C INSTANCE_OFFSET_ICD_TERM:DWORD +EXTERN C DISPATCH_OFFSET_ICD_TERM:DWORD +EXTERN C EXT_OFFSET_DEVICE_DISPATCH:DWORD + PhysDevExtTramp macro num public _vkPhysDevExtTramp&num&@4 _vkPhysDevExtTramp&num&@4: mov eax, dword ptr [esp + 4] ; Load the wrapped VkPhysicalDevice into eax - mov ecx, [eax + PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] ; Load the unwrapped VkPhysicalDevice into ecx + add eax, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP + mov ecx, [eax] ; Load the unwrapped VkPhysicalDevice into ecx + sub eax, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP mov [esp + 4], ecx ; Overwrite the wrapped VkPhysicalDevice with the unwrapped one (on the stack) mov eax, [eax] ; Dereference the wrapped VkPhysicalDevice to get the dispatch table in eax - jmp dword ptr [eax + (PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * num))] ; Jump to the next function in the chain, preserving the args on the stack + add eax, PHYS_DEV_OFFSET_INST_DISPATCH + jmp dword ptr [eax + (PTR_SIZE * num)] ; Jump to the next function in the chain, preserving the args on the stack endm PhysDevExtTermin macro num public _vkPhysDevExtTermin&num&@4 _vkPhysDevExtTermin&num&@4: mov ecx, dword ptr [esp + 4] ; Move the wrapped VkPhysicalDevice into ecx - mov eax, dword ptr [ecx + ICD_TERM_OFFSET_PHYS_DEV_TERM] ; Store the loader_icd_term* in eax - cmp dword ptr [eax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * num))], 0 ; Check if the next function in the chain is NULL - je terminError&num& ; Go to the error section if it is NULL - mov ecx, dword ptr [ecx + PHYS_DEV_OFFSET_PHYS_DEV_TERM] ; Unwrap the VkPhysicalDevice in ecx + add ecx, ICD_TERM_OFFSET_PHYS_DEV_TERM + mov eax, dword ptr [ecx] ; Store the loader_icd_term* in eax + sub ecx, ICD_TERM_OFFSET_PHYS_DEV_TERM + add eax, DISPATCH_OFFSET_ICD_TERM + cmp dword ptr [eax + (PTR_SIZE * num)], 0 ; Check if the next function in the chain is NULL + je terminError&num& + add ecx, PHYS_DEV_OFFSET_PHYS_DEV_TERM ; Go to the error section if it is NULL + mov ecx, dword ptr [ecx] ; Unwrap the VkPhysicalDevice in ecx mov dword ptr [esp + 4], ecx ; Copy the unwrapped VkPhysicalDevice into the first arg - jmp dword ptr [eax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * num))] ; Jump to the next function in the chain + jmp dword ptr [eax + (PTR_SIZE * num)] ; Jump to the next function in the chain terminError&num&: - mov eax, dword ptr [eax + INSTANCE_OFFSET_ICD_TERM] ; Load the loader_instance into eax - push dword ptr [eax + (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * num))] ; Push the func name (fifth arg) + sub eax, DISPATCH_OFFSET_ICD_TERM + add eax, INSTANCE_OFFSET_ICD_TERM + mov eax, dword ptr [eax] ; Load the loader_instance into eax + add eax, FUNCTION_OFFSET_INSTANCE + push dword ptr [eax + (CHAR_PTR_SIZE * num)] ; Push the func name (fifth arg) + sub eax, FUNCTION_OFFSET_INSTANCE push offset termin_error_string ; Push the error string (fourth arg) push 0 ; Push zero (third arg) - push VULKAN_LOADER_ERROR_BIT ; Push the error logging bit (second arg) + push VULKAN_LOADER_ERROR_BIT_VALUE ; Push the error logging bit (second arg) push eax ; Push the loader_instance (first arg) call _loader_log ; Log the error message before we crash add esp, 20 ; Clean up the args @@ -110,7 +155,8 @@ public _vkdev_ext&num&@4 _vkdev_ext&num&@4: mov eax, dword ptr [esp + 4] ; Dereference the handle to get VkDevice chain_device mov eax, dword ptr [eax] ; Dereference the chain_device to get the loader_dispatch - jmp dword ptr [eax + (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * num))] ; Jump to the appropriate call chain + add eax, EXT_OFFSET_DEVICE_DISPATCH + jmp dword ptr [eax + (PTR_SIZE * num)] ; Jump to the appropriate call chain endm ; This is also needed for 32-bit only diff --git a/scripts/parse_asm_values.py b/scripts/parse_asm_values.py deleted file mode 100644 index 157fb7d5e..000000000 --- a/scripts/parse_asm_values.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/python3 -i -# -# Copyright (c) 2022 The Khronos Group Inc. -# Copyright (c) 2022 LunarG, Inc. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Author: Charles Giessen - -# This script reads in the 'intermediate output' of a compiler to look for sizeof/offsetof information -# necessary for the assembler portions of the loader. This is achieved by forcing the compiler to output -# the intermediate assembly output and looking for specific patterns which contain the relevant information - -import sys -import os.path -from os.path import exists -import re -import subprocess -import traceback - - -# Where to write the "gen_defines.asm" file -destination_file = sys.argv[1] -# The location the build system puts the intermediate asm file which depends on the compiler -source_asm_file = sys.argv[2] -# Whether we are using "MASM", "MARMASM" or "GAS" for the assembler -assembler_type = sys.argv[3] -# Whether we are using gcc, clang, or msvc -compiler = sys.argv[4] -# taken from CMAKE_SYSTEM_PROCESSOR - x86_64, aarch64|arm64, x86, aarch32|armhf -# Only used with GAS/MARMASM - MASM doesn't need this, as it has its own way to determine x86 vs x64 -arch = sys.argv[5] - -POSIX_COMPILERS = ["GNU", "Clang", "AppleClang"] - -if destination_file is None or source_asm_file is None or assembler_type is None or compiler is None or arch is None: - print("Required command line arguments were not provided") - sys.exit(1) - -defines = ["VULKAN_LOADER_ERROR_BIT", - "PTR_SIZE", - "CHAR_PTR_SIZE", - "FUNCTION_OFFSET_INSTANCE", - "PHYS_DEV_OFFSET_INST_DISPATCH", - "PHYS_DEV_OFFSET_PHYS_DEV_TRAMP", - "ICD_TERM_OFFSET_PHYS_DEV_TERM", - "PHYS_DEV_OFFSET_PHYS_DEV_TERM", - "INSTANCE_OFFSET_ICD_TERM", - "DISPATCH_OFFSET_ICD_TERM", - "EXT_OFFSET_DEVICE_DISPATCH" ] - -if os.path.splitext(source_asm_file)[1] == ".a": - try: - ar_path = sys.argv[6] - asm_archive_member = sys.argv[7] - subprocess_result = subprocess.Popen([ar_path, "p", source_asm_file, asm_archive_member], stdout=subprocess.PIPE) - asm_intermediate_file = subprocess_result.stdout.read().decode("utf-8") - except IOError: - print("Could not open assembler archive file:", source_asm_file) - traceback.print_exc() - sys.exit(1) -else: - try: - with open(source_asm_file, 'r') as f: - asm_intermediate_file = f.read() - except IOError: - print("Could not open assembler file:", source_asm_file) - sys.exit(1) - -with open(destination_file, "w", encoding="utf-8") as dest: - # special case vulkan error bit due to it not appearing in the asm - its defined in the header as 8 so it shouldn't change - if assembler_type == "MASM": - dest.write("VULKAN_LOADER_ERROR_BIT equ 8;\n") - elif assembler_type == 'MARMASM': - dest.write(' AREA loader_structs_details, DATA,READONLY\n') - if arch == "aarch64" or arch == "arm64": - dest.write("AARCH_64 EQU 1\n") - elif arch in ["aarch32", "armhf", "arm"]: - dest.write("AARCH_64 EQU 0\n") - else: - print('The parameter "arch" has value of ', arch, ' which is not recognized') - dest.write("VULKAN_LOADER_ERROR_BIT EQU 8\n") - elif assembler_type == "GAS": - # let the assembler know which platform to use - if arch == "x86_64": - dest.write(".set X86_64, 1\n") - elif arch == "aarch64" or arch == "arm64": - dest.write(".set AARCH_64, 1\n") - elif arch in ["aarch32", "armhf", "arm"]: - dest.write(".set AARCH_64, 0\n") - else: - print('The parameter "arch" has value of ', arch, ' which is not recognized') - # Nothing to write in the x86 case - - for d in defines: - match = None - if compiler == "MSVC": - if d == "VULKAN_LOADER_ERROR_BIT": - continue # skip due to special case - if 'arm' in arch.lower(): - match = re.search('\\|'+ d + '\\| DCD[\t ]*0x([0-9a-f]+)', asm_intermediate_file) - else: - match = re.search(d + " DD [ ]*([0-9a-f]+)H", asm_intermediate_file) - elif compiler in POSIX_COMPILERS: - match = re.search(d + " = ([0-9]+)", asm_intermediate_file) - - if len(match.groups()) > 0: - if compiler == "MSVC": - value = str(int(match.group(1), 16)) - elif compiler in POSIX_COMPILERS: - value = match.group(1) - - # MASM uses hex values, decode them here - if assembler_type == "MASM": - dest.write(d + " equ " + value +";\n") - elif assembler_type == 'MARMASM': - dest.write(d + ' EQU ' + value +'\n') - elif assembler_type == "GAS": - dest.write(".set " + d + ", " + value + "\n") - else: - print("Couldn't find ", d) - sys.exit(1) - if assembler_type == 'MARMASM': - dest.write(" END\n") -