mapi: Add and use entry_get_public.
authorChia-I Wu <olv@lunarg.com>
Fri, 24 Dec 2010 07:06:41 +0000 (15:06 +0800)
committerChia-I Wu <olv@lunarg.com>
Fri, 24 Dec 2010 09:33:49 +0000 (17:33 +0800)
Given a dispatch slot, entry_get_public returns the address of the
corresponding public entry point.  There may be more than one of them.
But since they are all equivalent, it is fine to return any one of them.

With entry_get_public, the address of any public entry point can be
calculated at runtime when an assembly dispatcher is used.  There is no
need to have a mapping table in such case.  This omits the unnecessary
relocations from the binary.

src/mapi/mapi/entry.c
src/mapi/mapi/entry.h
src/mapi/mapi/entry_x86-64_tls.h
src/mapi/mapi/entry_x86_tls.h
src/mapi/mapi/entry_x86_tsd.h
src/mapi/mapi/mapi_abi.py
src/mapi/mapi/stub.c

index 1f84ad910b51a2c7207ea5dcd3bdf34d649fcef6..69b6134bd27c5fcff96a774911cea5b77a6ecbd6 100644 (file)
@@ -42,6 +42,8 @@
 #include "u_current.h"
 
 /* C version of the public entries */
+#define MAPI_TMP_DEFINES
+#define MAPI_TMP_PUBLIC_DECLARES
 #define MAPI_TMP_PUBLIC_ENTRIES
 #include "mapi_tmp.h"
 
@@ -50,6 +52,13 @@ entry_patch_public(void)
 {
 }
 
