Add support for converting PE+ to Elf64.
authorVladimir Serbinenko <phcoder@gmail.com>
Mon, 16 Dec 2013 14:30:50 +0000 (15:30 +0100)
committerVladimir Serbinenko <phcoder@gmail.com>
Mon, 16 Dec 2013 14:30:50 +0000 (15:30 +0100)
ChangeLog
configure.ac
grub-core/Makefile.am
util/grub-pe2elf.c

index cfab3f1..2bf4ef1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-12-16  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Add support for converting PE+ to Elf64.
+
 2013-12-16  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/commands/minicmd.c (grub_mini_cmd_dump): Handle LLP case.
index 59bd873..be08d55 100644 (file)
@@ -699,7 +699,7 @@ AC_ARG_ENABLE([efiemu],
 if test x"$enable_efiemu" = xno ; then
   efiemu_excuse="explicitly disabled"
 fi
-if test x"$grub_cv_target_cc_link_format" = x-mi386pe ; then
+if test x"$grub_cv_target_cc_link_format" = x-mi386pe || test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then
   efiemu_excuse="not available on cygwin"
 fi
 if test x"$target_cpu" != xi386 ; then
@@ -759,8 +759,11 @@ CFLAGS="$TARGET_CFLAGS"
 if test x"$target_cpu" = xi386 || test x"$target_cpu" = xx86_64; then
   AC_CACHE_CHECK([for target linking format], [grub_cv_target_cc_link_format], [
     grub_cv_target_cc_link_format=unknown
-    for format in -melf_${target_cpu} -melf_${target_cpu}_fbsd -melf_${target_cpu}_obsd -melf_${target_cpu}_haiku -m${target_cpu}pe -arch,${target_cpu}; do
-      if test x${target_cpu} != xi386 && test x$format = x${target_cpu}pe; then
+    for format in -melf_${target_cpu} -melf_${target_cpu}_fbsd -melf_${target_cpu}_obsd -melf_${target_cpu}_haiku -mi386pe -mi386pep -arch,${target_cpu}; do
+      if test x${target_cpu} != xi386 && test x$format = xi386pe; then
+        continue
+      fi
+      if test x${target_cpu} != xx86_64 && test x$format = xi386pep; then
         continue
       fi
       CFLAGS="$TARGET_CFLAGS"
@@ -781,9 +784,12 @@ if test x"$target_cpu" = xi386 || test x"$target_cpu" = xx86_64; then
     AC_MSG_ERROR([no suitable link format found])
   fi
   TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format"
-  if test x"$grub_cv_target_cc_link_format" = x-mi386pe; then
+  if test x"$grub_cv_target_cc_link_format" = x-mi386pe ; then
     TARGET_OBJ2ELF='./build-grub-pe2elf';
   fi
+  if test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then
+    TARGET_OBJ2ELF='./build-grub-pep2elf';
+  fi
 fi
 
 if test x$grub_cv_target_cc_link_format = x-arch,i386 || test x$grub_cv_target_cc_link_format = x-arch,x86_64; then
@@ -801,7 +807,7 @@ if test x$grub_cv_target_cc_link_format = x-arch,i386 || test x$grub_cv_target_c
    TARGET_IMG_LDFLAGS_AC='-nostdlib -static -Wl,-preload -Wl,-segalign,20'
    TARGET_IMG_BASE_LDOPT="-Wl,-image_base"
    TARGET_LDFLAGS_OLDMAGIC=""
-elif test x$grub_cv_target_cc_link_format = x-mi386pe; then
+elif test x$grub_cv_target_cc_link_format = x-mi386pe || test x$grub_cv_target_cc_link_format = x-mi386pep ; then
   TARGET_APPLE_LINKER=0
   TARGET_LDFLAGS_OLDMAGIC="-Wl,-N"
   TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/${grub_coredir}/conf/i386-cygwin-img-ld.sc"
index 5b804c7..79c63ab 100644 (file)
@@ -26,8 +26,11 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin
 CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
 CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
 
+build-grub-pep2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
+       $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
+
 build-grub-pe2elf: $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
-       $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
+       $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^
 
 # gentrigtables
 gentrigtables: gentrigtables.c
index a711af9..a48ef23 100644 (file)
  *    relocation sections
  */
 
-#define TEXT_SECTION   1
-#define RDATA_SECTION  2
-#define DATA_SECTION   3
-#define BSS_SECTION    4
-#define MODNAME_SECTION        5
-#define MODDEPS_SECTION        6
-#define MODLICENSE_SECTION     7
-#define SYMTAB_SECTION 8
-#define STRTAB_SECTION 9
-
-#define REL_SECTION    10
-
-/* 10 normal section + up to 4 relocation (.text, .rdata, .data, .symtab).  */
-#define MAX_SECTIONS    16
+#if GRUB_TARGET_WORDSIZE == 64
+typedef Elf64_Rela elf_reloc_t;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Sym Elf_Sym;
+#define ELF_R_INFO ELF64_R_INFO
+#define ELF_ST_INFO ELF64_ST_INFO
+#define GRUB_PE32_MACHINE GRUB_PE32_MACHINE_X86_64
+#else
+typedef Elf32_Rel elf_reloc_t;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Sym Elf_Sym;
+#define ELF_R_INFO ELF32_R_INFO
+#define ELF_ST_INFO ELF32_ST_INFO
+#define GRUB_PE32_MACHINE GRUB_PE32_MACHINE_I386
+#endif
 
 #define STRTAB_BLOCK   256
 
 static char *strtab;
 static int strtab_max, strtab_len;
 
-static Elf32_Ehdr ehdr;
-static Elf32_Shdr shdr[MAX_SECTIONS];
-static int num_sections;
+static Elf_Ehdr ehdr;
+static Elf_Shdr *shdr;
+static int num_sections, first_reloc_section, reloc_sections_end, symtab_section, strtab_section;
 static grub_uint32_t offset, image_base;
 
 static int
@@ -102,15 +105,20 @@ write_section_data (FILE* fp, const char *name, char *image,
 {
   int *section_map;
   int i;
+  grub_uint32_t last_category = 0;
+  grub_uint32_t idx, idx_reloc;
   char *pe_strtab = (image + pe_chdr->symtab_offset
                     + pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol));
 
-  section_map = xmalloc ((pe_chdr->num_sections + 1) * sizeof (int));
+  section_map = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (int));
   section_map[0] = 0;
+  shdr = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (shdr[0]));
+  idx = 1;
+  idx_reloc = pe_chdr->num_sections + 1;
 
   for (i = 0; i < pe_chdr->num_sections; i++, pe_shdr++)
     {
-      grub_uint32_t idx;
+      grub_uint32_t category;
       const char *shname = pe_shdr->name;
       grub_size_t secsize;
 
@@ -124,54 +132,56 @@ write_section_data (FILE* fp, const char *name, char *image,
 
       secsize = pe_shdr->raw_data_size;
 
+      shdr[idx].sh_type = SHT_PROGBITS;
+
       if (! strcmp (shname, ".text"))
         {
-          idx = TEXT_SECTION;
+          category = 0;
           shdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
         }
-      else if (! strcmp (shname, ".rdata"))
+      else if (! strncmp (shname, ".rdata", 6))
         {
-          idx = RDATA_SECTION;
+          category = 1;
           shdr[idx].sh_flags = SHF_ALLOC;
         }
       else if (! strcmp (shname, ".data"))
         {
-          idx = DATA_SECTION;
+          category = 2;
           shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
         }
       else if (! strcmp (shname, ".bss"))
         {
-          idx = BSS_SECTION;
+          category = 3;
+         shdr[idx].sh_type = SHT_NOBITS;
           shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
          if (secsize < pe_shdr->virtual_size)
            secsize = pe_shdr->virtual_size;
         }
-      else if (! strcmp (shname, ".modname"))
-        idx = MODNAME_SECTION;
-      else if (! strcmp (shname, ".moddeps"))
-        idx = MODDEPS_SECTION;
-      else if (strcmp (shname, ".module_license") == 0)
-        idx = MODLICENSE_SECTION;
+      else if (strcmp (shname, ".modname") == 0 || strcmp (shname, ".moddeps") == 0
+              || strcmp (shname, ".module_license") == 0)
+        category = 4;
       else
         {
           section_map[i + 1] = -1;
           continue;
         }
 
+      if (category < last_category)
+       grub_util_error ("out of order sections");
+
       section_map[i + 1] = idx;
 
       if (pe_shdr->virtual_size
          && pe_shdr->virtual_size < secsize)
        secsize = pe_shdr->virtual_size;
 
-      shdr[idx].sh_type = (idx == BSS_SECTION) ? SHT_NOBITS : SHT_PROGBITS;
       shdr[idx].sh_size = secsize;
       shdr[idx].sh_addralign = 1 << (((pe_shdr->characteristics >>
                                        GRUB_PE32_SCN_ALIGN_SHIFT) &
                                       GRUB_PE32_SCN_ALIGN_MASK) - 1);
       shdr[idx].sh_addr = pe_shdr->virtual_address + image_base;
 
-      if (idx != BSS_SECTION)
+      if (shdr[idx].sh_type != SHT_NOBITS)
         {
           shdr[idx].sh_offset = offset;
           grub_util_write_image_at (image + pe_shdr->raw_data_offset,
@@ -185,45 +195,55 @@ write_section_data (FILE* fp, const char *name, char *image,
         {
           char relname[5 + strlen (shname)];
 
-          if (num_sections >= MAX_SECTIONS)
-            grub_util_error ("too many sections");
-
           sprintf (relname, ".rel%s", shname);
 
-          shdr[num_sections].sh_name = insert_string (relname);
-          shdr[num_sections].sh_link = i;
-          shdr[num_sections].sh_info = idx;
+          shdr[idx_reloc].sh_name = insert_string (relname);
+          shdr[idx_reloc].sh_link = i;
+          shdr[idx_reloc].sh_info = idx;
 
-          shdr[idx].sh_name = shdr[num_sections].sh_name + 4;
+          shdr[idx].sh_name = shdr[idx_reloc].sh_name + 4;
 
-          num_sections++;
+          idx_reloc++;
         }
       else
         shdr[idx].sh_name = insert_string (shname);
+      idx++;
     }
 
+  idx_reloc -= pe_chdr->num_sections + 1;
+  num_sections = idx + idx_reloc + 2;
+  first_reloc_section = idx;
+  reloc_sections_end = idx + idx_reloc;
+  memmove (shdr + idx, shdr + pe_chdr->num_sections + 1,
+          idx_reloc * sizeof (shdr[0]));
+  memset (shdr + idx + idx_reloc, 0, 3 * sizeof (shdr[0]));
+  memset (shdr, 0, sizeof (shdr[0]));
+
+  symtab_section = idx + idx_reloc;
+  strtab_section = idx + idx_reloc + 1;
+
   return section_map;
 }
 
 static void
 write_reloc_section (FILE* fp, const char *name, char *image,
                      struct grub_pe32_coff_header *pe_chdr,
-                     struct grub_pe32_section_table *pe_shdr,
-                     Elf32_Sym *symtab,
+                     struct grub_pe32_section_table  *pe_shdr,
+                     Elf_Sym *symtab,
                      int *symtab_map)
 {
   int i;
 
-  for (i = REL_SECTION; i < num_sections; i++)
+  for (i = first_reloc_section; i < reloc_sections_end; i++)
     {
       struct grub_pe32_section_table *pe_sec;
       struct grub_pe32_reloc *pe_rel;
-      Elf32_Rel *rel;
+      elf_reloc_t *rel;
       int num_rels, j, modified;
 
       pe_sec = pe_shdr + shdr[i].sh_link;
       pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset);
-      rel = (Elf32_Rel *) xmalloc (pe_sec->num_relocations * sizeof (Elf32_Rel));
+      rel = (elf_reloc_t *) xmalloc (pe_sec->num_relocations * sizeof (elf_reloc_t));
       num_rels = 0;
       modified = 0;
 
@@ -236,43 +256,84 @@ write_reloc_section (FILE* fp, const char *name, char *image,
               (symtab_map[pe_rel->symtab_index] == -1))
             grub_util_error ("invalid symbol");
 
-          if (pe_rel->type == GRUB_PE32_REL_I386_DIR32)
-            type = R_386_32;
-          else if (pe_rel->type == GRUB_PE32_REL_I386_REL32)
-            type = R_386_PC32;
-          else
-            grub_util_error ("unknown pe relocation type %d\n", pe_rel->type);
-
           ofs = pe_rel->offset - pe_sec->virtual_address;
           addr = (grub_uint32_t *)(image + pe_sec->raw_data_offset + ofs);
-          if (type == R_386_PC32)
+
+          switch (pe_rel->type)
+           {
+#if GRUB_TARGET_WORDSIZE == 64
+           case 1:
+             type = R_X86_64_64;
+             rel[num_rels].r_addend = *(grub_int64_t *)addr;
+             *(grub_int64_t *)addr = 0;
+             modified = 1;
+             break;
+           case 4:
+             type = R_X86_64_PC32;
+             rel[num_rels].r_addend = *(grub_int32_t *)addr;
+             *addr = 0;
+             modified = 1;
+             break;
+           case 14:
+             type = R_X86_64_PC64;
+             rel[num_rels].r_addend = *(grub_uint64_t *)addr - 8;
+             *(grub_uint64_t *)addr = 0;
+             modified = 1;
+             break;
+#else
+           case GRUB_PE32_REL_I386_DIR32:
+             type = R_386_32;
+             break;
+           case GRUB_PE32_REL_I386_REL32:
+             type = R_386_PC32;
+             break;
+#endif
+           default:
+             grub_util_error ("unknown pe relocation type %d\n", pe_rel->type);
+           }
+
+          if (type ==
+#if GRUB_TARGET_WORDSIZE == 64
+             R_386_PC32
+#else
+             R_X86_64_PC32
+#endif
+
+             )
             {
               unsigned char code;
 
               code = image[pe_sec->raw_data_offset + ofs - 1];
 
+#if GRUB_TARGET_WORDSIZE == 32
               if (((code != 0xe8) && (code != 0xe9)) || (*addr))
                 grub_util_error ("invalid relocation (%x %x)", code, *addr);
+#endif
 
-              modified = 1;
-              if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx)
+              if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx
+                 && symtab[symtab_map[pe_rel->symtab_index]].st_shndx
+                 == shdr[i].sh_info)
                 {
-                  if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx
-                      != shdr[i].sh_info)
-                    grub_util_error ("cross section call is not allowed");
-
-                  *addr = (symtab[symtab_map[pe_rel->symtab_index]].st_value
-                           - ofs - 4);
+                 modified = 1;
+                  *addr += (symtab[symtab_map[pe_rel->symtab_index]].st_value
+                           - ofs - 4);
 
                   continue;
                 }
               else
-                *addr = -4;
+               {
+#if GRUB_TARGET_WORDSIZE == 64
+                 rel[num_rels].r_addend -= 4;
+#else
+                 modified = 1;
+                 *addr = -4;
+#endif
+               }
             }
 
           rel[num_rels].r_offset = ofs;
-          rel[num_rels].r_info = ELF32_R_INFO (symtab_map[pe_rel->symtab_index],
-                                               type);
+          rel[num_rels].r_info = ELF_R_INFO (symtab_map[pe_rel->symtab_index],
+                                            type);
           num_rels++;
         }
 
@@ -282,12 +343,16 @@ write_reloc_section (FILE* fp, const char *name, char *image,
                                   shdr[shdr[i].sh_info].sh_offset,
                                   fp, name);
 
+#if GRUB_TARGET_WORDSIZE == 64
+      shdr[i].sh_type = SHT_RELA;
+#else
       shdr[i].sh_type = SHT_REL;
+#endif
       shdr[i].sh_offset = offset;
-      shdr[i].sh_link = SYMTAB_SECTION;
+      shdr[i].sh_link = symtab_section;
       shdr[i].sh_addralign = 4;
-      shdr[i].sh_entsize = sizeof (Elf32_Rel);
-      shdr[i].sh_size = num_rels * sizeof (Elf32_Rel);
+      shdr[i].sh_entsize = sizeof (elf_reloc_t);
+      shdr[i].sh_size = num_rels * sizeof (elf_reloc_t);
 
       grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp, name);
       offset += shdr[i].sh_size;
@@ -303,16 +368,16 @@ write_symbol_table (FILE* fp, const char *name, char *image,
 {
   struct grub_pe32_symbol *pe_symtab;
   char *pe_strtab;
-  Elf32_Sym *symtab;
+  Elf_Sym *symtab;
   int *symtab_map, num_syms;
   int i;
 
   pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
   pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
 
-  symtab = (Elf32_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
-                                  sizeof (Elf32_Sym));
-  memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf32_Sym));
+  symtab = (Elf_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
+                               sizeof (Elf_Sym));
+  memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf_Sym));
   num_syms = 1;
 
   symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int));
