On Wed, Jun 24, 2009 at 03:00:32AM +0200, Robert Millan wrote:
> A possible solution to this could be to make grub_dl_load_core() create a
> copy of the module and work on the copy.  This could even be ifdef'ed,
> but I doubt the performance hit would be significant.

I found a better approach;  instead of copiing the whole module, we just
need to copy the symbol tab.  A small adjustment to each of the functions
that will access it (grub_dl_resolve_symbols and
grub_arch_dl_relocate_symbols) will make them use the copy instead of
the original.

Patch attached.

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."
2009-06-25  Robert Millan  <rmh.g...@aybabtu.com>

	* kern/dl.c (Elf_Word, Elf_Addr, Elf_Ehdr, Elf_Shdr, Elf_Sym): Remove
	typedefs.
	(ELF_ST_BIND, ELF_ST_TYPE): Remove macros.

	* include/grub/elf.h (Elf_Word, Elf_Addr, Elf_Ehdr, Elf_Shdr)
	(Elf_Sym, ELF_ST_BIND, ELF_ST_TYPE): New macros.

	* efiemu/loadcore64.c: Include `<grub/elf.h>'.
	(Elf_Word, Elf_Ehdr, Elf_Shdr, Elf_Sym, ELF_ST_BIND)
	(ELF_ST_TYPE): Undefine macros for native word length
	so that they can be redefined afterwards.
	* efiemu/loadcore32.c: Likewise.


	* include/grub/dl.h: Include `<grub/elf.h>'.
	(struct grub_dl): Add `symtab' member.

	* kern/dl.c (grub_dl_resolve_symbols): Copy symbol table to
	`mod->symtab', and use the copied structure for further writes
	rather than the original.

	* kern/powerpc/dl.c (grub_arch_dl_relocate_symbols): Initialize
	`symtab' using `mod->symtab'.
	* kern/sparc64/dl.c: Likewise.
	* kern/i386/dl.c: Likewise.
	* kern/x86_64/dl.c: Likewise.

Index: kern/powerpc/dl.c
===================================================================
--- kern/powerpc/dl.c	(revision 2358)
+++ kern/powerpc/dl.c	(working copy)
@@ -58,7 +58,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t
   if (i == e->e_shnum)
     return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
 
-  symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
+  symtab = mod->symtab;
   entsize = s->sh_entsize;
 
   for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
Index: kern/dl.c
===================================================================
--- kern/dl.c	(revision 2358)
+++ kern/dl.c	(working copy)
@@ -29,30 +29,6 @@
 #include <grub/env.h>
 #include <grub/cache.h>
 
-#if GRUB_CPU_SIZEOF_VOID_P == 4
-
-typedef Elf32_Word Elf_Word;
-typedef Elf32_Addr Elf_Addr;
-typedef Elf32_Ehdr Elf_Ehdr;
-typedef Elf32_Shdr Elf_Shdr;
-typedef Elf32_Sym Elf_Sym;
-
-# define ELF_ST_BIND(val)	ELF32_ST_BIND (val)
-# define ELF_ST_TYPE(val)	ELF32_ST_TYPE (val)
-
-#elif GRUB_CPU_SIZEOF_VOID_P == 8
-
-typedef Elf64_Word Elf_Word;
-typedef Elf64_Addr Elf_Addr;
-typedef Elf64_Ehdr Elf_Ehdr;
-typedef Elf64_Shdr Elf_Shdr;
-typedef Elf64_Sym Elf_Sym;
-
-# define ELF_ST_BIND(val)	ELF64_ST_BIND (val)
-# define ELF_ST_TYPE(val)	ELF64_ST_TYPE (val)
-
-#endif
-
 
 
 struct grub_dl_list
@@ -333,9 +309,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, 
   if (i == e->e_shnum)
     return grub_error (GRUB_ERR_BAD_MODULE, "no symbol table");
 
-  sym = (Elf_Sym *) ((char *) e + s->sh_offset);
   size = s->sh_size;
   entsize = s->sh_entsize;
+  mod->symtab = grub_malloc (size);
+  memcpy (mod->symtab, (char *) e + s->sh_offset, size);
+  sym = mod->symtab;
 
   s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shentsize * s->sh_link);
   str = (char *) e + s->sh_offset;
@@ -695,6 +673,7 @@ grub_dl_unload (grub_dl_t mod)
     }
 
   grub_free (mod->name);
+  grub_free (mod->symtab);
   grub_free (mod);
   return 1;
 }