+mapi_func
+entry_get_public(int slot)
+{
+   /* pubic_entries are defined by MAPI_TMP_PUBLIC_ENTRIES */
+   return public_entries[slot];
+}
+
 mapi_func
 entry_generate(int slot)
 {
index 48ed3f9ec4a0550d779d20f04e68e9812177a484..4d7e1f6d16e6079ac634b494fc1894bb83e499f0 100644 (file)
 #include "u_compiler.h"
 #include "stub.h"
 
-/* declare public entries */
-#define MAPI_TMP_DEFINES
-#define MAPI_TMP_PUBLIC_DECLARES
-#include "mapi_tmp.h"
-
 void
 entry_patch_public(void);
 
+mapi_func
+entry_get_public(int slot);
+
 mapi_func
 entry_generate(int slot);
 
index 2c02933802f4815785e6de3f8ddd4f032576ad7d..d14bf1c394698af92ff29c4ebed91b556e31aaa8 100644 (file)
@@ -49,6 +49,9 @@ __asm__("x86_64_current_tls:\n\t"
        "movq u_current_table@GOTTPOFF(%rip), %rax\n\t"
        "ret");
 
+__asm__(".balign 32\n"
+        "x86_64_entry_start:");
+
 #define STUB_ASM_ENTRY(func)                             \
    ".globl " func "\n"                                   \
    ".type " func ", @function\n"                         \
@@ -71,6 +74,13 @@ entry_patch_public(void)
 {
 }
 
+mapi_func
+entry_get_public(int slot)
+{
+   extern char x86_64_entry_start[];
+   return (mapi_func) (x86_64_entry_start + slot * 32);
+}
+
 void
 entry_patch(mapi_func entry, int slot)
 {
index 3d0b7caffe13fe367a92a6043861467a11c9e29b..ea63490e1c782482d3693a2956b01fe0dbf1f01a 100644 (file)
@@ -54,11 +54,12 @@ __asm__("x86_current_tls:\n\t"
        "ret");
 
 #ifndef GLX_X86_READONLY_TEXT
-__asm__(".section wtext, \"awx\", @progbits\n"
-        ".balign 16\n"
-        "x86_entry_start:");
+__asm__(".section wtext, \"awx\", @progbits");
 #endif /* GLX_X86_READONLY_TEXT */
 
+__asm__(".balign 16\n"
+        "x86_entry_start:");
+
 #define STUB_ASM_ENTRY(func)     \
    ".globl " func "\n"           \
    ".type " func ", @function\n" \
@@ -101,6 +102,13 @@ entry_patch_public(void)
 #endif
 }
 
+mapi_func
+entry_get_public(int slot)
+{
+   extern char x86_entry_start[];
+   return (mapi_func) (x86_entry_start + slot * 16);
+}
+
 void
 entry_patch(mapi_func entry, int slot)
 {
index f37c7473a6f36d78ea9cadccaf71931fd44d88b6..0a07ad7424786161699c0741d6883b278b185afb 100644 (file)
@@ -32,7 +32,9 @@
 
 #define X86_ENTRY_SIZE 32
 
-__asm__(".text");
+__asm__(".text\n"
+        ".balign 32\n"
+        "x86_entry_start:");
 
 #define STUB_ASM_ENTRY(func)        \
    ".globl " func "\n"              \
@@ -60,6 +62,13 @@ entry_patch_public(void)
 {
 }
 
+mapi_func
+entry_get_public(int slot)
+{
+   extern const char x86_entry_start[];
+   return (mapi_func) (x86_entry_start + slot * X86_ENTRY_SIZE);
+}
+
 void
 entry_patch(mapi_func entry, int slot)
 {
index 0949219c2c4e17d21366a1e5a44686ab6b6c18aa..5c212420a80190e56801ce8f1d3ce14b9920fb30 100644 (file)
@@ -378,6 +378,19 @@ class ABIPrinter(object):
 
         return '\n\n'.join(dispatches)
 
+    def c_public_initializer(self, prefix):
+        """Return the initializer for public dispatch functions."""
+        names = []
+        for ent in self.entries:
+            if ent.alias:
+                continue
+
+            name = '%s(mapi_func) %s' % (self.indent,
+                    self._c_function_call(ent, prefix))
+            names.append(name)
+
+        return ',\n'.join(names)
+
     def c_stub_string_pool(self):
         """Return the string pool for use by stubs."""
         # sort entries by their names
@@ -400,9 +413,8 @@ class ABIPrinter(object):
         """Return the initializer for struct mapi_stub array."""
         stubs = []
         for ent in self.entries_sorted_by_names:
-            stubs.append('%s{ (mapi_func) %s, %d, (void *) %d }' % (
-                self.indent, self._c_function_call(ent, prefix),
-                ent.slot, pool_offsets[ent]))
+            stubs.append('%s{ (void *) %d, %d, NULL }' % (
+                self.indent, pool_offsets[ent], ent.slot))
 
         return ',\n'.join(stubs)
 
@@ -526,6 +538,10 @@ class ABIPrinter(object):
             print
             print '#ifdef MAPI_TMP_PUBLIC_ENTRIES'
             print self.c_public_dispatches(self.prefix_lib)
+            print
+            print 'static const mapi_func public_entries[] = {'
+            print self.c_public_initializer(self.prefix_lib)
+            print '};'
             print '#undef MAPI_TMP_PUBLIC_ENTRIES'
             print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */'
 
index 9a5c1d694b39feecf02281bade885ae3662305eb..99b475a3b4b23012751e0834943229740aab7eb4 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <stdlib.h>
-#include <stddef.h> /* for offsetof */
 #include <string.h>
 #include <assert.h>
 
@@ -40,9 +39,9 @@
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
 struct mapi_stub {
-   mapi_func addr;
-   int slot;
    const void *name;
+   int slot;
+   mapi_func addr;
 };
 
 /* define public_string_pool and public_stubs */
@@ -203,5 +202,6 @@ stub_get_slot(const struct mapi_stub *stub)
 mapi_func
 stub_get_addr(const struct mapi_stub *stub)
 {
-   return stub->addr;
+   assert(stub->addr || (unsigned int) stub->slot < MAPI_TABLE_NUM_STATIC);
+   return (stub->addr) ? stub->addr : entry_get_public(stub->slot);
 }