From 73911575dd67eaa09837fe0f691655553c3dea69 Mon Sep 17 00:00:00 2001 From: phcoder Date: Sun, 2 Jan 2011 14:58:57 +0100 Subject: [PATCH] support for registering functions from modules (not tested yet) --- grub-core/kern/dl.c | 20 +++++++++++++++++--- grub-core/kern/emu/full.c | 8 ++++++++ grub-core/kern/ia64/dl.c | 30 ++++++++++++++++++++---------- include/grub/dl.h | 9 +++++++++ 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 2f2493fca..9dfff5287 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -360,9 +360,22 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) 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)) - return grub_errno; - + { +#ifdef __ia64__ + /* FIXME: free descriptor once it's not used anymore. */ + char **desc; + desc = grub_malloc (2 * sizeof (char *)); + if (!desc) + return grub_errno; + desc[0] = (void *) sym->st_value; + desc[1] = mod->gp; + if (grub_dl_register_symbol (name, (void *) desc, mod)) + return grub_errno; +#else + if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) + return grub_errno; +#endif + } if (grub_strcmp (name, "grub_mod_init") == 0) mod->init = sym->st_value; else if (grub_strcmp (name, "grub_mod_fini") == 0) @@ -552,6 +565,7 @@ grub_dl_load_core (void *addr, grub_size_t size) if (grub_dl_resolve_name (mod, e) || grub_dl_resolve_dependencies (mod, e) || grub_dl_load_segments (mod, e) + || grub_arch_dl_allocate_gp (mod, e) || grub_dl_resolve_symbols (mod, e) || grub_arch_dl_relocate_symbols (mod, e)) { diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index 0396d0ab4..67a125301 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -56,4 +56,12 @@ grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), { return ~(grub_size_t)0; } + +grub_err_t +grub_arch_dl_allocate_gp (grub_dl_t mod __attribute__ ((unused)), + const void *ehdr __attribute__ ((unused))) +{ + return GRUB_ERR_BAD_MODULE; +} + #endif diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 24fa01b90..1fbe185b4 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -154,16 +154,13 @@ grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec) return cnt * sizeof (struct ia64_trampoline); } -/* Relocate symbols. */ grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr) { - Elf_Ehdr *e = ehdr; - Elf_Shdr *s; - Elf_Word entsize; - unsigned i; - grub_uint64_t *gp, *gpptr; grub_size_t gp_size = 0; + const Elf_Ehdr *e = ehdr; + const Elf_Shdr *s; + unsigned i; for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); i < e->e_shnum; @@ -199,10 +196,23 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) if (gp_size > MASK19) return grub_error (GRUB_ERR_OUT_OF_RANGE, "gp too big"); - gpptr = gp = grub_malloc (gp_size); - if (!gp) + mod->gp = grub_malloc (gp_size); + if (!mod->gp) return grub_errno; - mod->gp = (char *) gp; + return GRUB_ERR_NONE; +} + +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + grub_uint64_t *gp, *gpptr; + + gp = gpptr = (grub_uint64_t *) mod->gp; /* Find a symbol table. */ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); diff --git a/include/grub/dl.h b/include/grub/dl.h index e04285280..c43c30ca7 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -124,6 +124,8 @@ void grub_arch_dl_init_linker (void); #ifdef __ia64__ grub_size_t grub_arch_dl_get_tramp_size (const void *ehdr, unsigned sec); +grub_err_t grub_arch_dl_allocate_gp (grub_dl_t mod, const void *ehdr); + #define GRUB_ARCH_DL_TRAMP_ALIGN 16 #else static inline grub_size_t @@ -131,6 +133,13 @@ grub_arch_dl_get_tramp_size (const void *ehdr __attribute__ ((unused)), int sec { return 0; } +static inline grub_err_t +grub_arch_dl_allocate_gp (grub_dl_t mod __attribute__ ((unused)), + const void *ehdr __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} + #define GRUB_ARCH_DL_TRAMP_ALIGN 1 #endif