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@lunarg.com>
26  */
27 
28 #ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY
29 #define HIDDEN __attribute__((visibility("hidden")))
30 #else
31 #define HIDDEN
32 #endif
33 
34 __asm__(".text\n"
35         ".balign 32\n"
36         "x86_64_entry_start:");
37 
38 #define STUB_ASM_ENTRY(func)                             \
39    ".globl " func "\n"                                   \
40    ".type " func ", @function\n"                         \
41    ".balign 32\n"                                        \
42    func ":"
43 
44 #ifndef __ILP32__
45 
46 #define STUB_ASM_CODE(slot)                              \
47    "movq " ENTRY_CURRENT_TABLE "@GOTTPOFF(%rip), %rax\n\t"  \
48    "movq %fs:(%rax), %r11\n\t"                           \
49    "jmp *(8 * " slot ")(%r11)"
50 
51 #else
52 
53 #define STUB_ASM_CODE(slot)                              \
54    "movq " ENTRY_CURRENT_TABLE "@GOTTPOFF(%rip), %rax\n\t"  \
55    "movl %fs:(%rax), %r11d\n\t"                          \
56    "movl 4*" slot "(%r11d), %r11d\n\t"                   \
57    "jmp *%r11"
58 
59 #endif
60 
61 #define MAPI_TMP_STUB_ASM_GCC
62 #include "mapi_tmp.h"
63 
64 #ifndef MAPI_MODE_BRIDGE
65 
66 #include <string.h>
67 #include "u_execmem.h"
68 
69 void
entry_patch_public(void)70 entry_patch_public(void)
71 {
72 }
73 
74 extern char
75 x86_64_entry_start[] HIDDEN;
76 
77 mapi_func
entry_get_public(int slot)78 entry_get_public(int slot)
79 {
80    return (mapi_func) (x86_64_entry_start + slot * 32);
81 }
82 
83 void
entry_patch(mapi_func entry,int slot)84 entry_patch(mapi_func entry, int slot)
85 {
86    char *code = (char *) entry;
87    int offset = 12;
88 #ifdef __ILP32__
89    offset = 13;
90 #endif
91    *((unsigned int *) (code + offset)) = slot * sizeof(mapi_func);
92 }
93 
94 mapi_func
entry_generate(int slot)95 entry_generate(int slot)
96 {
97    const char code_templ[] = {
98 #ifndef __ILP32__
99       /* movq %fs:0, %r11 */
100       0x64, 0x4c, 0x8b, 0x1c, 0x25, 0x00, 0x00, 0x00, 0x00,
101       /* jmp *0x1234(%r11) */
102       0x41, 0xff, 0xa3, 0x34, 0x12, 0x00, 0x00,
103 #else
104       /* movl %fs:0, %r11d */
105       0x64, 0x44, 0x8b, 0x1c, 0x25, 0x00, 0x00, 0x00, 0x00,
106       /* movl 0x1234(%r11d), %r11d */
107       0x67, 0x45, 0x8b, 0x9b, 0x34, 0x12, 0x00, 0x00,
108       /* jmp *%r11 */
109       0x41, 0xff, 0xe3,
110 #endif
111    };
112    unsigned long long addr;
113    char *code;
114    mapi_func entry;
115 
116    __asm__("movq " ENTRY_CURRENT_TABLE "@GOTTPOFF(%%rip), %0"
117            : "=r" (addr));
118    if ((addr >> 32) != 0xffffffff)
119       return NULL;
120    addr &= 0xffffffff;
121 
122    code = u_execmem_alloc(sizeof(code_templ));
123    if (!code)
124       return NULL;
125 
126    memcpy(code, code_templ, sizeof(code_templ));
127 
128    *((unsigned int *) (code + 5)) = addr;
129    entry = (mapi_func) code;
130    entry_patch(entry, slot);
131 
132    return entry;
133 }
134 
135 #endif /* MAPI_MODE_BRIDGE */
136