diff options
author | Matt Fleming <matt.fleming@intel.com> | 2013-05-20 17:23:30 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2013-05-21 11:30:30 +0100 |
commit | 3d3f765a61f67acf86acee0fed0dc5fabfd8a6fd (patch) | |
tree | 0df479c39dedfb64b23f87c49491e6abd5a852b7 | |
parent | f7404e7c9d217903f5f040ca53e3fe7ffd0523be (diff) | |
download | syslinux-3d3f765a61f67acf86acee0fed0dc5fabfd8a6fd.tar.gz syslinux-3d3f765a61f67acf86acee0fed0dc5fabfd8a6fd.tar.xz syslinux-3d3f765a61f67acf86acee0fed0dc5fabfd8a6fd.zip |
efi: shrink the size of syslinux.efi
syslinux.efi currently includes the .bss section of the ELF shared
object, syslinux.so, as zero'd space in the file. This dramatically
increases the size of syslinux.efi.
Use the 'initialized_data_sz' field in the MSDOS/COFF header to
differentiate the on-disk and in-memory file size, and to make the
firmware loader zero the .bss for us.
efi/wrapper now only copies upto the offset of the .bss section from
syslinux.so when building syslinux.efi.
With this change syslinux.efi shrinks from 2.4M to 168K.
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r-- | efi/i386/syslinux.ld | 5 | ||||
-rw-r--r-- | efi/wrapper.c | 121 | ||||
-rw-r--r-- | efi/x86_64/syslinux.ld | 5 |
3 files changed, 116 insertions, 15 deletions
diff --git a/efi/i386/syslinux.ld b/efi/i386/syslinux.ld index e0270537..523a9b90 100644 --- a/efi/i386/syslinux.ld +++ b/efi/i386/syslinux.ld @@ -128,10 +128,6 @@ SECTIONS *(.reloc) } - .comment : { - *(.commet) - } - .symtab : { *(.symtab) } @@ -172,5 +168,6 @@ SECTIONS /* Stuff we don't need... */ /DISCARD/ : { *(.eh_frame) + *(.comment) } } diff --git a/efi/wrapper.c b/efi/wrapper.c index 1b1d5d33..04c895f6 100644 --- a/efi/wrapper.c +++ b/efi/wrapper.c @@ -36,13 +36,15 @@ typedef Elf64_Addr Elf_Addr; /* * 'so_size' is the file size of the ELF shared object. + * 'data_size' is the size of initialised data in the shared object. * 'class' dictates how the header is written * For 32bit machines (class == ELFCLASS32), the optional * header includes PE32 header fields * For 64bit machines (class == ELFCLASS64), the optional * header includes PE32+header fields */ -static void write_header(FILE *f, __uint32_t entry, __uint32_t so_size, __uint8_t class) +static void write_header(FILE *f, __uint32_t entry, size_t data_size, + __uint32_t so_size, __uint8_t class) { struct optional_hdr o_hdr; struct optional_hdr_pe32p o_hdr_pe32p; @@ -57,7 +59,6 @@ static void write_header(FILE *f, __uint32_t entry, __uint32_t so_size, __uint8_ __uint32_t hdr_sz; __uint32_t reloc_start, reloc_end; - memset(&hdr, 0, sizeof(hdr)); hdr.msdos_signature = MSDOS_SIGNATURE; @@ -93,6 +94,7 @@ static void write_header(FILE *f, __uint32_t entry, __uint32_t so_size, __uint8_ o_hdr.minor_linker_version = 0x14; o_hdr.code_sz = total_sz; 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; @@ -120,6 +122,7 @@ static void write_header(FILE *f, __uint32_t entry, __uint32_t so_size, __uint8_ o_hdr_pe32p.minor_linker_version = 0x14; o_hdr_pe32p.code_sz = total_sz; 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; @@ -175,10 +178,12 @@ int main(int argc, char **argv) Elf64_Ehdr e64_hdr; __uint32_t entry; __uint8_t class; + __uint64_t shoff; + __uint16_t shnum, shentsize, shstrndx; unsigned char *id; FILE *f_in, *f_out; void *buf; - size_t rv; + size_t datasz, rv; if (argc < 3) { usage(argv[0]); @@ -210,6 +215,10 @@ int main(int argc, char **argv) id = e32_hdr.e_ident; class = ELFCLASS32; entry = e32_hdr.e_entry; + shoff = e32_hdr.e_shoff; + shnum = e32_hdr.e_shnum; + shstrndx = e32_hdr.e_shstrndx; + shentsize = e32_hdr.e_shentsize; } else if (e32_hdr.e_ident[EI_CLASS] == ELFCLASS64) { /* read the header again for x86_64 @@ -220,6 +229,10 @@ int main(int argc, char **argv) fread((void *)&e64_hdr, sizeof(e64_hdr), 1, f_in); id = e64_hdr.e_ident; entry = e64_hdr.e_entry; + shoff = e64_hdr.e_shoff; + shnum = e64_hdr.e_shnum; + shstrndx = e64_hdr.e_shstrndx; + shentsize = e64_hdr.e_shentsize; } else { fprintf(stderr, "Unsupported architecture\n"); exit(EXIT_FAILURE); @@ -233,22 +246,116 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - buf = malloc(st.st_size); + if (!shoff || !shnum || (shstrndx == SHN_UNDEF)) { + fprintf(stderr, "Cannot find section table\n"); + exit(EXIT_FAILURE); + } + + /* + * Find the beginning of the .bss section. Everything preceding + * it is copied verbatim to the output file. + */ + if (e32_hdr.e_ident[EI_CLASS] == ELFCLASS32) { + const char *shstrtab, *name; + Elf32_Shdr shdr; + int i; + void *strtab; + + fseek(f_in, shoff, SEEK_SET); + + /* First find the strtab section */ + fseek(f_in, shstrndx * shentsize, SEEK_CUR); + fread(&shdr, sizeof(shdr), 1, f_in); + + strtab = malloc(shdr.sh_size); + if (!strtab) { + fprintf(stderr, "Failed to malloc strtab\n"); + exit(EXIT_FAILURE); + } + + fseek(f_in, shdr.sh_offset, SEEK_SET); + fread(strtab, shdr.sh_size, 1, f_in); + + /* Now search for the .bss section */ + fseek(f_in, shoff, SEEK_SET); + for (i = 0; i < shnum; i++) { + rv = fread(&shdr, sizeof(shdr), 1, f_in); + if (!rv) { + fprintf(stderr, "Failed to read section table\n"); + exit(EXIT_FAILURE); + } + + name = strtab + shdr.sh_name; + if (!strcmp(name, ".bss")) + break; + } + + if (i == shnum) { + fprintf(stderr, "Failed to find .bss section\n"); + exit(EXIT_FAILURE); + } + + datasz = shdr.sh_offset; + } + else if (e32_hdr.e_ident[EI_CLASS] == ELFCLASS64) { + const char *shstrtab, *name; + Elf64_Shdr shdr; + int i; + void *strtab; + + fseek(f_in, shoff, SEEK_SET); + + /* First find the strtab section */ + fseek(f_in, shstrndx * shentsize, SEEK_CUR); + fread(&shdr, sizeof(shdr), 1, f_in); + + strtab = malloc(shdr.sh_size); + if (!strtab) { + fprintf(stderr, "Failed to malloc strtab\n"); + exit(EXIT_FAILURE); + } + + fseek(f_in, shdr.sh_offset, SEEK_SET); + fread(strtab, shdr.sh_size, 1, f_in); + + /* Now search for the .bss section */ + fseek(f_in, shoff, SEEK_SET); + for (i = 0; i < shnum; i++) { + rv = fread(&shdr, sizeof(shdr), 1, f_in); + if (!rv) { + fprintf(stderr, "Failed to read section table\n"); + exit(EXIT_FAILURE); + } + + name = strtab + shdr.sh_name; + if (!strcmp(name, ".bss")) + break; + } + + if (i == shnum) { + fprintf(stderr, "Failed to find .bss section\n"); + exit(EXIT_FAILURE); + } + + datasz = shdr.sh_offset; + } + + buf = malloc(datasz); if (!buf) { perror("malloc"); exit(EXIT_FAILURE); } - write_header(f_out, entry, st.st_size, class); + write_header(f_out, entry, datasz, st.st_size, class); /* Write out the entire ELF shared object */ rewind(f_in); - rv = fread(buf, st.st_size, 1, f_in); + rv = fread(buf, datasz, 1, f_in); if (!rv && ferror(f_in)) { fprintf(stderr, "Failed to read all bytes from input\n"); exit(EXIT_FAILURE); } - fwrite(buf, st.st_size, rv, f_out); + fwrite(buf, datasz, rv, f_out); return 0; } diff --git a/efi/x86_64/syslinux.ld b/efi/x86_64/syslinux.ld index 3c8c7c34..95160bd7 100644 --- a/efi/x86_64/syslinux.ld +++ b/efi/x86_64/syslinux.ld @@ -128,10 +128,6 @@ SECTIONS *(.reloc) } - .comment : { - *(.commet) - } - .symtab : { *(.symtab) } @@ -172,5 +168,6 @@ SECTIONS /* Stuff we don't need... */ /DISCARD/ : { *(.eh_frame) + *(.comment) } } |