Index: kern/sparc64/dl.c
===================================================================
--- kern/sparc64/dl.c	(revision 2358)
+++ kern/sparc64/dl.c	(working copy)
@@ -58,7 +58,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t
   if (i == e->e_shnum)
     return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
 
-  symtab = (Elf64_Sym *) ((char *) e + s->sh_offset);
+  symtab = mod->symtab;
   entsize = s->sh_entsize;
 
   for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
Index: kern/i386/dl.c
===================================================================
--- kern/i386/dl.c	(revision 2358)
+++ kern/i386/dl.c	(working copy)
@@ -57,7 +57,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t
   if (i == e->e_shnum)
     return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
 
-  symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
+  symtab = mod->symtab;
   entsize = s->sh_entsize;
 
   for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
Index: kern/x86_64/dl.c
===================================================================
--- kern/x86_64/dl.c	(revision 2358)
+++ kern/x86_64/dl.c	(working copy)
@@ -57,7 +57,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t
   if (i == e->e_shnum)
     return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
 
-  symtab = (Elf64_Sym *) ((char *) e + s->sh_offset);
+  symtab = mod->symtab;
   entsize = s->sh_entsize;
 
   for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
Index: efiemu/loadcore64.c
===================================================================
--- efiemu/loadcore64.c	(revision 2358)
+++ efiemu/loadcore64.c	(working copy)
@@ -18,6 +18,15 @@
  */
 
 #define SUFFIX(x) x ## 64
+
+#include <grub/elf.h>
+#undef Elf_Ehdr
+#undef Elf_Shdr
+#undef Elf_Sym
+#undef Elf_Word
+#undef ELF_ST_TYPE
+#undef ELF_ST_BIND
+
 #define Elf_Ehdr Elf64_Ehdr
 #define Elf_Shdr Elf64_Shdr
 #define Elf_Sym Elf64_Sym
Index: efiemu/loadcore32.c
===================================================================
--- efiemu/loadcore32.c	(revision 2358)
+++ efiemu/loadcore32.c	(working copy)
@@ -18,10 +18,20 @@
  */
 
 #define SUFFIX(x) x ## 32
+
+#include <grub/elf.h>
+#undef Elf_Ehdr
+#undef Elf_Shdr
+#undef Elf_Sym
+#undef Elf_Word
+#undef ELF_ST_TYPE
+#undef ELF_ST_BIND
+
 #define Elf_Ehdr Elf32_Ehdr
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Sym Elf32_Sym
 #define Elf_Word Elf32_Word
 #define ELF_ST_TYPE ELF32_ST_TYPE
 #define ELF_ST_BIND ELF32_ST_BIND
+
 #include "loadcore.c"
Index: include/grub/elf.h
===================================================================
--- include/grub/elf.h	(revision 2358)
+++ include/grub/elf.h	(working copy)
@@ -2330,4 +2330,28 @@ typedef Elf32_Addr Elf32_Conflict;
 
 #define R_X86_64_NUM		24
 
+#if GRUB_CPU_SIZEOF_VOID_P == 4
+
+#define Elf_Word Elf32_Word
+#define Elf_Addr Elf32_Addr
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+
+# define ELF_ST_BIND(val)	ELF32_ST_BIND (val)
+# define ELF_ST_TYPE(val)	ELF32_ST_TYPE (val)
+
+#elif GRUB_CPU_SIZEOF_VOID_P == 8
+
+#define Elf_Word Elf64_Word
+#define Elf_Addr Elf64_Addr
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+
+# define ELF_ST_BIND(val)	ELF64_ST_BIND (val)
+# define ELF_ST_TYPE(val)	ELF64_ST_TYPE (val)
+
+#endif
+
 #endif /* ! GRUB_ELF_H */
Index: include/grub/dl.h
===================================================================
--- include/grub/dl.h	(revision 2358)
+++ include/grub/dl.h	(working copy)
@@ -23,6 +23,7 @@
 #include <grub/symbol.h>
 #include <grub/err.h>
 #include <grub/types.h>
+#include <grub/elf.h>
 
 #define GRUB_MOD_INIT(name)	\
 static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
@@ -78,6 +79,7 @@ struct grub_dl
   int ref_count;
   grub_dl_dep_t dep;
   grub_dl_segment_t segment;
+  Elf_Sym *symtab;
   void (*init) (struct grub_dl *mod);
   void (*fini) (void);
 };
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to