Home | History | Annotate | Download | only in mapi
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2010 LunarG Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Chia-I Wu <olv (at) lunarg.com>
     26  */
     27 
     28 #include <string.h>
     29 
     30 #ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY
     31 #define HIDDEN __attribute__((visibility("hidden")))
     32 #else
     33 #define HIDDEN
     34 #endif
     35 
     36 __asm__(".text");
     37 
     38 __asm__("x86_current_tls:\n\t"
     39 	"call 1f\n"
     40         "1:\n\t"
     41         "popl %eax\n\t"
     42 	"addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %eax\n\t"
     43 	"movl " ENTRY_CURRENT_TABLE "@GOTNTPOFF(%eax), %eax\n\t"
     44 	"ret");
     45 
     46 #ifndef GLX_X86_READONLY_TEXT
     47 __asm__(".section wtext, \"awx\", @progbits");
     48 #endif /* GLX_X86_READONLY_TEXT */
     49 
     50 __asm__(".balign 16\n"
     51         "x86_entry_start:");
     52 
     53 #define STUB_ASM_ENTRY(func)     \
     54    ".globl " func "\n"           \
     55    ".type " func ", @function\n" \
     56    ".balign 16\n"                \
     57    func ":"
     58 
     59 #define STUB_ASM_CODE(slot)      \
     60    "call x86_current_tls\n\t"    \
     61    "movl %gs:(%eax), %eax\n\t"   \
     62    "jmp *(4 * " slot ")(%eax)"
     63 
     64 #define MAPI_TMP_STUB_ASM_GCC
     65 #include "mapi_tmp.h"
     66 
     67 #ifndef GLX_X86_READONLY_TEXT
     68 __asm__(".balign 16\n"
     69         "x86_entry_end:");
     70 __asm__(".text");
     71 #endif /* GLX_X86_READONLY_TEXT */
     72 
     73 #ifndef MAPI_MODE_BRIDGE
     74 
     75 #include "u_execmem.h"
     76 
     77 extern unsigned long
     78 x86_current_tls();
     79 
     80 extern char x86_entry_start[] HIDDEN;
     81 extern char x86_entry_end[] HIDDEN;
     82 
     83 void
     84 entry_patch_public(void)
     85 {
     86 #ifndef GLX_X86_READONLY_TEXT
     87    char patch[8] = {
     88       0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* movl %gs:0x0, %eax */
     89       0x90, 0x90                          /* nop's */
     90    };
     91    char *entry;
     92 
     93    *((unsigned long *) (patch + 2)) = x86_current_tls();
     94 
     95    for (entry = x86_entry_start; entry < x86_entry_end; entry += 16)
     96       memcpy(entry, patch, sizeof(patch));
     97 #endif
     98 }
     99 
    100 mapi_func
    101 entry_get_public(int slot)
    102 {
    103    return (mapi_func) (x86_entry_start + slot * 16);
    104 }
    105 
    106 void
    107 entry_patch(mapi_func entry, int slot)
    108 {
    109    char *code = (char *) entry;
    110    *((unsigned long *) (code + 8)) = slot * sizeof(mapi_func);
    111 }
    112 
    113 mapi_func
    114 entry_generate(int slot)
    115 {
    116    const char code_templ[16] = {
    117       0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* movl %gs:0x0, %eax */
    118       0xff, 0xa0, 0x34, 0x12, 0x00, 0x00, /* jmp *0x1234(%eax) */
    119       0x90, 0x90, 0x90, 0x90              /* nop's */
    120    };
    121    char *code;
    122    mapi_func entry;
    123 
    124    code = u_execmem_alloc(sizeof(code_templ));
    125    if (!code)
    126       return NULL;
    127 
    128    memcpy(code, code_templ, sizeof(code_templ));
    129 
    130    *((unsigned long *) (code + 2)) = x86_current_tls();
    131    entry = (mapi_func) code;
    132    entry_patch(entry, slot);
    133 
    134    return entry;
    135 }
    136 
    137 #endif /* MAPI_MODE_BRIDGE */
    138