From 7b58e65f2423311b2224cf54d347a0c33eac09bc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 8 May 2011 18:29:37 +0200 Subject: [PATCH] track function symbols --- grub-core/gensymlist.sh | 10 +++++----- grub-core/kern/dl.c | 22 +++++++++++++--------- include/grub/dl.h | 2 +- include/grub/elf.h | 3 +++ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/grub-core/gensymlist.sh b/grub-core/gensymlist.sh index 0ab56e9cb..5f402ea87 100644 --- a/grub-core/gensymlist.sh +++ b/grub-core/gensymlist.sh @@ -47,7 +47,7 @@ grub_register_exported_symbols (void) EOF cat < 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 diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index aa15cfa24..6353b0d59 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -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; diff --git a/include/grub/dl.h b/include/grub/dl.h index 6646902d4..319ed5745 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -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); diff --git a/include/grub/elf.h b/include/grub/elf.h index b9401f241..a02b90238 100644 --- a/include/grub/elf.h +++ b/include/grub/elf.h @@ -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)