Add support for converting PE+ to Elf64.
This commit is contained in:
parent
66a07ce2f8
commit
6f1f6a0c82
4 changed files with 189 additions and 101 deletions
|
@ -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>
|
2013-12-16 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/commands/minicmd.c (grub_mini_cmd_dump): Handle LLP case.
|
* grub-core/commands/minicmd.c (grub_mini_cmd_dump): Handle LLP case.
|
||||||
|
|
14
configure.ac
14
configure.ac
|
@ -699,7 +699,7 @@ AC_ARG_ENABLE([efiemu],
|
||||||
if test x"$enable_efiemu" = xno ; then
|
if test x"$enable_efiemu" = xno ; then
|
||||||
efiemu_excuse="explicitly disabled"
|
efiemu_excuse="explicitly disabled"
|
||||||
fi
|
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"
|
efiemu_excuse="not available on cygwin"
|
||||||
fi
|
fi
|
||||||
if test x"$target_cpu" != xi386 ; then
|
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
|
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], [
|
AC_CACHE_CHECK([for target linking format], [grub_cv_target_cc_link_format], [
|
||||||
grub_cv_target_cc_link_format=unknown
|
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
|
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 = x${target_cpu}pe; then
|
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
|
continue
|
||||||
fi
|
fi
|
||||||
CFLAGS="$TARGET_CFLAGS"
|
CFLAGS="$TARGET_CFLAGS"
|
||||||
|
@ -784,6 +787,9 @@ if test x"$target_cpu" = xi386 || test x"$target_cpu" = xx86_64; then
|
||||||
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';
|
TARGET_OBJ2ELF='./build-grub-pe2elf';
|
||||||
fi
|
fi
|
||||||
|
if test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then
|
||||||
|
TARGET_OBJ2ELF='./build-grub-pep2elf';
|
||||||
|
fi
|
||||||
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
|
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_LDFLAGS_AC='-nostdlib -static -Wl,-preload -Wl,-segalign,20'
|
||||||
TARGET_IMG_BASE_LDOPT="-Wl,-image_base"
|
TARGET_IMG_BASE_LDOPT="-Wl,-image_base"
|
||||||
TARGET_LDFLAGS_OLDMAGIC=""
|
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_APPLE_LINKER=0
|
||||||
TARGET_LDFLAGS_OLDMAGIC="-Wl,-N"
|
TARGET_LDFLAGS_OLDMAGIC="-Wl,-N"
|
||||||
TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/${grub_coredir}/conf/i386-cygwin-img-ld.sc"
|
TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/${grub_coredir}/conf/i386-cygwin-img-ld.sc"
|
||||||
|
|
|
@ -26,8 +26,11 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin
|
||||||
CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
|
CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
|
||||||
CCASFLAGS_LIBRARY += $(CCASFLAGS_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-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: gentrigtables.c
|
gentrigtables: gentrigtables.c
|
||||||
|
|
|
@ -48,29 +48,32 @@
|
||||||
* relocation sections
|
* relocation sections
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define TEXT_SECTION 1
|
#if GRUB_TARGET_WORDSIZE == 64
|
||||||
#define RDATA_SECTION 2
|
typedef Elf64_Rela elf_reloc_t;
|
||||||
#define DATA_SECTION 3
|
typedef Elf64_Ehdr Elf_Ehdr;
|
||||||
#define BSS_SECTION 4
|
typedef Elf64_Shdr Elf_Shdr;
|
||||||
#define MODNAME_SECTION 5
|
typedef Elf64_Sym Elf_Sym;
|
||||||
#define MODDEPS_SECTION 6
|
#define ELF_R_INFO ELF64_R_INFO
|
||||||
#define MODLICENSE_SECTION 7
|
#define ELF_ST_INFO ELF64_ST_INFO
|
||||||
#define SYMTAB_SECTION 8
|
#define GRUB_PE32_MACHINE GRUB_PE32_MACHINE_X86_64
|
||||||
#define STRTAB_SECTION 9
|
#else
|
||||||
|
typedef Elf32_Rel elf_reloc_t;
|
||||||
#define REL_SECTION 10
|
typedef Elf32_Ehdr Elf_Ehdr;
|
||||||
|
typedef Elf32_Shdr Elf_Shdr;
|
||||||
/* 10 normal section + up to 4 relocation (.text, .rdata, .data, .symtab). */
|
typedef Elf32_Sym Elf_Sym;
|
||||||
#define MAX_SECTIONS 16
|
#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
|
#define STRTAB_BLOCK 256
|
||||||
|
|
||||||
static char *strtab;
|
static char *strtab;
|
||||||
static int strtab_max, strtab_len;
|
static int strtab_max, strtab_len;
|
||||||
|
|
||||||
static Elf32_Ehdr ehdr;
|
static Elf_Ehdr ehdr;
|
||||||
static Elf32_Shdr shdr[MAX_SECTIONS];
|
static Elf_Shdr *shdr;
|
||||||
static int num_sections;
|
static int num_sections, first_reloc_section, reloc_sections_end, symtab_section, strtab_section;
|
||||||
static grub_uint32_t offset, image_base;
|
static grub_uint32_t offset, image_base;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -102,15 +105,20 @@ write_section_data (FILE* fp, const char *name, char *image,
|
||||||
{
|
{
|
||||||
int *section_map;
|
int *section_map;
|
||||||
int i;
|
int i;
|
||||||
|
grub_uint32_t last_category = 0;
|
||||||
|
grub_uint32_t idx, idx_reloc;
|
||||||
char *pe_strtab = (image + pe_chdr->symtab_offset
|
char *pe_strtab = (image + pe_chdr->symtab_offset
|
||||||
+ pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol));
|
+ 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;
|
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++)
|
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;
|
const char *shname = pe_shdr->name;
|
||||||
grub_size_t secsize;
|
grub_size_t secsize;
|
||||||
|
|
||||||
|
@ -124,54 +132,56 @@ write_section_data (FILE* fp, const char *name, char *image,
|
||||||
|
|
||||||
secsize = pe_shdr->raw_data_size;
|
secsize = pe_shdr->raw_data_size;
|
||||||
|
|
||||||
|
shdr[idx].sh_type = SHT_PROGBITS;
|
||||||
|
|
||||||
if (! strcmp (shname, ".text"))
|
if (! strcmp (shname, ".text"))
|
||||||
{
|
{
|
||||||
idx = TEXT_SECTION;
|
category = 0;
|
||||||
shdr[idx].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
|
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;
|
shdr[idx].sh_flags = SHF_ALLOC;
|
||||||
}
|
}
|
||||||
else if (! strcmp (shname, ".data"))
|
else if (! strcmp (shname, ".data"))
|
||||||
{
|
{
|
||||||
idx = DATA_SECTION;
|
category = 2;
|
||||||
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
|
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
|
||||||
}
|
}
|
||||||
else if (! strcmp (shname, ".bss"))
|
else if (! strcmp (shname, ".bss"))
|
||||||
{
|
{
|
||||||
idx = BSS_SECTION;
|
category = 3;
|
||||||
|
shdr[idx].sh_type = SHT_NOBITS;
|
||||||
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
|
shdr[idx].sh_flags = SHF_ALLOC | SHF_WRITE;
|
||||||
if (secsize < pe_shdr->virtual_size)
|
if (secsize < pe_shdr->virtual_size)
|
||||||
secsize = pe_shdr->virtual_size;
|
secsize = pe_shdr->virtual_size;
|
||||||
}
|
}
|
||||||
else if (! strcmp (shname, ".modname"))
|
else if (strcmp (shname, ".modname") == 0 || strcmp (shname, ".moddeps") == 0
|
||||||
idx = MODNAME_SECTION;
|
|| strcmp (shname, ".module_license") == 0)
|
||||||
else if (! strcmp (shname, ".moddeps"))
|
category = 4;
|
||||||
idx = MODDEPS_SECTION;
|
|
||||||
else if (strcmp (shname, ".module_license") == 0)
|
|
||||||
idx = MODLICENSE_SECTION;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
section_map[i + 1] = -1;
|
section_map[i + 1] = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (category < last_category)
|
||||||
|
grub_util_error ("out of order sections");
|
||||||
|
|
||||||
section_map[i + 1] = idx;
|
section_map[i + 1] = idx;
|
||||||
|
|
||||||
if (pe_shdr->virtual_size
|
if (pe_shdr->virtual_size
|
||||||
&& pe_shdr->virtual_size < secsize)
|
&& pe_shdr->virtual_size < secsize)
|
||||||
secsize = pe_shdr->virtual_size;
|
secsize = pe_shdr->virtual_size;
|
||||||
|
|
||||||
shdr[idx].sh_type = (idx == BSS_SECTION) ? SHT_NOBITS : SHT_PROGBITS;
|
|
||||||
shdr[idx].sh_size = secsize;
|
shdr[idx].sh_size = secsize;
|
||||||
shdr[idx].sh_addralign = 1 << (((pe_shdr->characteristics >>
|
shdr[idx].sh_addralign = 1 << (((pe_shdr->characteristics >>
|
||||||
GRUB_PE32_SCN_ALIGN_SHIFT) &
|
GRUB_PE32_SCN_ALIGN_SHIFT) &
|
||||||
GRUB_PE32_SCN_ALIGN_MASK) - 1);
|
GRUB_PE32_SCN_ALIGN_MASK) - 1);
|
||||||
shdr[idx].sh_addr = pe_shdr->virtual_address + image_base;
|
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;
|
shdr[idx].sh_offset = offset;
|
||||||
grub_util_write_image_at (image + pe_shdr->raw_data_offset,
|
grub_util_write_image_at (image + pe_shdr->raw_data_offset,
|
||||||
|
@ -185,23 +195,33 @@ write_section_data (FILE* fp, const char *name, char *image,
|
||||||
{
|
{
|
||||||
char relname[5 + strlen (shname)];
|
char relname[5 + strlen (shname)];
|
||||||
|
|
||||||
if (num_sections >= MAX_SECTIONS)
|
|
||||||
grub_util_error ("too many sections");
|
|
||||||
|
|
||||||
sprintf (relname, ".rel%s", shname);
|
sprintf (relname, ".rel%s", shname);
|
||||||
|
|
||||||
shdr[num_sections].sh_name = insert_string (relname);
|
shdr[idx_reloc].sh_name = insert_string (relname);
|
||||||
shdr[num_sections].sh_link = i;
|
shdr[idx_reloc].sh_link = i;
|
||||||
shdr[num_sections].sh_info = idx;
|
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
|
else
|
||||||
shdr[idx].sh_name = insert_string (shname);
|
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;
|
return section_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,21 +229,21 @@ static void
|
||||||
write_reloc_section (FILE* fp, const char *name, char *image,
|
write_reloc_section (FILE* fp, const char *name, char *image,
|
||||||
struct grub_pe32_coff_header *pe_chdr,
|
struct grub_pe32_coff_header *pe_chdr,
|
||||||
struct grub_pe32_section_table *pe_shdr,
|
struct grub_pe32_section_table *pe_shdr,
|
||||||
Elf32_Sym *symtab,
|
Elf_Sym *symtab,
|
||||||
int *symtab_map)
|
int *symtab_map)
|
||||||
{
|
{
|
||||||
int i;
|
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_section_table *pe_sec;
|
||||||
struct grub_pe32_reloc *pe_rel;
|
struct grub_pe32_reloc *pe_rel;
|
||||||
Elf32_Rel *rel;
|
elf_reloc_t *rel;
|
||||||
int num_rels, j, modified;
|
int num_rels, j, modified;
|
||||||
|
|
||||||
pe_sec = pe_shdr + shdr[i].sh_link;
|
pe_sec = pe_shdr + shdr[i].sh_link;
|
||||||
pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset);
|
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;
|
num_rels = 0;
|
||||||
modified = 0;
|
modified = 0;
|
||||||
|
|
||||||
|
@ -236,42 +256,83 @@ write_reloc_section (FILE* fp, const char *name, char *image,
|
||||||
(symtab_map[pe_rel->symtab_index] == -1))
|
(symtab_map[pe_rel->symtab_index] == -1))
|
||||||
grub_util_error ("invalid symbol");
|
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;
|
ofs = pe_rel->offset - pe_sec->virtual_address;
|
||||||
addr = (grub_uint32_t *)(image + pe_sec->raw_data_offset + ofs);
|
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;
|
unsigned char code;
|
||||||
|
|
||||||
code = image[pe_sec->raw_data_offset + ofs - 1];
|
code = image[pe_sec->raw_data_offset + ofs - 1];
|
||||||
|
|
||||||
|
#if GRUB_TARGET_WORDSIZE == 32
|
||||||
if (((code != 0xe8) && (code != 0xe9)) || (*addr))
|
if (((code != 0xe8) && (code != 0xe9)) || (*addr))
|
||||||
grub_util_error ("invalid relocation (%x %x)", code, *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
|
if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx
|
||||||
!= shdr[i].sh_info)
|
&& symtab[symtab_map[pe_rel->symtab_index]].st_shndx
|
||||||
grub_util_error ("cross section call is not allowed");
|
== shdr[i].sh_info)
|
||||||
|
{
|
||||||
*addr = (symtab[symtab_map[pe_rel->symtab_index]].st_value
|
modified = 1;
|
||||||
|
*addr += (symtab[symtab_map[pe_rel->symtab_index]].st_value
|
||||||
- ofs - 4);
|
- ofs - 4);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
#if GRUB_TARGET_WORDSIZE == 64
|
||||||
|
rel[num_rels].r_addend -= 4;
|
||||||
|
#else
|
||||||
|
modified = 1;
|
||||||
*addr = -4;
|
*addr = -4;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rel[num_rels].r_offset = ofs;
|
rel[num_rels].r_offset = ofs;
|
||||||
rel[num_rels].r_info = ELF32_R_INFO (symtab_map[pe_rel->symtab_index],
|
rel[num_rels].r_info = ELF_R_INFO (symtab_map[pe_rel->symtab_index],
|
||||||
type);
|
type);
|
||||||
num_rels++;
|
num_rels++;
|
||||||
}
|
}
|
||||||
|
@ -282,12 +343,16 @@ write_reloc_section (FILE* fp, const char *name, char *image,
|
||||||
shdr[shdr[i].sh_info].sh_offset,
|
shdr[shdr[i].sh_info].sh_offset,
|
||||||
fp, name);
|
fp, name);
|
||||||
|
|
||||||
|
#if GRUB_TARGET_WORDSIZE == 64
|
||||||
|
shdr[i].sh_type = SHT_RELA;
|
||||||
|
#else
|
||||||
shdr[i].sh_type = SHT_REL;
|
shdr[i].sh_type = SHT_REL;
|
||||||
|
#endif
|
||||||
shdr[i].sh_offset = offset;
|
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_addralign = 4;
|
||||||
shdr[i].sh_entsize = sizeof (Elf32_Rel);
|
shdr[i].sh_entsize = sizeof (elf_reloc_t);
|
||||||
shdr[i].sh_size = num_rels * sizeof (Elf32_Rel);
|
shdr[i].sh_size = num_rels * sizeof (elf_reloc_t);
|
||||||
|
|
||||||
grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp, name);
|
grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp, name);
|
||||||
offset += shdr[i].sh_size;
|
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;
|
struct grub_pe32_symbol *pe_symtab;
|
||||||
char *pe_strtab;
|
char *pe_strtab;
|
||||||
Elf32_Sym *symtab;
|
Elf_Sym *symtab;
|
||||||
int *symtab_map, num_syms;
|
int *symtab_map, num_syms;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
|
pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
|
||||||
pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
|
pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
|
||||||
|
|
||||||
symtab = (Elf32_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
|
symtab = (Elf_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
|
||||||
sizeof (Elf32_Sym));
|
sizeof (Elf_Sym));
|
||||||
memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf32_Sym));
|
memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf_Sym));
|
||||||
num_syms = 1;
|
num_syms = 1;
|
||||||
|
|
||||||
symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int));
|
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")) &&
|
if ((strcmp (symname, "_grub_mod_init")) &&
|
||||||
(strcmp (symname, "_grub_mod_fini")) &&
|
(strcmp (symname, "_grub_mod_fini")) &&
|
||||||
|
(strcmp (symname, "grub_mod_init")) &&
|
||||||
|
(strcmp (symname, "grub_mod_fini")) &&
|
||||||
(bind == STB_LOCAL))
|
(bind == STB_LOCAL))
|
||||||
continue;
|
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_shndx = section_map[pe_symtab->section];
|
||||||
symtab[num_syms].st_value = pe_symtab->value;
|
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;
|
symtab_map[i] = num_syms;
|
||||||
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,
|
write_reloc_section (fp, name, image, pe_chdr, pe_shdr,
|
||||||
symtab, symtab_map);
|
symtab, symtab_map);
|
||||||
|
|
||||||
shdr[SYMTAB_SECTION].sh_name = insert_string (".symtab");
|
shdr[symtab_section].sh_name = insert_string (".symtab");
|
||||||
shdr[SYMTAB_SECTION].sh_type = SHT_SYMTAB;
|
shdr[symtab_section].sh_type = SHT_SYMTAB;
|
||||||
shdr[SYMTAB_SECTION].sh_offset = offset;
|
shdr[symtab_section].sh_offset = offset;
|
||||||
shdr[SYMTAB_SECTION].sh_size = num_syms * sizeof (Elf32_Sym);
|
shdr[symtab_section].sh_size = num_syms * sizeof (Elf_Sym);
|
||||||
shdr[SYMTAB_SECTION].sh_entsize = sizeof (Elf32_Sym);
|
shdr[symtab_section].sh_entsize = sizeof (Elf_Sym);
|
||||||
shdr[SYMTAB_SECTION].sh_link = STRTAB_SECTION;
|
shdr[symtab_section].sh_link = strtab_section;
|
||||||
shdr[SYMTAB_SECTION].sh_addralign = 4;
|
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, fp, name);
|
||||||
offset += shdr[SYMTAB_SECTION].sh_size;
|
offset += shdr[symtab_section].sh_size;
|
||||||
|
|
||||||
free (symtab);
|
free (symtab);
|
||||||
free (symtab_map);
|
free (symtab_map);
|
||||||
|
@ -398,11 +465,11 @@ write_symbol_table (FILE* fp, const char *name, char *image,
|
||||||
static void
|
static void
|
||||||
write_string_table (FILE *fp, const char *name)
|
write_string_table (FILE *fp, const char *name)
|
||||||
{
|
{
|
||||||
shdr[STRTAB_SECTION].sh_name = insert_string (".strtab");
|
shdr[strtab_section].sh_name = insert_string (".strtab");
|
||||||
shdr[STRTAB_SECTION].sh_type = SHT_STRTAB;
|
shdr[strtab_section].sh_type = SHT_STRTAB;
|
||||||
shdr[STRTAB_SECTION].sh_offset = offset;
|
shdr[strtab_section].sh_offset = offset;
|
||||||
shdr[STRTAB_SECTION].sh_size = strtab_len;
|
shdr[strtab_section].sh_size = strtab_len;
|
||||||
shdr[STRTAB_SECTION].sh_addralign = 1;
|
shdr[strtab_section].sh_addralign = 1;
|
||||||
grub_util_write_image_at (strtab, strtab_len, offset, fp,
|
grub_util_write_image_at (strtab, strtab_len, offset, fp,
|
||||||
name);
|
name);
|
||||||
offset += strtab_len;
|
offset += strtab_len;
|
||||||
|
@ -421,20 +488,25 @@ write_section_header (FILE *fp, const char *name)
|
||||||
ehdr.e_version = EV_CURRENT;
|
ehdr.e_version = EV_CURRENT;
|
||||||
ehdr.e_type = ET_REL;
|
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_CLASS] = ELFCLASS32;
|
||||||
ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
|
ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||||
ehdr.e_machine = EM_386;
|
ehdr.e_machine = EM_386;
|
||||||
|
#endif
|
||||||
ehdr.e_ehsize = sizeof (ehdr);
|
ehdr.e_ehsize = sizeof (ehdr);
|
||||||
ehdr.e_shentsize = sizeof (Elf32_Shdr);
|
ehdr.e_shentsize = sizeof (Elf_Shdr);
|
||||||
ehdr.e_shstrndx = STRTAB_SECTION;
|
ehdr.e_shstrndx = strtab_section;
|
||||||
|
|
||||||
ehdr.e_shoff = offset;
|
ehdr.e_shoff = offset;
|
||||||
ehdr.e_shnum = num_sections;
|
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);
|
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
|
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));
|
pe_chdr = (struct grub_pe32_coff_header *) (image + (grub_le_to_cpu32 (((grub_uint32_t *)image)[0xf]) + 4));
|
||||||
else
|
else
|
||||||
pe_chdr = (struct grub_pe32_coff_header *) image;
|
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_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 = xmalloc (STRTAB_BLOCK);
|
||||||
strtab_max = STRTAB_BLOCK;
|
strtab_max = STRTAB_BLOCK;
|
||||||
|
@ -460,12 +532,15 @@ convert_pe (FILE* fp, const char *name, char *image)
|
||||||
offset = sizeof (ehdr);
|
offset = sizeof (ehdr);
|
||||||
if (pe_chdr->optional_header_size)
|
if (pe_chdr->optional_header_size)
|
||||||
{
|
{
|
||||||
|
#if GRUB_TARGET_WORDSIZE == 64
|
||||||
|
struct grub_pe64_optional_header *o;
|
||||||
|
#else
|
||||||
struct grub_pe32_optional_header *o;
|
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;
|
image_base = o->image_base;
|
||||||
}
|
}
|
||||||
pe_shdr = (struct grub_pe32_section_table *) ((char *) (pe_chdr + 1) + pe_chdr->optional_header_size);
|
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);
|
section_map = write_section_data (fp, name, image, pe_chdr, pe_shdr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue