GLdispatch: Fix the x86 TLS stubs.

Fix the generated code for the x86 TLS dispatch stubs.

Update the x86 TLS stubs to use the same common code as the rest of the x86 and
x86-64 entrypoints.

Fixes https://github.com/NVIDIA/libglvnd/issues/18
This commit is contained in:
Kyle Brenneman 2016-09-27 15:56:01 -06:00
parent 522c601799
commit f9117614be
3 changed files with 44 additions and 85 deletions

View file

@ -140,18 +140,13 @@ AC_MSG_RESULT($HAVE_INIT_TLS)
AC_MSG_CHECKING([for entrypoint stub type])
case "x$asm_arch" in
xx86)
# The x86 TLS stubs don't work, so use the TSD stubs instead.
gldispatch_entry_type=x86_tsd
gldispatch_use_tls=no
;;
xx86_64)
# For x86-64, both the TLS and TSD stubs work.
xx86 | xx86_64)
# For x86 and x86-64, both the TLS and TSD stubs work.
if test "x$HAVE_INIT_TLS" = "xyes" ; then
gldispatch_entry_type=x86_64_tls
gldispatch_entry_type=${asm_arch}_tls
gldispatch_use_tls=yes
else
gldispatch_entry_type=x86_64_tsd
gldispatch_entry_type=${asm_arch}_tsd
gldispatch_use_tls=no
fi
;;

View file

@ -4,6 +4,8 @@
if GLDISPATCH_TYPE_X86_TLS
MAPI_GLDISPATCH_ENTRY_FILES = entry_x86_tls.c
MAPI_GLDISPATCH_ENTRY_FILES += entry_x86_64_common.c
MAPI_GLDISPATCH_ENTRY_FILES += entry_common.c
endif
if GLDISPATCH_TYPE_X86_TSD

View file

@ -25,19 +25,28 @@
* Chia-I Wu <olv@lunarg.com>
*/
#include <string.h>
#include <assert.h>
#include "u_macros.h"
#include "utils_misc.h"
#include "entry.h"
#include "entry_common.h"
#define ENTRY_STUB_ALIGN 32
#include <assert.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include "utils_misc.h"
#include "u_macros.h"
#include "glapi.h"
#include "glvnd/GLdispatchABI.h"
#define ENTRY_STUB_ALIGN 16
#define ENTRY_STUB_SIZE ENTRY_STUB_ALIGN
#define ENTRY_STUB_ALIGN_DIRECTIVE ".balign " U_STRINGIFY(ENTRY_STUB_ALIGN) "\n"
__asm__(".section wtext, \"awx\", @progbits");
__asm__(ENTRY_STUB_ALIGN_DIRECTIVE
"x86_entry_start:");
__asm__(".section wtext,\"ax\",@progbits\n");
__asm__(".balign 4096\n"
".globl public_entry_start\n"
".hidden public_entry_start\n"
"public_entry_start:");
#define STUB_ASM_ENTRY(func) \
".globl " func "\n" \
@ -51,9 +60,13 @@ __asm__(ENTRY_STUB_ALIGN_DIRECTIVE
"jmp *(4 * " slot ")(%eax)"
#define MAPI_TMP_STUB_ASM_GCC
#define MAPI_TMP_TABLE
#include "mapi_tmp.h"
__asm__(".balign 4096\n"
".globl public_entry_end\n"
".hidden public_entry_end\n"
"public_entry_end:");
__asm__(".text\n");
__asm__("x86_current_tls:\n\t"
@ -62,80 +75,29 @@ __asm__("x86_current_tls:\n\t"
"1:\n\t"
"popl %eax\n\t"
"addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %eax\n\t"
"movl " ENTRY_CURRENT_TABLE "@GOTNTPOFF(%eax), %eax\n\t"
"movl _glapi_tls_Current@GOTNTPOFF(%eax), %eax\n\t"
"ret");
#include "u_execmem.h"
extern unsigned long
extern uint32_t
x86_current_tls();
static char x86_entry_start[];
const int entry_type = ENTRY_X86_TLS;
const int entry_type = __GLDISPATCH_STUB_X86;
const int entry_stub_size = ENTRY_STUB_SIZE;
static const unsigned char ENTRY_TEMPLATE[] =
{
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* movl %gs:0x0, %eax */
0xff, 0xa0, 0x34, 0x12, 0x00, 0x00, /* jmp *0x1234(%eax) */
};
static const int TEMPLATE_OFFSET_TLS_OFFSET = 2;
static const int TEMPLATE_OFFSET_SLOT = 8;
void entry_generate_default_code(char *entry, int slot)
{
unsigned int *p;
unsigned long tls_addr;
char tmpl[] = {
0x65, 0xa1, 0x0, 0x0, 0x0, 0x0, // movl %gs:0x0,%eax
0xff, 0x20, // jmp *(%eax)
0x90, 0x90, 0x90, 0x90, // nop's
0x90
};
char *writeEntry = u_execmem_get_writable(entry);
STATIC_ASSERT(sizeof(mapi_func) == 4);
STATIC_ASSERT(ENTRY_STUB_SIZE >= sizeof(tmpl));
tls_addr = x86_current_tls();
p = (unsigned int *)&tmpl[2];
*p = (unsigned int)tls_addr;
p = (unsigned int *)&tmpl[8];
*p = (unsigned int)(4 * slot);
memcpy(entry, tmpl, sizeof(tmpl));
memcpy(writeEntry, ENTRY_TEMPLATE, sizeof(ENTRY_TEMPLATE));
*((uint32_t *) (writeEntry + TEMPLATE_OFFSET_TLS_OFFSET)) = x86_current_tls();
*((uint32_t *) (writeEntry + TEMPLATE_OFFSET_SLOT)) = (uint32_t) (slot * sizeof(mapi_func));
}
void
entry_init_public(void)
{
int slot;
// Patch the stubs with a more optimal code sequence
for (slot = 0; slot < MAPI_TABLE_NUM_STATIC; slot++)
entry_generate_default_code((char *) entry_get_public(slot), slot);
}
mapi_func
entry_get_public(int slot)
{
return (mapi_func) (x86_entry_start + slot * ENTRY_STUB_SIZE);
}
#if !defined(STATIC_DISPATCH_ONLY)
void
entry_patch(mapi_func entry, int slot)
{
entry_generate_default_code((char *)entry, slot);
}
mapi_func
entry_generate(int slot)
{
void *code;
code = u_execmem_alloc(ENTRY_STUB_SIZE);
if (!code)
return NULL;
entry_generate_default_code(code, slot);
return (mapi_func) code;
}
#endif // !defined(STATIC_DISPATCH_ONLY)