]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
track function symbols
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 8 May 2011 16:29:37 +0000 (18:29 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sun, 8 May 2011 16:29:37 +0000 (18:29 +0200)
grub-core/gensymlist.sh
grub-core/kern/dl.c
include/grub/dl.h
include/grub/elf.h

index 0ab56e9cb361a1b69eae485976e1f68f98b44d7b..5f402ea8753bf8bc440124db30f7bd7c4e5ba08d 100644 (file)
@@ -47,7 +47,7 @@ grub_register_exported_symbols (void)
 EOF
 
 cat <<EOF
-  struct symtab { const char *name; void *addr; };
+  struct symtab { const char *name; void *addr; int isfunc; };
   struct symtab *p;
   static struct symtab tab[] =
     {
@@ -56,16 +56,16 @@ EOF
 (while read LINE; do echo $LINE; done) \
   | grep -v '^#' \
   | sed -n \
-        -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/      {"\1", \1},/;p;}' \
-        -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/      {"\1", \&\1},/;p;}' \
+        -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/      {"\1", \1, 1},/;p;}' \
+        -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/      {"\1", \&\1, 0},/;p;}' \
   | sort -u
 
 cat <<EOF
-      {0, 0}
+      {0, 0, 0}
     };
 
   COMPILE_TIME_ASSERT (sizeof (tab) > sizeof (tab[0]));
   for (p = tab; p->name; p++)
-    grub_dl_register_symbol (p->name, p->addr, 0);
+    grub_dl_register_symbol (p->name, p->addr, p->isfunc, 0);
 }
 EOF
index aa15cfa24744d6cbeb92dc57f7ebee64e2c27a59..6353b0d59f6eef9fddce0235777cb8a8d0961237 100644 (file)
@@ -90,6 +90,7 @@ struct grub_symbol
   struct grub_symbol *next;
   const char *name;
   void *addr;
+  int isfunc;
   grub_dl_t mod;       /* The module to which this symbol belongs.  */
 };
 typedef struct grub_symbol *grub_symbol_t;
@@ -114,21 +115,22 @@ grub_symbol_hash (const char *s)
 
 /* Resolve the symbol name NAME and return the address.
    Return NULL, if not found.  */
-static void *
+static grub_symbol_t
 grub_dl_resolve_symbol (const char *name)
 {
   grub_symbol_t sym;
 
   for (sym = grub_symtab[grub_symbol_hash (name)]; sym; sym = sym->next)
     if (grub_strcmp (sym->name, name) == 0)
-      return sym->addr;
+      return sym;
 
   return 0;
 }
 
 /* Register a symbol with the name NAME and the address ADDR.  */
 grub_err_t
-grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
+grub_dl_register_symbol (const char *name, void *addr, int isfunc,
+                        grub_dl_t mod)
 {
   grub_symbol_t sym;
   unsigned k;
@@ -151,6 +153,7 @@ grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod)
 
   sym->addr = addr;
   sym->mod = mod;
+  sym->isfunc = isfunc;
 
   k = grub_symbol_hash (name);
   sym->next = grub_symtab[k];
@@ -371,17 +374,20 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
          /* Resolve a global symbol.  */
          if (sym->st_name != 0 && sym->st_shndx == 0)
            {
-             sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name);
-             if (! sym->st_value)
+             grub_symbol_t nsym = grub_dl_resolve_symbol (name);
+             if (! nsym)
                return grub_error (GRUB_ERR_BAD_MODULE,
                                   "symbol not found: `%s'", name);
+             sym->st_value = (Elf_Addr) nsym->addr;
+             if (nsym->isfunc)
+               sym->st_info = ELF_ST_INFO (bind, STT_FUNC);
            }
          else
            {
              sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
                                                                    sym->st_shndx);
              if (bind != STB_LOCAL)
-               if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
+               if (grub_dl_register_symbol (name, (void *) sym->st_value, 0, mod))
                  return grub_errno;
            }
          break;
@@ -398,13 +404,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
                return grub_errno;
              desc[0] = (void *) sym->st_value;
              desc[1] = mod->base;
-             if (grub_dl_register_symbol (name, (void *) desc, mod))
-               return grub_errno;
              sym->st_value = (grub_addr_t) desc;
          }
 #endif
          if (bind != STB_LOCAL)
-           if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
+           if (grub_dl_register_symbol (name, (void *) sym->st_value, 1, mod))
              return grub_errno;
          if (grub_strcmp (name, "grub_mod_init") == 0)
            mod->init = (void (*) (grub_dl_t)) sym->st_value;
index 6646902d4d8cd3db03e7b5c27437f2543a26cef8..319ed5745cc93ed1937536707892a2c465035c10 100644 (file)
@@ -116,7 +116,7 @@ extern grub_dl_t EXPORT_VAR(grub_dl_head);
 
 grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name);
 grub_err_t grub_dl_register_symbol (const char *name, void *addr,
-                                   grub_dl_t mod);
+                                   int isfunc, grub_dl_t mod);
 
 grub_err_t grub_arch_dl_check_header (void *ehdr);
 grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr);
index b9401f241468871dc05dc5440675d4191e5b23c3..a02b902389113bde8bbcfbf1e6a514f78e7caa8b 100644 (file)
@@ -2348,6 +2348,8 @@ typedef Elf32_Xword Elf_Xword;
 
 #define ELF_ST_BIND(val)       ELF32_ST_BIND(val)
 #define ELF_ST_TYPE(val)       ELF32_ST_TYPE(val)
+#define ELF_ST_INFO(a,b)       ELF32_ST_INFO(a,b)
+
 #define ELF_R_SYM(val)         ELF32_R_SYM(val)
 #define ELF_R_TYPE(val)                ELF32_R_TYPE(val)
 #define ELF_R_INFO(sym, type)  ELF32_R_INFO(sym, type)
@@ -2369,6 +2371,7 @@ typedef Elf64_Xword Elf_Xword;
 
 #define ELF_ST_BIND(val)       ELF64_ST_BIND (val)
 #define ELF_ST_TYPE(val)       ELF64_ST_TYPE (val)
+#define ELF_ST_INFO(a,b)       ELF64_ST_INFO(a,b)
 #define ELF_R_SYM(val)         ELF64_R_SYM(val)
 #define ELF_R_TYPE(val)                ELF64_R_TYPE(val)
 #define ELF_R_INFO(sym, type)  ELF64_R_INFO(sym, type)