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; + } +}