]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Implement symbol relocations for the ELF binary reader.
authorRhys Weatherley <rweather@southern-storm.com.au>
Fri, 7 May 2004 01:43:12 +0000 (01:43 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Fri, 7 May 2004 01:43:12 +0000 (01:43 +0000)
ChangeLog
include/jit/jit-elf.h
jit/Makefile.am
jit/jit-context.c
jit/jit-elf-read.c
jit/jit-internal.h
jit/jit-symbol.c [new file with mode: 0644]

index 6f1547fdb10f1b9fb16d4241dde6ab6adae9f3d9..d75bdf5bddf1ab1f2ecda9b11abc55570d6b8d53 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        * dpas/dpas-builtin.c, dpas/dpas-scanner.l: add the "Flush"
        and "Terminate" builtins; fix a small bug in string scanning.
 
+       * include/jit/jit-elf.h, jit/Makefile.am, jit/jit-context.c,
+       jit/jit-elf-read.c, jit/jit-internal.h, jit/jit-symbol.c:
+       implement symbol relocations for the ELF binary reader.
+
 2004-05-06  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * dpas/Makefile.am, dpas/dpas-builtin.c, dpas/dpas-function.c,
index 84d78d405c889de4c6379f9cc11d85d282e1ff1a..929c188576e4125d4c9e2b4d9ac59691cb541aab 100644 (file)
@@ -71,6 +71,9 @@ void jit_readelf_add_to_context
        (jit_readelf_t readelf, jit_context_t context) JIT_NOTHROW;
 int jit_readelf_resolve_all
        (jit_context_t context, int print_failures) JIT_NOTHROW;
+int jit_readelf_register_symbol
+       (jit_context_t context, const char *name,
+        void *value, int after) JIT_NOTHROW;
 
 jit_writeelf_t jit_writeelf_create(const char *library_name) JIT_NOTHROW;
 void jit_writeelf_destroy(jit_writeelf_t writeelf) JIT_NOTHROW;
index f11f9d68a2e7ef0397ba6ff1e4c4e2ee75deb012..128cbf768fe8535ccb3cee26d73dc294c6a53f22 100644 (file)
@@ -44,6 +44,7 @@ libjit_a_SOURCES = \
                jit-rules-x86.h \
                jit-rules-x86.c \
                jit-string.c \
+               jit-symbol.c \
                jit-thread.c \
                jit-type.c \
                jit-value.c \
index 5c8abbc5a93e7425fac95c2233c4b592095fcc9c..8cf099fe97ee33de1aba8d49c53b10d0e3d1a59b 100644 (file)
@@ -100,6 +100,7 @@ jit_context_t jit_context_create(void)
 @*/
 void jit_context_destroy(jit_context_t context)
 {
+       int sym;
        if(context)
        {
                while(context->functions != 0)
@@ -110,6 +111,11 @@ void jit_context_destroy(jit_context_t context)
                {
                        _jit_cache_destroy(context->cache);
                }
+               for(sym = 0; sym < context->num_registered_symbols; ++sym)
+               {
+                       jit_free(context->registered_symbols[sym]);
+               }
+               jit_free(context->registered_symbols);
                jit_mutex_destroy(&(context->cache_lock));
                jit_mutex_destroy(&(context->builder_lock));
                jit_free(context);
index 223f36f47e46c3dc7449948ab494214f0041072c..944f66f5bd1ed98eda7f3865296bcbfefeabba6d 100644 (file)
@@ -97,6 +97,10 @@ existing format was better than inventing a completely new one.
        typedef Elf32_Off   Elf_Off;
        typedef Elf32_Dyn   Elf_Dyn;
        typedef Elf32_Sym   Elf_Sym;
+       typedef Elf32_Rel   Elf_Rel;
+       typedef Elf32_Rela  Elf_Rela;
+       #define ELF_R_SYM(val)  ELF32_R_SYM((val))
+       #define ELF_R_TYPE(val) ELF32_R_TYPE((val))
 #else
        typedef Elf64_Ehdr  Elf_Ehdr;
        typedef Elf64_Shdr  Elf_Shdr;
@@ -107,6 +111,10 @@ existing format was better than inventing a completely new one.
        typedef Elf64_Off   Elf_Off;
        typedef Elf64_Dyn   Elf_Dyn;
        typedef Elf64_Sym   Elf_Sym;
+       typedef Elf64_Rel   Elf_Rel;
+       typedef Elf64_Rela  Elf_Rela;
+       #define ELF_R_SYM(val)  ELF64_R_SYM((val))
+       #define ELF_R_TYPE(val) ELF64_R_TYPE((val))
 #endif
 
 /*
@@ -144,6 +152,8 @@ static jit_reloc_func get_reloc(unsigned int machine);
  */
 struct jit_readelf
 {
+       jit_readelf_t   next;
+       int                             resolved;
        Elf_Ehdr                ehdr;
        unsigned char  *phdrs;
        unsigned char  *shdrs;
@@ -683,6 +693,24 @@ static void load_dynamic_section(jit_readelf_t readelf, int flags)
                        }
                        break;
 
+                       case DT_RELA:
+                       {
+                               printf("address of Rela relocs: 0x%lx\n", (long)value);
+                       }
+                       break;
+
+                       case DT_RELASZ:
+                       {
+                               printf("total size of Rela relocs: %ld\n", (long)value);
+                       }
+                       break;
+
+                       case DT_RELAENT:
+                       {
+                               printf("size of one Rela reloc: %ld\n", (long)value);
+                       }
+                       break;
+
                        case DT_PLTREL:
                        {
                                printf("type of PLT relocs: %ld\n", (long)value);
@@ -1389,7 +1417,344 @@ const char *jit_readelf_get_needed(jit_readelf_t readelf, unsigned int index)
 @*/
 void jit_readelf_add_to_context(jit_readelf_t readelf, jit_context_t context)
 {
-       /* TODO */
+       if(!readelf || !context)
+       {
+               return;
+       }
+       jit_mutex_lock(&(context->cache_lock));
+       readelf->next = context->elf_binaries;
+       context->elf_binaries = readelf;
+       jit_mutex_unlock(&(context->cache_lock));
+}
+
+/*
+ * Import the internal symbol table from "jit-symbol.c".
+ */
+typedef struct
+{
+       const char *name;
+       void       *value;
+
+} jit_internalsym;
+extern jit_internalsym const _jit_internal_symbols[];
+extern int const _jit_num_internal_symbols;
+
+/*
+ * Resolve a symbol to an address.
+ */
+static void *resolve_symbol
+       (jit_context_t context, jit_readelf_t readelf,
+        int print_failures, const char *name, jit_nuint symbol)
+{
+       Elf_Sym *sym;
+       void *value;
+       const char *symbol_name;
+       jit_readelf_t library;
+       int index, left, right, cmp;
+
+       /* Find the actual symbol details */
+       if(symbol >= readelf->symbol_table_size)
+       {
+               if(print_failures)
+               {
+                       printf("%s: invalid symbol table index %lu\n",
+                                  name, (unsigned long)symbol);
+               }
+               return 0;
+       }
+       sym = &(readelf->symbol_table[symbol]);
+
+       /* Does the symbol have a locally-defined value? */
+       if(sym->st_value)
+       {
+               value = jit_readelf_map_vaddr(readelf, (jit_nuint)(sym->st_value));
+               if(!value)
+               {
+                       if(print_failures)
+                       {
+                               printf("%s: could not map virtual address 0x%lx\n",
+                                          name, (long)(sym->st_value));
+                       }
+               }
+               return value;
+       }
+
+       /* Get the symbol's name, so that we can look it up in other libraries */
+       symbol_name = get_dyn_string(readelf, sym->st_name);
+       if(!symbol_name)
+       {
+               if(print_failures)
+               {
+                       printf("%s: symbol table index %lu does not have a valid name\n",
+                                  name, (unsigned long)symbol);
+               }
+               return 0;
+       }
+
+       /* Look for "before" symbols that are registered with the context */
+       for(index = 0; index < context->num_registered_symbols; ++index)
+       {
+               if(!jit_strcmp(symbol_name, context->registered_symbols[index]->name) &&
+                  !(context->registered_symbols[index]->after))
+               {
+                       return context->registered_symbols[index]->value;
+               }
+       }
+
+       /* Search all loaded ELF libraries for the name */
+       library = context->elf_binaries;
+       while(library != 0)
+       {
+               value = jit_readelf_get_symbol(library, symbol_name);
+               if(value)
+               {
+                       return value;
+               }
+               library = library->next;
+       }
+
+       /* Look for libjit internal symbols (i.e. intrinsics) */
+       left = 0;
+       right = _jit_num_internal_symbols - 1;
+       while(left <= right)
+       {
+               index = (left + right) / 2;
+               cmp = jit_strcmp(symbol_name, _jit_internal_symbols[index].name);
+               if(cmp == 0)
+               {
+                       return _jit_internal_symbols[index].value;
+               }
+               else if(cmp < 0)
+               {
+                       right = index - 1;
+               }
+               else
+               {
+                       left = index + 1;
+               }
+       }
+
+       /* Look for "after" symbols that are registered with the context */
+       for(index = 0; index < context->num_registered_symbols; ++index)
+       {
+               if(!jit_strcmp(symbol_name, context->registered_symbols[index]->name) &&
+                  context->registered_symbols[index]->after)
+               {
+                       return context->registered_symbols[index]->value;
+               }
+       }
+
+       /* If we get here, then we could not resolve the symbol */
+       printf("%s: could not resolve `%s'\n", name, symbol_name);
+       return 0;
+}
+
+/*
+ * Perform a DT_REL style relocation on an ELF binary.
+ */
+static int perform_rel
+       (jit_context_t context, jit_readelf_t readelf, 
+        int print_failures, const char *name, Elf_Rel *reloc)
+{
+       void *address;
+       void *value;
+
+       /* Get the address to apply the relocation at */
+       address = jit_readelf_map_vaddr(readelf, (jit_nuint)(reloc->r_offset));
+       if(!address)
+       {
+               if(print_failures)
+               {
+                       printf("%s: cannot map virtual address 0x%lx\n",
+                                  name, (long)(reloc->r_offset));
+               }
+               return 0;
+       }
+
+       /* Resolve the designated symbol to its actual value */
+       value = resolve_symbol
+               (context, readelf, print_failures, name,
+                (jit_nuint)ELF_R_SYM(reloc->r_info));
+       if(!value)
+       {
+               return 0;
+       }
+
+       /* Perform the relocation */
+       if(!(*(readelf->reloc_func))
+               (readelf, address, (int)(ELF_R_TYPE(reloc->r_info)),
+                (jit_nuint)value, 0, 0))
+       {
+               if(print_failures)
+               {
+                       printf("%s: relocation type %d was not recognized\n",
+                                  name, (int)(ELF_R_TYPE(reloc->r_info)));
+               }
+               return 0;
+       }
+       return 1;
+}
+
+/*
+ * Perform a DT_RELA style relocation on an ELF binary.
+ */
+static int perform_rela
+       (jit_context_t context, jit_readelf_t readelf,
+        int print_failures, const char *name, Elf_Rela *reloc)
+{
+       void *address;
+       void *value;
+
+       /* Get the address to apply the relocation at */
+       address = jit_readelf_map_vaddr(readelf, (jit_nuint)(reloc->r_offset));
+       if(!address)
+       {
+               if(print_failures)
+               {
+                       printf("%s: cannot map virtual address 0x%lx\n",
+                                  name, (long)(reloc->r_offset));
+               }
+               return 0;
+       }
+
+       /* Resolve the designated symbol to its actual value */
+       value = resolve_symbol
+               (context, readelf, print_failures, name,
+                (jit_nuint)ELF_R_SYM(reloc->r_info));
+       if(!value)
+       {
+               return 0;
+       }
+
+       /* Perform the relocation */
+       if(!(*(readelf->reloc_func))
+               (readelf, address, (int)(ELF_R_TYPE(reloc->r_info)),
+                (jit_nuint)value, 1, (jit_nuint)(reloc->r_addend)))
+       {
+               if(print_failures)
+               {
+                       printf("%s: relocation type %d was not recognized\n",
+                                  name, (int)(ELF_R_TYPE(reloc->r_info)));
+               }
+               return 0;
+       }
+       return 1;
+}
+
+/*
+ * Perform relocations on an ELF binary.  Returns zero on failure.
+ */
+static int perform_relocations
+       (jit_context_t context, jit_readelf_t readelf, int print_failures)
+{
+       Elf_Addr address;
+       Elf_Addr table_size;
+       Elf_Addr entry_size;
+       unsigned char *table;
+       const char *name;
+       int ok = 1;
+
+       /* Get the library name, for printing diagnostic messages */
+       name = jit_readelf_get_name(readelf);
+       if(!name)
+       {
+               name = "unknown-elf-binary";
+       }
+
+       /* Bail out if we don't know how to perform relocations */
+       if(!(readelf->reloc_func))
+       {
+               if(print_failures)
+               {
+                       printf("%s: do not know how to perform relocations\n", name);
+               }
+               return 0;
+       }
+
+       /* Apply the "Rel" relocations in the dynamic section */
+       if(dynamic_for_type(readelf, DT_REL, &address) &&
+          dynamic_for_type(readelf, DT_RELSZ, &table_size) &&
+          dynamic_for_type(readelf, DT_RELENT, &entry_size) && entry_size)
+       {
+               table = (unsigned char *)jit_readelf_map_vaddr
+                       (readelf, (jit_nuint)address);
+               while(table && table_size >= entry_size)
+               {
+                       if(!perform_rel(context, readelf, print_failures, name,
+                                               (Elf_Rel *)table))
+                       {
+                               ok = 0;
+                       }
+                       table += (jit_nuint)entry_size;
+                       table_size -= entry_size;
+               }
+       }
+
+       /* Apply the "Rela" relocations in the dynamic section */
+       if(dynamic_for_type(readelf, DT_RELA, &address) &&
+          dynamic_for_type(readelf, DT_RELASZ, &table_size) &&
+          dynamic_for_type(readelf, DT_RELAENT, &entry_size) && entry_size)
+       {
+               table = (unsigned char *)jit_readelf_map_vaddr
+                       (readelf, (jit_nuint)address);
+               while(table && table_size >= entry_size)
+               {
+                       if(!perform_rela(context, readelf, print_failures, name,
+                                                (Elf_Rela *)table))
+                       {
+                               ok = 0;
+                       }
+                       table += (jit_nuint)entry_size;
+                       table_size -= entry_size;
+               }
+       }
+
+       /* Apply the "PLT" relocations in the dynamic section, which
+          may be either DT_REL or DT_RELA style relocations */
+       if(dynamic_for_type(readelf, DT_JMPREL, &address) &&
+          dynamic_for_type(readelf, DT_PLTRELSZ, &table_size) &&
+          dynamic_for_type(readelf, DT_PLTREL, &entry_size))
+       {
+               if(entry_size == DT_REL)
+               {
+                       if(dynamic_for_type(readelf, DT_RELENT, &entry_size) && entry_size)
+                       {
+                               table = (unsigned char *)jit_readelf_map_vaddr
+                                       (readelf, (jit_nuint)address);
+                               while(table && table_size >= entry_size)
+                               {
+                                       if(!perform_rel(context, readelf, print_failures, name,
+                                                               (Elf_Rel *)table))
+                                       {
+                                               ok = 0;
+                                       }
+                                       table += (jit_nuint)entry_size;
+                                       table_size -= entry_size;
+                               }
+                       }
+               }
+               else if(entry_size == DT_RELA)
+               {
+                       if(dynamic_for_type(readelf, DT_RELAENT, &entry_size) && entry_size)
+                       {
+                               table = (unsigned char *)jit_readelf_map_vaddr
+                                       (readelf, (jit_nuint)address);
+                               while(table && table_size >= entry_size)
+                               {
+                                       if(!perform_rela(context, readelf, print_failures, name,
+                                                                (Elf_Rela *)table))
+                                       {
+                                               ok = 0;
+                                       }
+                                       table += (jit_nuint)entry_size;
+                                       table_size -= entry_size;
+                               }
+                       }
+               }
+       }
+
+       /* Return to the caller */
+       return ok;
 }
 
 /*@
@@ -1407,8 +1772,82 @@ void jit_readelf_add_to_context(jit_readelf_t readelf, jit_context_t context)
 @*/
 int jit_readelf_resolve_all(jit_context_t context, int print_failures)
 {
-       /* TODO */
-       return 0;
+       jit_readelf_t readelf;
+       int ok = 1;
+       if(!context)
+       {
+               return 0;
+       }
+       jit_mutex_lock(&(context->cache_lock));
+       readelf = context->elf_binaries;
+       while(readelf != 0)
+       {
+               if(!(readelf->resolved))
+               {
+                       readelf->resolved = 1;
+                       if(!perform_relocations(context, readelf, print_failures))
+                       {
+                               ok = 0;
+                       }
+               }
+               readelf = readelf->next;
+       }
+       jit_mutex_unlock(&(context->cache_lock));
+       return ok;
+}
+
+/*@
+ * @deftypefun int jit_readelf_register_symbol (jit_context_t context, {const char *} name, {void *} value, int after)
+ * Register @code{value} with @code{name} on the specified @code{context}.
+ * Whenever symbols are resolved with @code{jit_readelf_resolve_all},
+ * and the symbol @code{name} is encountered, @code{value} will be
+ * substituted.  Returns zero if out of memory or there is something
+ * wrong with the parameters.
+ *
+ * If @code{after} is non-zero, then @code{name} will be resolved after all
+ * other ELF libraries; otherwise it will be resolved before the ELF
+ * libraries.
+ *
+ * This function is used to register intrinsic symbols that are specific to
+ * the front end virtual machine.  References to intrinsics within
+ * @code{libjit} itself are resolved automatically.
+ * @end deftypefun
+@*/
+int jit_readelf_register_symbol
+       (jit_context_t context, const char *name, void *value, int after)
+{
+       jit_regsym_t sym;
+       jit_regsym_t *new_list;
+
+       /* Bail out if there is something wrong with the parameters */
+       if(!context || !name || !value)
+       {
+               return 0;
+       }
+
+       /* Allocate and populate the symbol information block */
+       sym = (jit_regsym_t)jit_malloc
+               (sizeof(struct jit_regsym) + jit_strlen(name));
+       if(!sym)
+       {
+               return 0;
+       }
+       sym->value = value;
+       sym->after = after;
+       jit_strcpy(sym->name, name);
+
+       /* Add the symbol details to the registered list */
+       new_list = (jit_regsym_t *)jit_realloc
+               (context->registered_symbols,
+                sizeof(jit_regsym_t) * (context->num_registered_symbols + 1));
+       if(!new_list)
+       {
+               jit_free(sym);
+               return 0;
+       }
+       new_list[(context->num_registered_symbols)++] = sym;
+       context->registered_symbols = new_list;
+       return 1;
 }
 
 /************************************************************************
index a81f8c7ba5bc2de5aae3e0f7febf1feb3478d430..724fc2e5c71d9709628cab58c7b1ef06d90eff9f 100644 (file)
@@ -407,6 +407,17 @@ void _jit_function_compute_liveness(jit_function_t func);
  */
 void *_jit_function_compile_on_demand(jit_function_t func);
 
+/*
+ * Information about a registered external symbol.
+ */
+typedef struct jit_regsym *jit_regsym_t;
+struct jit_regsym
+{
+       void   *value;
+       int             after;
+       char    name[1];
+};
+
 /*
  * Internal structure of a context.
  */
@@ -427,6 +438,13 @@ struct _jit_context
 
        /* The context's function code cache */
        struct jit_cache   *cache;
+
+       /* ELF binaries that have been loaded into this context */
+       jit_readelf_t           elf_binaries;
+
+       /* Table of symbols that have been registered with this context */
+       jit_regsym_t       *registered_symbols;
+       int                                     num_registered_symbols;
 };
 
 /*
diff --git a/jit/jit-symbol.c b/jit/jit-symbol.c
new file mode 100644 (file)
index 0000000..3fec14e
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * jit-symbol.c - Table of registered intrinsic symbols.
+ *
+ * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "jit-internal.h"
+
+/*
+ * This list must be sorted, so that a binary search can be used on it.
+ */
+typedef struct
+{
+       const char *name;
+       void       *value;
+
+} jit_internalsym;
+jit_internalsym const _jit_internal_symbols[] = {
+       {"jit_exception_builtin", (void *)jit_exception_builtin},
+       {"jit_exception_get_stack_trace", (void *)jit_exception_get_stack_trace},
+       {"jit_exception_throw", (void *)jit_exception_throw},
+       {"jit_float32_abs", (void *)jit_float32_abs},
+       {"jit_float32_acos", (void *)jit_float32_acos},
+       {"jit_float32_add", (void *)jit_float32_add},
+       {"jit_float32_asin", (void *)jit_float32_asin},
+       {"jit_float32_atan", (void *)jit_float32_atan},
+       {"jit_float32_atan2", (void *)jit_float32_atan2},
+       {"jit_float32_ceil", (void *)jit_float32_ceil},
+       {"jit_float32_cmpg", (void *)jit_float32_cmpg},
+       {"jit_float32_cmpl", (void *)jit_float32_cmpl},
+       {"jit_float32_cos", (void *)jit_float32_cos},
+       {"jit_float32_cosh", (void *)jit_float32_cosh},
+       {"jit_float32_div", (void *)jit_float32_div},
+       {"jit_float32_eq", (void *)jit_float32_eq},
+       {"jit_float32_exp", (void *)jit_float32_exp},
+       {"jit_float32_floor", (void *)jit_float32_floor},
+       {"jit_float32_ge", (void *)jit_float32_ge},
+       {"jit_float32_gt", (void *)jit_float32_gt},
+       {"jit_float32_ieee_rem", (void *)jit_float32_ieee_rem},
+       {"jit_float32_is_finite", (void *)jit_float32_is_finite},
+       {"jit_float32_is_inf", (void *)jit_float32_is_inf},
+       {"jit_float32_is_nan", (void *)jit_float32_is_nan},
+       {"jit_float32_le", (void *)jit_float32_le},
+       {"jit_float32_log", (void *)jit_float32_log},
+       {"jit_float32_log10", (void *)jit_float32_log10},
+       {"jit_float32_lt", (void *)jit_float32_lt},
+       {"jit_float32_max", (void *)jit_float32_max},
+       {"jit_float32_min", (void *)jit_float32_min},
+       {"jit_float32_mul", (void *)jit_float32_mul},
+       {"jit_float32_ne", (void *)jit_float32_ne},
+       {"jit_float32_neg", (void *)jit_float32_neg},
+       {"jit_float32_pow", (void *)jit_float32_pow},
+       {"jit_float32_rem", (void *)jit_float32_rem},
+       {"jit_float32_rint", (void *)jit_float32_rint},
+       {"jit_float32_round", (void *)jit_float32_round},
+       {"jit_float32_sign", (void *)jit_float32_sign},
+       {"jit_float32_sin", (void *)jit_float32_sin},
+       {"jit_float32_sinh", (void *)jit_float32_sinh},
+       {"jit_float32_sqrt", (void *)jit_float32_sqrt},
+       {"jit_float32_sub", (void *)jit_float32_sub},
+       {"jit_float32_tan", (void *)jit_float32_tan},
+       {"jit_float32_tanh", (void *)jit_float32_tanh},
+       {"jit_float32_to_nfloat", (void *)jit_float32_to_nfloat},
+       {"jit_float64_abs", (void *)jit_float64_abs},
+       {"jit_float64_acos", (void *)jit_float64_acos},
+       {"jit_float64_add", (void *)jit_float64_add},
+       {"jit_float64_asin", (void *)jit_float64_asin},
+       {"jit_float64_atan", (void *)jit_float64_atan},
+       {"jit_float64_atan2", (void *)jit_float64_atan2},
+       {"jit_float64_ceil", (void *)jit_float64_ceil},
+       {"jit_float64_cmpg", (void *)jit_float64_cmpg},
+       {"jit_float64_cmpl", (void *)jit_float64_cmpl},
+       {"jit_float64_cos", (void *)jit_float64_cos},
+       {"jit_float64_cosh", (void *)jit_float64_cosh},
+       {"jit_float64_div", (void *)jit_float64_div},
+       {"jit_float64_eq", (void *)jit_float64_eq},
+       {"jit_float64_exp", (void *)jit_float64_exp},
+       {"jit_float64_floor", (void *)jit_float64_floor},
+       {"jit_float64_ge", (void *)jit_float64_ge},
+       {"jit_float64_gt", (void *)jit_float64_gt},
+       {"jit_float64_ieee_rem", (void *)jit_float64_ieee_rem},
+       {"jit_float64_is_finite", (void *)jit_float64_is_finite},
+       {"jit_float64_is_inf", (void *)jit_float64_is_inf},
+       {"jit_float64_is_nan", (void *)jit_float64_is_nan},
+       {"jit_float64_le", (void *)jit_float64_le},
+       {"jit_float64_log", (void *)jit_float64_log},
+       {"jit_float64_log10", (void *)jit_float64_log10},
+       {"jit_float64_lt", (void *)jit_float64_lt},
+       {"jit_float64_max", (void *)jit_float64_max},
+       {"jit_float64_min", (void *)jit_float64_min},
+       {"jit_float64_mul", (void *)jit_float64_mul},
+       {"jit_float64_ne", (void *)jit_float64_ne},
+       {"jit_float64_neg", (void *)jit_float64_neg},
+       {"jit_float64_pow", (void *)jit_float64_pow},
+       {"jit_float64_rem", (void *)jit_float64_rem},
+       {"jit_float64_rint", (void *)jit_float64_rint},
+       {"jit_float64_round", (void *)jit_float64_round},
+       {"jit_float64_sign", (void *)jit_float64_sign},
+       {"jit_float64_sin", (void *)jit_float64_sin},
+       {"jit_float64_sinh", (void *)jit_float64_sinh},
+       {"jit_float64_sqrt", (void *)jit_float64_sqrt},
+       {"jit_float64_sub", (void *)jit_float64_sub},
+       {"jit_float64_tan", (void *)jit_float64_tan},
+       {"jit_float64_tanh", (void *)jit_float64_tanh},
+       {"jit_float64_to_nfloat", (void *)jit_float64_to_nfloat},
+       {"jit_int_abs", (void *)jit_int_abs},
+       {"jit_int_add", (void *)jit_int_add},
+       {"jit_int_add_ovf", (void *)jit_int_add_ovf},
+       {"jit_int_and", (void *)jit_int_and},
+       {"jit_int_cmp", (void *)jit_int_cmp},
+       {"jit_int_div", (void *)jit_int_div},
+       {"jit_int_eq", (void *)jit_int_eq},
+       {"jit_int_ge", (void *)jit_int_ge},
+       {"jit_int_gt", (void *)jit_int_gt},
+       {"jit_int_le", (void *)jit_int_le},
+       {"jit_int_lt", (void *)jit_int_lt},
+       {"jit_int_max", (void *)jit_int_max},
+       {"jit_int_min", (void *)jit_int_min},
+       {"jit_int_mul", (void *)jit_int_mul},
+       {"jit_int_mul_ovf", (void *)jit_int_mul_ovf},
+       {"jit_int_ne", (void *)jit_int_ne},
+       {"jit_int_neg", (void *)jit_int_neg},
+       {"jit_int_not", (void *)jit_int_not},
+       {"jit_int_or", (void *)jit_int_or},
+       {"jit_int_rem", (void *)jit_int_rem},
+       {"jit_int_shl", (void *)jit_int_shl},
+       {"jit_int_shr", (void *)jit_int_shr},
+       {"jit_int_sign", (void *)jit_int_sign},
+       {"jit_int_sub", (void *)jit_int_sub},
+       {"jit_int_sub_ovf", (void *)jit_int_sub_ovf},
+       {"jit_int_to_int", (void *)jit_int_to_int},
+       {"jit_int_to_int_ovf", (void *)jit_int_to_int_ovf},
+       {"jit_int_to_long", (void *)jit_int_to_long},
+       {"jit_int_to_long_ovf", (void *)jit_int_to_long_ovf},
+       {"jit_int_to_nfloat", (void *)jit_int_to_nfloat},
+       {"jit_int_to_sbyte", (void *)jit_int_to_sbyte},
+       {"jit_int_to_sbyte_ovf", (void *)jit_int_to_sbyte_ovf},
+       {"jit_int_to_short", (void *)jit_int_to_short},
+       {"jit_int_to_short_ovf", (void *)jit_int_to_short_ovf},
+       {"jit_int_to_ubyte", (void *)jit_int_to_ubyte},
+       {"jit_int_to_ubyte_ovf", (void *)jit_int_to_ubyte_ovf},
+       {"jit_int_to_uint", (void *)jit_int_to_uint},
+       {"jit_int_to_uint_ovf", (void *)jit_int_to_uint_ovf},
+       {"jit_int_to_ulong", (void *)jit_int_to_ulong},
+       {"jit_int_to_ulong_ovf", (void *)jit_int_to_ulong_ovf},
+       {"jit_int_to_ushort", (void *)jit_int_to_ushort},
+       {"jit_int_to_ushort_ovf", (void *)jit_int_to_ushort_ovf},
+       {"jit_int_xor", (void *)jit_int_xor},
+       {"jit_long_abs", (void *)jit_long_abs},
+       {"jit_long_add", (void *)jit_long_add},
+       {"jit_long_add_ovf", (void *)jit_long_add_ovf},
+       {"jit_long_and", (void *)jit_long_and},
+       {"jit_long_cmp", (void *)jit_long_cmp},
+       {"jit_long_div", (void *)jit_long_div},
+       {"jit_long_eq", (void *)jit_long_eq},
+       {"jit_long_ge", (void *)jit_long_ge},
+       {"jit_long_gt", (void *)jit_long_gt},
+       {"jit_long_le", (void *)jit_long_le},
+       {"jit_long_lt", (void *)jit_long_lt},
+       {"jit_long_max", (void *)jit_long_max},
+       {"jit_long_min", (void *)jit_long_min},
+       {"jit_long_mul", (void *)jit_long_mul},
+       {"jit_long_mul_ovf", (void *)jit_long_mul_ovf},
+       {"jit_long_ne", (void *)jit_long_ne},
+       {"jit_long_neg", (void *)jit_long_neg},
+       {"jit_long_not", (void *)jit_long_not},
+       {"jit_long_or", (void *)jit_long_or},
+       {"jit_long_rem", (void *)jit_long_rem},
+       {"jit_long_shl", (void *)jit_long_shl},
+       {"jit_long_shr", (void *)jit_long_shr},
+       {"jit_long_sign", (void *)jit_long_sign},
+       {"jit_long_sub", (void *)jit_long_sub},
+       {"jit_long_sub_ovf", (void *)jit_long_sub_ovf},
+       {"jit_long_to_int", (void *)jit_long_to_int},
+       {"jit_long_to_int_ovf", (void *)jit_long_to_int_ovf},
+       {"jit_long_to_long", (void *)jit_long_to_long},
+       {"jit_long_to_long_ovf", (void *)jit_long_to_long_ovf},
+       {"jit_long_to_nfloat", (void *)jit_long_to_nfloat},
+       {"jit_long_to_uint", (void *)jit_long_to_uint},
+       {"jit_long_to_uint_ovf", (void *)jit_long_to_uint_ovf},
+       {"jit_long_to_ulong", (void *)jit_long_to_ulong},
+       {"jit_long_to_ulong_ovf", (void *)jit_long_to_ulong_ovf},
+       {"jit_long_xor", (void *)jit_long_xor},
+       {"jit_nfloat_abs", (void *)jit_nfloat_abs},
+       {"jit_nfloat_acos", (void *)jit_nfloat_acos},
+       {"jit_nfloat_add", (void *)jit_nfloat_add},
+       {"jit_nfloat_asin", (void *)jit_nfloat_asin},
+       {"jit_nfloat_atan", (void *)jit_nfloat_atan},
+       {"jit_nfloat_atan2", (void *)jit_nfloat_atan2},
+       {"jit_nfloat_ceil", (void *)jit_nfloat_ceil},
+       {"jit_nfloat_cmpg", (void *)jit_nfloat_cmpg},
+       {"jit_nfloat_cmpl", (void *)jit_nfloat_cmpl},
+       {"jit_nfloat_cos", (void *)jit_nfloat_cos},
+       {"jit_nfloat_cosh", (void *)jit_nfloat_cosh},
+       {"jit_nfloat_div", (void *)jit_nfloat_div},
+       {"jit_nfloat_eq", (void *)jit_nfloat_eq},
+       {"jit_nfloat_exp", (void *)jit_nfloat_exp},
+       {"jit_nfloat_floor", (void *)jit_nfloat_floor},
+       {"jit_nfloat_ge", (void *)jit_nfloat_ge},
+       {"jit_nfloat_gt", (void *)jit_nfloat_gt},
+       {"jit_nfloat_ieee_rem", (void *)jit_nfloat_ieee_rem},
+       {"jit_nfloat_is_finite", (void *)jit_nfloat_is_finite},
+       {"jit_nfloat_is_inf", (void *)jit_nfloat_is_inf},
+       {"jit_nfloat_is_nan", (void *)jit_nfloat_is_nan},
+       {"jit_nfloat_le", (void *)jit_nfloat_le},
+       {"jit_nfloat_log", (void *)jit_nfloat_log},
+       {"jit_nfloat_log10", (void *)jit_nfloat_log10},
+       {"jit_nfloat_lt", (void *)jit_nfloat_lt},
+       {"jit_nfloat_max", (void *)jit_nfloat_max},
+       {"jit_nfloat_min", (void *)jit_nfloat_min},
+       {"jit_nfloat_mul", (void *)jit_nfloat_mul},
+       {"jit_nfloat_ne", (void *)jit_nfloat_ne},
+       {"jit_nfloat_neg", (void *)jit_nfloat_neg},
+       {"jit_nfloat_pow", (void *)jit_nfloat_pow},
+       {"jit_nfloat_rem", (void *)jit_nfloat_rem},
+       {"jit_nfloat_rint", (void *)jit_nfloat_rint},
+       {"jit_nfloat_round", (void *)jit_nfloat_round},
+       {"jit_nfloat_sign", (void *)jit_nfloat_sign},
+       {"jit_nfloat_sin", (void *)jit_nfloat_sin},
+       {"jit_nfloat_sinh", (void *)jit_nfloat_sinh},
+       {"jit_nfloat_sqrt", (void *)jit_nfloat_sqrt},
+       {"jit_nfloat_sub", (void *)jit_nfloat_sub},
+       {"jit_nfloat_tan", (void *)jit_nfloat_tan},
+       {"jit_nfloat_tanh", (void *)jit_nfloat_tanh},
+       {"jit_nfloat_to_float32", (void *)jit_nfloat_to_float32},
+       {"jit_nfloat_to_float64", (void *)jit_nfloat_to_float64},
+       {"jit_nfloat_to_int", (void *)jit_nfloat_to_int},
+       {"jit_nfloat_to_int_ovf", (void *)jit_nfloat_to_int_ovf},
+       {"jit_nfloat_to_long", (void *)jit_nfloat_to_long},
+       {"jit_nfloat_to_long_ovf", (void *)jit_nfloat_to_long_ovf},
+       {"jit_nfloat_to_uint", (void *)jit_nfloat_to_uint},
+       {"jit_nfloat_to_uint_ovf", (void *)jit_nfloat_to_uint_ovf},
+       {"jit_nfloat_to_ulong", (void *)jit_nfloat_to_ulong},
+       {"jit_nfloat_to_ulong_ovf", (void *)jit_nfloat_to_ulong_ovf},
+       {"jit_uint_add", (void *)jit_uint_add},
+       {"jit_uint_add_ovf", (void *)jit_uint_add_ovf},
+       {"jit_uint_and", (void *)jit_uint_and},
+       {"jit_uint_cmp", (void *)jit_uint_cmp},
+       {"jit_uint_div", (void *)jit_uint_div},
+       {"jit_uint_eq", (void *)jit_uint_eq},
+       {"jit_uint_ge", (void *)jit_uint_ge},
+       {"jit_uint_gt", (void *)jit_uint_gt},
+       {"jit_uint_le", (void *)jit_uint_le},
+       {"jit_uint_lt", (void *)jit_uint_lt},
+       {"jit_uint_max", (void *)jit_uint_max},
+       {"jit_uint_min", (void *)jit_uint_min},
+       {"jit_uint_mul", (void *)jit_uint_mul},
+       {"jit_uint_mul_ovf", (void *)jit_uint_mul_ovf},
+       {"jit_uint_ne", (void *)jit_uint_ne},
+       {"jit_uint_neg", (void *)jit_uint_neg},
+       {"jit_uint_not", (void *)jit_uint_not},
+       {"jit_uint_or", (void *)jit_uint_or},
+       {"jit_uint_rem", (void *)jit_uint_rem},
+       {"jit_uint_shl", (void *)jit_uint_shl},
+       {"jit_uint_shr", (void *)jit_uint_shr},
+       {"jit_uint_sub", (void *)jit_uint_sub},
+       {"jit_uint_sub_ovf", (void *)jit_uint_sub_ovf},
+       {"jit_uint_to_int", (void *)jit_uint_to_int},
+       {"jit_uint_to_int_ovf", (void *)jit_uint_to_int_ovf},
+       {"jit_uint_to_long", (void *)jit_uint_to_long},
+       {"jit_uint_to_long_ovf", (void *)jit_uint_to_long_ovf},
+       {"jit_uint_to_nfloat", (void *)jit_uint_to_nfloat},
+       {"jit_uint_to_uint", (void *)jit_uint_to_uint},
+       {"jit_uint_to_uint_ovf", (void *)jit_uint_to_uint_ovf},
+       {"jit_uint_to_ulong", (void *)jit_uint_to_ulong},
+       {"jit_uint_to_ulong_ovf", (void *)jit_uint_to_ulong_ovf},
+       {"jit_uint_xor", (void *)jit_uint_xor},
+       {"jit_ulong_add", (void *)jit_ulong_add},
+       {"jit_ulong_add_ovf", (void *)jit_ulong_add_ovf},
+       {"jit_ulong_and", (void *)jit_ulong_and},
+       {"jit_ulong_cmp", (void *)jit_ulong_cmp},
+       {"jit_ulong_div", (void *)jit_ulong_div},
+       {"jit_ulong_eq", (void *)jit_ulong_eq},
+       {"jit_ulong_ge", (void *)jit_ulong_ge},
+       {"jit_ulong_gt", (void *)jit_ulong_gt},
+       {"jit_ulong_le", (void *)jit_ulong_le},
+       {"jit_ulong_lt", (void *)jit_ulong_lt},
+       {"jit_ulong_max", (void *)jit_ulong_max},
+       {"jit_ulong_min", (void *)jit_ulong_min},
+       {"jit_ulong_mul", (void *)jit_ulong_mul},
+       {"jit_ulong_mul_ovf", (void *)jit_ulong_mul_ovf},
+       {"jit_ulong_ne", (void *)jit_ulong_ne},
+       {"jit_ulong_neg", (void *)jit_ulong_neg},
+       {"jit_ulong_not", (void *)jit_ulong_not},
+       {"jit_ulong_or", (void *)jit_ulong_or},
+       {"jit_ulong_rem", (void *)jit_ulong_rem},
+       {"jit_ulong_shl", (void *)jit_ulong_shl},
+       {"jit_ulong_shr", (void *)jit_ulong_shr},
+       {"jit_ulong_sub", (void *)jit_ulong_sub},
+       {"jit_ulong_sub_ovf", (void *)jit_ulong_sub_ovf},
+       {"jit_ulong_to_int", (void *)jit_ulong_to_int},
+       {"jit_ulong_to_int_ovf", (void *)jit_ulong_to_int_ovf},
+       {"jit_ulong_to_long", (void *)jit_ulong_to_long},
+       {"jit_ulong_to_long_ovf", (void *)jit_ulong_to_long_ovf},
+       {"jit_ulong_to_nfloat", (void *)jit_ulong_to_nfloat},
+       {"jit_ulong_to_uint", (void *)jit_ulong_to_uint},
+       {"jit_ulong_to_uint_ovf", (void *)jit_ulong_to_uint_ovf},
+       {"jit_ulong_to_ulong", (void *)jit_ulong_to_ulong},
+       {"jit_ulong_to_ulong_ovf", (void *)jit_ulong_to_ulong_ovf},
+       {"jit_ulong_xor", (void *)jit_ulong_xor},
+};
+int const _jit_num_internal_symbols =
+       (sizeof(_jit_internal_symbols) / sizeof(jit_internalsym));