From 9fcdfaf7ff456d3be94563b5c4339547b80a3f6f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Oct 2009 16:08:31 -0600 Subject: [PATCH] implement binaryToElf utility and use it instead of objcopy on Linux This is necessary because objcopy does not currently allow us to specify the alignment requirement for the .boot section used to store the boot image for AOT builds. This may be a problem for Windows as well, in which case we'll need to add a binaryToPE utility. --- makefile | 18 +++- src/binaryToElf.cpp | 240 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 src/binaryToElf.cpp diff --git a/makefile b/makefile index 06b9c791ee..58847aa29c 100644 --- a/makefile +++ b/makefile @@ -129,6 +129,8 @@ shared = -shared native-path = echo +binaryToElf = $(native-build)/binaryToElf + ifeq ($(arch),i386) object-arch = i386 object-format = elf32-i386 @@ -150,11 +152,14 @@ ifeq ($(platform),darwin) rdynamic = strip-all = -S -x binaryToMacho = $(native-build)/binaryToMacho + binaryToElf = so-suffix = .jnilib shared = -dynamiclib endif ifeq ($(platform),windows) + binaryToElf = + inc = "$(root)/win32/include" lib = "$(root)/win32/lib" @@ -626,11 +631,21 @@ $(static-library): $(vm-objects) $(jni-objects) $(vm-heapwalk-objects) $(bootimage-bin): $(bootimage-generator) $(<) $(classpath-build) $(@) -$(bootimage-object): $(bootimage-bin) $(binaryToMacho) +$(binaryToElf): $(src)/binaryToElf.cpp + $(cxx) $(^) $(call output,$(@)) + +# we would always use objcopy here except (1) it's not supported on +# Darwin, and (2) it won't let us specify per-section alignment +# requirements +$(bootimage-object): $(bootimage-bin) $(binaryToMacho) $(binaryToElf) @echo "creating $(@)" ifeq ($(platform),darwin) $(binaryToMacho) $(asm) $(<) __BOOT __boot \ __binary_bootimage_bin_start __binary_bootimage_bin_end > $(@) +else +ifeq ($(platform),linux) + $(binaryToElf) $(<) .boot \ + _binary_bootimage_bin_start _binary_bootimage_bin_end > $(@) else (wd=$$(pwd) && \ cd $(native-build) && \ @@ -639,6 +654,7 @@ else $(objcopy) --set-section-flags .boot=alloc,load,code "$${wd}/$(@).tmp" \ "$${wd}/$(@)") endif +endif $(gnu-object-dep): $(gnu-libraries) @mkdir -p $(build)/gnu-objects diff --git a/src/binaryToElf.cpp b/src/binaryToElf.cpp new file mode 100644 index 0000000000..aeb1459689 --- /dev/null +++ b/src/binaryToElf.cpp @@ -0,0 +1,240 @@ +/* Copyright (c) 2009, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "stdint.h" +#include "stdio.h" +#include "string.h" + +#include "sys/stat.h" +#include "sys/mman.h" +#include "fcntl.h" +#include "unistd.h" + +#include "elf.h" + +#ifdef __x86_64__ +# define FileHeader Elf64_Ehdr +# define SectionHeader Elf64_Shdr +# define Symbol Elf64_Sym +# define Class ELFCLASS64 +# define Machine EM_X86_64 +# define SYMBOL_INFO ELF64_ST_INFO +#else // not __x86_64__ +# define FileHeader Elf32_Ehdr +# define SectionHeader Elf32_Shdr +# define Symbol Elf32_Sym +# define Class ELFCLASS32 +# define Machine EM_386 +# define SYMBOL_INFO ELF32_ST_INFO +#endif // not __x86_64__ + +#define Data ELFDATA2LSB +#define OSABI ELFOSABI_SYSV + +namespace { + +void +writeObject(FILE* out, const uint8_t* data, unsigned size, + const char* sectionName, const char* startName, + const char* endName) +{ + const unsigned sectionCount = 5; + const unsigned symbolCount = 2; + + const unsigned sectionNameLength = strlen(sectionName) + 1; + const unsigned startNameLength = strlen(startName) + 1; + const unsigned endNameLength = strlen(endName) + 1; + + const char* const sectionStringTableName = ".shstrtab"; + const char* const stringTableName = ".strtab"; + const char* const symbolTableName = ".symtab"; + + const unsigned sectionStringTableNameLength + = strlen(sectionStringTableName) + 1; + const unsigned stringTableNameLength = strlen(stringTableName) + 1; + const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; + + const unsigned nullStringOffset = 0; + + const unsigned sectionStringTableNameOffset = nullStringOffset + 1; + const unsigned stringTableNameOffset + = sectionStringTableNameOffset + sectionStringTableNameLength; + const unsigned symbolTableNameOffset + = stringTableNameOffset + stringTableNameLength; + const unsigned sectionNameOffset + = symbolTableNameOffset + symbolTableNameLength; + const unsigned sectionStringTableLength + = sectionNameOffset + sectionNameLength; + + const unsigned startNameOffset = nullStringOffset + 1; + const unsigned endNameOffset = startNameOffset + startNameLength; + const unsigned stringTableLength = endNameOffset + endNameLength; + + const unsigned bodySectionNumber = 1; + const unsigned sectionStringTableSectionNumber = 2; + const unsigned stringTableSectionNumber = 3; + + FileHeader fileHeader; + fileHeader.e_ident[EI_MAG0] = ELFMAG0; + fileHeader.e_ident[EI_MAG1] = ELFMAG1; + fileHeader.e_ident[EI_MAG2] = ELFMAG2; + fileHeader.e_ident[EI_MAG3] = ELFMAG3; + fileHeader.e_ident[EI_CLASS] = Class; + fileHeader.e_ident[EI_DATA] = Data; + fileHeader.e_ident[EI_VERSION] = EV_CURRENT; + fileHeader.e_ident[EI_OSABI] = OSABI; + fileHeader.e_ident[EI_ABIVERSION] = 0; + fileHeader.e_type = ET_REL; + fileHeader.e_machine = Machine; + fileHeader.e_version = EV_CURRENT; + fileHeader.e_entry = 0; + fileHeader.e_phoff = 0; + fileHeader.e_shoff = sizeof(FileHeader); + fileHeader.e_flags = 0; + fileHeader.e_ehsize = sizeof(FileHeader); + fileHeader.e_phentsize = 0; + fileHeader.e_phnum = 0; + fileHeader.e_shentsize = sizeof(SectionHeader); + fileHeader.e_shnum = sectionCount; + fileHeader.e_shstrndx = sectionStringTableSectionNumber; + + SectionHeader nullSection; + memset(&nullSection, 0, sizeof(SectionHeader)); + + SectionHeader bodySection; + bodySection.sh_name = sectionNameOffset; + bodySection.sh_type = SHT_PROGBITS; + bodySection.sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR; + bodySection.sh_addr = 0; + bodySection.sh_offset = sizeof(FileHeader) + + (sizeof(SectionHeader) * sectionCount); + bodySection.sh_size = size; + bodySection.sh_link = 0; + bodySection.sh_info = 0; + bodySection.sh_addralign = sizeof(void*); + bodySection.sh_entsize = 0; + + SectionHeader sectionStringTableSection; + sectionStringTableSection.sh_name = sectionStringTableNameOffset; + sectionStringTableSection.sh_type = SHT_STRTAB; + sectionStringTableSection.sh_flags = 0; + sectionStringTableSection.sh_addr = 0; + sectionStringTableSection.sh_offset + = bodySection.sh_offset + bodySection.sh_size; + sectionStringTableSection.sh_size = sectionStringTableLength; + sectionStringTableSection.sh_link = 0; + sectionStringTableSection.sh_info = 0; + sectionStringTableSection.sh_addralign = 1; + sectionStringTableSection.sh_entsize = 0; + + SectionHeader stringTableSection; + stringTableSection.sh_name = stringTableNameOffset; + stringTableSection.sh_type = SHT_STRTAB; + stringTableSection.sh_flags = 0; + stringTableSection.sh_addr = 0; + stringTableSection.sh_offset = sectionStringTableSection.sh_offset + + sectionStringTableSection.sh_size; + stringTableSection.sh_size = stringTableLength; + stringTableSection.sh_link = 0; + stringTableSection.sh_info = 0; + stringTableSection.sh_addralign = 1; + stringTableSection.sh_entsize = 0; + + SectionHeader symbolTableSection; + symbolTableSection.sh_name = symbolTableNameOffset; + symbolTableSection.sh_type = SHT_SYMTAB; + symbolTableSection.sh_flags = 0; + symbolTableSection.sh_addr = 0; + symbolTableSection.sh_offset = stringTableSection.sh_offset + + stringTableSection.sh_size; + symbolTableSection.sh_size = sizeof(Symbol) * symbolCount; + symbolTableSection.sh_link = stringTableSectionNumber; + symbolTableSection.sh_info = 0; + symbolTableSection.sh_addralign = sizeof(void*); + symbolTableSection.sh_entsize = sizeof(Symbol); + + Symbol startSymbol; + startSymbol.st_name = startNameOffset; + startSymbol.st_value = 0; + startSymbol.st_size = 0; + startSymbol.st_info = SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE); + startSymbol.st_other = STV_DEFAULT; + startSymbol.st_shndx = bodySectionNumber; + + Symbol endSymbol; + endSymbol.st_name = endNameOffset; + endSymbol.st_value = 0; + endSymbol.st_size = 0; + endSymbol.st_info = SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE); + endSymbol.st_other = STV_DEFAULT; + endSymbol.st_shndx = bodySectionNumber; + + fwrite(&fileHeader, 1, sizeof(fileHeader), out); + fwrite(&nullSection, 1, sizeof(nullSection), out); + fwrite(&bodySection, 1, sizeof(bodySection), out); + fwrite(§ionStringTableSection, 1, sizeof(sectionStringTableSection), + out); + fwrite(&stringTableSection, 1, sizeof(stringTableSection), out); + fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out); + + fwrite(data, 1, size, out); + + fputc(0, out); + fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); + fwrite(stringTableName, 1, stringTableNameLength, out); + fwrite(symbolTableName, 1, symbolTableNameLength, out); + fwrite(sectionName, 1, sectionNameLength, out); + + fputc(0, out); + fwrite(startName, 1, startNameLength, out); + fwrite(endName, 1, endNameLength, out); + + fwrite(&startSymbol, 1, sizeof(startSymbol), out); + fwrite(&endSymbol, 1, sizeof(endSymbol), out); +} + +} // namespace + +int +main(int argc, const char** argv) +{ + if (argc != 5) { + fprintf(stderr, + "usage: %s
" + "\n", + argv[0]); + return -1; + } + + uint8_t* data = 0; + unsigned size; + int fd = open(argv[1], O_RDONLY); + if (fd != -1) { + struct stat s; + int r = fstat(fd, &s); + if (r != -1) { + data = static_cast + (mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); + size = s.st_size; + } + close(fd); + } + + if (data) { + writeObject(stdout, data, size, argv[2], argv[3], argv[4]); + + munmap(data, size); + + return 0; + } else { + perror(argv[0]); + return -1; + } +}