aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Gault <sylvain.gault@gmail.com>2014-02-03 05:43:03 +0100
committerH. Peter Anvin <hpa@linux.intel.com>2014-02-14 16:31:42 -0800
commit76ef6aab4a157bba1c53a5da19cecbbee4172a19 (patch)
treeb8a6a5324b2600c37c5ed910056e6ba9e3bf45aa
parent8c9a43f9fbd69a022f4a0913192e7bbc847e1af5 (diff)
downloadsyslinux-76ef6aab4a157bba1c53a5da19cecbbee4172a19.tar.gz
syslinux-76ef6aab4a157bba1c53a5da19cecbbee4172a19.tar.xz
syslinux-76ef6aab4a157bba1c53a5da19cecbbee4172a19.zip
efi: Location, size and alignment of .text section
In the generated PE file, the section header for the .text section used to address more than the whole file. Starting at offset 0 (before the end of the headers) is illegal and is rejected by OVMF. Giving a size greater than the actual file size is also illegal and rejected. Moreover, the body of the PE file have to be aligned to at least 512 bytes. Hence, .text need to be aligned as well. Signed-off-by: Sylvain Gault <sylvain.gault@gmail.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--efi/wrapper.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/efi/wrapper.c b/efi/wrapper.c
index ec77271b..8b553f85 100644
--- a/efi/wrapper.c
+++ b/efi/wrapper.c
@@ -54,11 +54,19 @@ static void write_header(FILE *f, __uint32_t entry, size_t data_size,
struct coff_hdr c_hdr;
struct header hdr;
struct coff_reloc c_rel;
- __uint32_t total_sz = so_size;
+ __uint32_t total_sz = data_size;
__uint32_t dummy = 0;
__uint32_t hdr_sz;
__uint32_t reloc_start, reloc_end;
+ /*
+ * The header size have to be a multiple of file_align, which currently
+ * is 512
+ */
+ hdr_sz = 512;
+ total_sz += hdr_sz;
+ entry += hdr_sz;
+
memset(&hdr, 0, sizeof(hdr));
hdr.msdos_signature = MSDOS_SIGNATURE;
@@ -77,11 +85,6 @@ static void write_header(FILE *f, __uint32_t entry, size_t data_size,
c_hdr.nr_sections = 2;
c_hdr.nr_syms = 1;
if (class == ELFCLASS32) {
- hdr_sz = sizeof(o_hdr) + sizeof(t_sec) + sizeof(e_hdr) +
- sizeof(r_sec) + sizeof(c_hdr) + sizeof(hdr) + sizeof(c_rel)
- + sizeof(dummy);
- total_sz += hdr_sz;
- entry += hdr_sz;
c_hdr.arch = IMAGE_FILE_MACHINE_I386;
c_hdr.characteristics = IMAGE_FILE_32BIT_MACHINE |
IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
@@ -92,25 +95,20 @@ static void write_header(FILE *f, __uint32_t entry, size_t data_size,
o_hdr.format = PE32_FORMAT;
o_hdr.major_linker_version = 0x02;
o_hdr.minor_linker_version = 0x14;
- o_hdr.code_sz = total_sz;
+ o_hdr.code_sz = data_size;
o_hdr.entry_point = entry;
o_hdr.initialized_data_sz = data_size;
fwrite(&o_hdr, sizeof(o_hdr), 1, f);
memset(&e_hdr, 0, sizeof(e_hdr));
e_hdr.section_align = 4096;
e_hdr.file_align = 512;
- e_hdr.image_sz = total_sz;
- e_hdr.headers_sz = 512;
+ e_hdr.image_sz = hdr_sz + so_size;
+ e_hdr.headers_sz = hdr_sz;
e_hdr.subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION;
e_hdr.rva_and_sizes_nr = sizeof(e_hdr.data_directory) / sizeof(__uint64_t);
fwrite(&e_hdr, sizeof(e_hdr), 1, f);
}
else if (class == ELFCLASS64) {
- hdr_sz = sizeof(o_hdr_pe32p) + sizeof(t_sec) + sizeof(e_hdr_pe32p) +
- sizeof(r_sec) + sizeof(c_hdr) + sizeof(hdr) + sizeof(c_rel)
- + sizeof(dummy);
- total_sz += hdr_sz;
- entry += hdr_sz;
c_hdr.arch = IMAGE_FILE_MACHINE_X86_64;
c_hdr.characteristics = IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
IMAGE_FILE_LINE_NUMBERS_STRIPPED;
@@ -120,15 +118,15 @@ static void write_header(FILE *f, __uint32_t entry, size_t data_size,
o_hdr_pe32p.format = PE32P_FORMAT;
o_hdr_pe32p.major_linker_version = 0x02;
o_hdr_pe32p.minor_linker_version = 0x14;
- o_hdr_pe32p.code_sz = total_sz;
+ o_hdr_pe32p.code_sz = data_size;
o_hdr_pe32p.entry_point = entry;
o_hdr.initialized_data_sz = data_size;
fwrite(&o_hdr_pe32p, sizeof(o_hdr_pe32p), 1, f);
memset(&e_hdr_pe32p, 0, sizeof(e_hdr));
e_hdr_pe32p.section_align = 4096;
e_hdr_pe32p.file_align = 512;
- e_hdr_pe32p.image_sz = total_sz;
- e_hdr_pe32p.headers_sz = 512;
+ e_hdr_pe32p.image_sz = hdr_sz + so_size;
+ e_hdr_pe32p.headers_sz = hdr_sz;
e_hdr_pe32p.subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION;
e_hdr_pe32p.rva_and_sizes_nr = sizeof(e_hdr_pe32p.data_directory) / sizeof(__uint64_t);
fwrite(&e_hdr_pe32p, sizeof(e_hdr_pe32p), 1, f);
@@ -136,8 +134,10 @@ static void write_header(FILE *f, __uint32_t entry, size_t data_size,
memset(&t_sec, 0, sizeof(t_sec));
strcpy((char *)t_sec.name, ".text");
- t_sec.virtual_sz = total_sz;
- t_sec.raw_data_sz = total_sz;
+ t_sec.virtual_sz = data_size;
+ t_sec.virtual_address = hdr_sz;
+ t_sec.raw_data_sz = t_sec.virtual_sz;
+ t_sec.raw_data = t_sec.virtual_address;
t_sec.characteristics = IMAGE_SCN_CNT_CODE |
IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
IMAGE_SCN_MEM_READ;
@@ -163,6 +163,16 @@ static void write_header(FILE *f, __uint32_t entry, size_t data_size,
fwrite(&c_rel, sizeof(c_rel), 1, f);
fwrite(&dummy, sizeof(dummy), 1, f);
+ /*
+ * Add some padding to align the ELF as needed
+ */
+ if (ftell(f) > t_sec.virtual_address) {
+ /* Don't rewind! hdr_sz need to be increased. */
+ fprintf(stderr, "PE32+ headers are too large.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ fseek(f, t_sec.virtual_address, SEEK_SET);
}
static void usage(char *progname)