@@ -362,6 +427,8 @@ write_symbol_table (FILE* fp, const char *name, char *image,
 
           if ((strcmp (symname, "_grub_mod_init")) &&
               (strcmp (symname, "_grub_mod_fini")) &&
+             (strcmp (symname, "grub_mod_init")) &&
+              (strcmp (symname, "grub_mod_fini")) &&
               (bind == STB_LOCAL))
               continue;
 
@@ -370,7 +437,7 @@ write_symbol_table (FILE* fp, const char *name, char *image,
 
       symtab[num_syms].st_shndx = section_map[pe_symtab->section];
       symtab[num_syms].st_value = pe_symtab->value;
-      symtab[num_syms].st_info = ELF32_ST_INFO (bind, type);
+      symtab[num_syms].st_info = ELF_ST_INFO (bind, type);
 
       symtab_map[i] = num_syms;
       num_syms++;
@@ -379,17 +446,17 @@ write_symbol_table (FILE* fp, const char *name, char *image,
   write_reloc_section (fp, name, image, pe_chdr, pe_shdr,
                       symtab, symtab_map);
 
-  shdr[SYMTAB_SECTION].sh_name = insert_string (".symtab");
-  shdr[SYMTAB_SECTION].sh_type = SHT_SYMTAB;
-  shdr[SYMTAB_SECTION].sh_offset = offset;
-  shdr[SYMTAB_SECTION].sh_size = num_syms * sizeof (Elf32_Sym);
-  shdr[SYMTAB_SECTION].sh_entsize = sizeof (Elf32_Sym);
-  shdr[SYMTAB_SECTION].sh_link = STRTAB_SECTION;
-  shdr[SYMTAB_SECTION].sh_addralign = 4;
+  shdr[symtab_section].sh_name = insert_string (".symtab");
+  shdr[symtab_section].sh_type = SHT_SYMTAB;
+  shdr[symtab_section].sh_offset = offset;
+  shdr[symtab_section].sh_size = num_syms * sizeof (Elf_Sym);
+  shdr[symtab_section].sh_entsize = sizeof (Elf_Sym);
+  shdr[symtab_section].sh_link = strtab_section;
+  shdr[symtab_section].sh_addralign = 4;
 
-  grub_util_write_image_at (symtab, shdr[SYMTAB_SECTION].sh_size,
+  grub_util_write_image_at (symtab, shdr[symtab_section].sh_size,
                             offset, fp, name);
-  offset += shdr[SYMTAB_SECTION].sh_size;
+  offset += shdr[symtab_section].sh_size;
 
   free (symtab);
   free (symtab_map);
@@ -398,11 +465,11 @@ write_symbol_table (FILE* fp, const char *name, char *image,
 static void
 write_string_table (FILE *fp, const char *name)
 {
-  shdr[STRTAB_SECTION].sh_name = insert_string (".strtab");
-  shdr[STRTAB_SECTION].sh_type = SHT_STRTAB;
-  shdr[STRTAB_SECTION].sh_offset = offset;
-  shdr[STRTAB_SECTION].sh_size = strtab_len;
-  shdr[STRTAB_SECTION].sh_addralign = 1;
+  shdr[strtab_section].sh_name = insert_string (".strtab");
+  shdr[strtab_section].sh_type = SHT_STRTAB;
+  shdr[strtab_section].sh_offset = offset;
+  shdr[strtab_section].sh_size = strtab_len;
+  shdr[strtab_section].sh_addralign = 1;
   grub_util_write_image_at (strtab, strtab_len, offset, fp,
                            name);
   offset += strtab_len;
@@ -421,20 +488,25 @@ write_section_header (FILE *fp, const char *name)
   ehdr.e_version = EV_CURRENT;
   ehdr.e_type = ET_REL;
 
+#if GRUB_TARGET_WORDSIZE == 64
+  ehdr.e_ident[EI_CLASS] = ELFCLASS64;
+  ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+  ehdr.e_machine = EM_X86_64;
+#else
   ehdr.e_ident[EI_CLASS] = ELFCLASS32;
   ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
   ehdr.e_machine = EM_386;
-
+#endif
   ehdr.e_ehsize = sizeof (ehdr);
-  ehdr.e_shentsize = sizeof (Elf32_Shdr);
-  ehdr.e_shstrndx = STRTAB_SECTION;
+  ehdr.e_shentsize = sizeof (Elf_Shdr);
+  ehdr.e_shstrndx = strtab_section;
 
   ehdr.e_shoff = offset;
   ehdr.e_shnum = num_sections;
-  grub_util_write_image_at (&shdr, sizeof (Elf32_Shdr) * num_sections,
+  grub_util_write_image_at (shdr, sizeof (Elf_Shdr) * num_sections,
                             offset, fp, name);
 
-  grub_util_write_image_at (&ehdr, sizeof (Elf32_Ehdr), 0, fp, name);
+  grub_util_write_image_at (&ehdr, sizeof (Elf_Ehdr), 0, fp, name);
 }
 
 static void
@@ -448,9 +520,9 @@ convert_pe (FILE* fp, const char *name, char *image)
     pe_chdr = (struct grub_pe32_coff_header *) (image + (grub_le_to_cpu32 (((grub_uint32_t *)image)[0xf]) + 4));
   else
     pe_chdr = (struct grub_pe32_coff_header *) image;
-  if (grub_le_to_cpu16 (pe_chdr->machine) != GRUB_PE32_MACHINE_I386)
+  if (grub_le_to_cpu16 (pe_chdr->machine) != GRUB_PE32_MACHINE)
     grub_util_error ("invalid coff image (%x != %x)",
-                    grub_le_to_cpu16 (pe_chdr->machine), GRUB_PE32_MACHINE_I386);
+                    grub_le_to_cpu16 (pe_chdr->machine), GRUB_PE32_MACHINE);
 
   strtab = xmalloc (STRTAB_BLOCK);
   strtab_max = STRTAB_BLOCK;
@@ -460,12 +532,15 @@ convert_pe (FILE* fp, const char *name, char *image)
   offset = sizeof (ehdr);
   if (pe_chdr->optional_header_size)
     {
+#if GRUB_TARGET_WORDSIZE == 64
+      struct grub_pe64_optional_header *o;
+#else
       struct grub_pe32_optional_header *o;
-      o = (struct grub_pe32_optional_header *) (pe_chdr + 1);
+#endif
+      o = (void *) (pe_chdr + 1);
       image_base = o->image_base;
     }
   pe_shdr = (struct grub_pe32_section_table *) ((char *) (pe_chdr + 1) + pe_chdr->optional_header_size);
-  num_sections = REL_SECTION;
 
   section_map = write_section_data (fp, name, image, pe_chdr, pe_shdr);