/* * Copyright (c) 2015, NVIDIA CORPORATION. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and/or associated documentation files (the * "Materials"), to deal in the Materials without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Materials, and to * permit persons to whom the Materials are furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * unaltered in all copies or substantial portions of the Materials. * Any additions, deletions, or changes to the original source files * must be clearly indicated in accompanying documentation. * * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ #include "glvnd_genentry.h" #include "utils_misc.h" #include "compiler.h" #include #include #include #include #include #include #if defined(USE_DISPATCH_ASM) #define _U_STRINGIFY(x) #x #define U_STRINGIFY(x) _U_STRINGIFY(x) #define GLX_STUBS_COUNT #include "g_glx_dispatch_stub_list.h" USED static GLVNDentrypointStub entrypointFunctions[GENERATED_ENTRYPOINT_MAX]; static char *entrypointNames[GENERATED_ENTRYPOINT_MAX] = {}; static int entrypointCount = 0; extern char glx_entrypoint_start[]; extern char glx_entrypoint_end[]; #if defined(USE_X86_ASM) #define STUB_SIZE 32 #define STUB_ASM_ARCH(slot) \ "push %ebx\n" \ "call 1f\n" \ "1:\n" \ "popl %ebx\n" \ "addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx\n" \ "movl entrypointFunctions@GOT(%ebx), %eax\n" \ "pop %ebx\n" \ "jmp *(4 * " slot ")(%eax)\n" #elif defined(USE_X86_64_ASM) #define STUB_SIZE 16 #define STUB_ASM_ARCH(slot) \ "movq entrypointFunctions@GOTPCREL(%rip), %rax\n\t" \ "jmp *(8 * " slot ")(%rax)\n" #elif defined(USE_ARMV7_ASM) #define STUB_SIZE 64 #define STUB_ASM_ARCH(slot) \ "ldr ip, 1f\n" \ "12:\n" \ "add ip, pc\n" \ "push { r0 }\n" \ "ldr r0, 1f+4\n" \ "add ip, r0\n" \ "pop { r0 }\n" \ "ldr ip, [ip]\n" \ "bx ip\n" \ "1:\n" \ ".word entrypointFunctions - (12b + 8)\n" \ ".word " slot " * 4\n" #elif defined(USE_AARCH64_ASM) #define STUB_SIZE 16 #define STUB_ASM_ARCH(slot) \ "hint #34\n" \ "adrp x16, entrypointFunctions + " slot "*8\n" \ "ldr x16, [x16, #:lo12:(entrypointFunctions + " slot "*8)]\n" \ "br x16\n" #elif defined(USE_PPC64_ASM) && defined(_CALL_ELF) && (_CALL_ELF == 2) #define STUB_SIZE 32 #define STUB_ASM_ARCH(slot) \ "0:\n" \ "addis 2,12,.TOC.-0b@ha\n" \ "addi 2,2,.TOC.-0b@l\n" \ "addis 11, 2, entrypointFunctions@got@ha\n" \ "ld 11, entrypointFunctions@got@l(11)\n" \ "ld 12, (" slot " * 8)(11)\n" \ "mtctr 12\n" \ "bctr\n" #elif defined(USE_LOONGARCH64_ASM) #define STUB_SIZE 32 #define STUB_ASM_ARCH(slot) \ "la.global $t0,entrypointFunctions\n" \ "li.d $t1," slot "*8\r\n" \ "add.d $t0, $t0,$t1\r\n" \ "ld.d $t0, $t0,0\n" \ "jirl $r0, $t0,0\n" #else #error "Can't happen -- not implemented" #endif #define STUB_ASM(slot) \ ".globl glx_entrypoint_stub_" slot "\n" \ ".hidden glx_entrypoint_stub_" slot "\n" \ ".balign " U_STRINGIFY(STUB_SIZE) "\n" \ "glx_entrypoint_stub_" slot ":\n" \ STUB_ASM_ARCH(slot) __asm__(".globl glx_entrypoint_start\n" ".hidden glx_entrypoint_start\n" ".balign " U_STRINGIFY(STUB_SIZE) "\n" \ "glx_entrypoint_start:\n" #if defined(USE_ARMV7_ASM) && defined(__thumb__) ".arm\n" #endif #define GLX_STUBS_ASM #include "g_glx_dispatch_stub_list.h" ".globl glx_entrypoint_end\n" ".hidden glx_entrypoint_end\n" ".balign " U_STRINGIFY(STUB_SIZE) "\n" \ "glx_entrypoint_end:\n" #if defined(USE_ARMV7_ASM) && defined(__thumb__) ".thumb\n" #endif ); static void *DefaultDispatchFunc(void) { // Print a warning message? return NULL; } static GLVNDentrypointStub GetEntrypointStub(int index) { return (GLVNDentrypointStub) (glx_entrypoint_start + (index * STUB_SIZE)); } GLVNDentrypointStub glvndGenerateEntrypoint(const char *procName) { int i; for (i=0; i= GENERATED_ENTRYPOINT_MAX) { return NULL; } entrypointNames[entrypointCount] = strdup(procName); if (entrypointNames[entrypointCount] == NULL) { return NULL; } entrypointFunctions[entrypointCount] = (GLVNDentrypointStub) DefaultDispatchFunc; entrypointCount++; return GetEntrypointStub(entrypointCount - 1); } void glvndFreeEntrypoints(void) { int i; for (i=0; i