From 9c308f751c91f37dd7a0bed81f380436bb965cc0 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 24 Apr 2012 16:17:52 -0600 Subject: [PATCH 1/6] refactor binaryToObject, to better support (eventually) putting symbols for compiled code in objects --- makefile | 34 +- src/binaryToObject/elf.cpp | 606 ++++++++++++++++---------------- src/binaryToObject/endianness.h | 106 ++++-- src/binaryToObject/mach-o.cpp | 568 ++++++++++++++---------------- src/binaryToObject/main.cpp | 117 ++---- src/binaryToObject/pe.cpp | 148 ++++---- src/binaryToObject/tools.cpp | 62 ++++ src/binaryToObject/tools.h | 90 +++++ 8 files changed, 932 insertions(+), 799 deletions(-) create mode 100644 src/binaryToObject/tools.cpp create mode 100644 src/binaryToObject/tools.h diff --git a/makefile b/makefile index 4a481f9c7b..7389967ddb 100755 --- a/makefile +++ b/makefile @@ -334,9 +334,6 @@ ifeq ($(platform),darwin) x := $(error "couldn't find SDK for iOS version") endif - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif flags = -arch armv7 -isysroot \ $(sdk-dir)/iPhoneOS$(ios-version).sdk/ openjdk-extra-cflags += $(flags) @@ -345,10 +342,11 @@ ifeq ($(platform),darwin) lflags += $(flags) endif + ifeq ($(build-arch),powerpc) + converter-cflags += -DBIG_ENDIAN + endif + ifeq ($(arch),powerpc) - ifneq (,$(filter i386 x86_64 arm,$(build-arch))) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} @@ -356,9 +354,6 @@ ifeq ($(platform),darwin) endif ifeq ($(arch),i386) - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} @@ -366,9 +361,6 @@ ifeq ($(platform),darwin) endif ifeq ($(arch),x86_64) - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch x86_64 cflags += -arch x86_64 asmflags += -arch x86_64 @@ -614,6 +606,9 @@ driver-object = $(build)/main.o driver-dynamic-objects = \ $(build)/main-dynamic.o +gdb-plugin-object = $(build)/gdb-plugin.o +gdb-plugin-source = $(src)/gdb-plugin.cpp + boot-source = $(src)/boot.cpp boot-object = $(build)/boot.o @@ -630,8 +625,8 @@ generator = $(build)/generator converter-objects = \ $(build)/binaryToObject-main.o \ - $(build)/binaryToObject-elf64.o \ - $(build)/binaryToObject-elf32.o \ + $(build)/binaryToObject-tools.o \ + $(build)/binaryToObject-elf.o \ $(build)/binaryToObject-mach-o64.o \ $(build)/binaryToObject-mach-o32.o \ $(build)/binaryToObject-pe.o @@ -828,6 +823,9 @@ $(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(driver-object): $(driver-source) $(compile-object) +$(gdb-plugin-object): $(gdb-plugin-source) + $(compile-object) + $(build)/main-dynamic.o: $(driver-source) @echo "compiling $(@)" @mkdir -p $(dir $(@)) @@ -843,11 +841,11 @@ $(boot-javahome-object): $(src)/boot-javahome.cpp $(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp $(build-cxx) $(converter-cflags) -c $(^) -o $(@) -$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) +$(build)/binaryToObject-tools.o: $(src)/binaryToObject/tools.cpp + $(build-cxx) $(converter-cflags) -c $(^) -o $(@) -$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@) +$(build)/binaryToObject-elf.o: $(src)/binaryToObject/elf.cpp + $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) $(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index bdfdce51c3..51c7d7c587 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -8,12 +8,14 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include #include "endianness.h" +#include "tools.h" + #define EI_NIDENT 16 #define EI_MAG0 0 @@ -62,344 +64,340 @@ #define STV_DEFAULT 0 -#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) -#define ELF32_ST_INFO(bind, type) ELF64_ST_INFO((bind), (type)) - -#if (BITS_PER_WORD == 64) -# define FileHeader Elf64_Ehdr -# define SectionHeader Elf64_Shdr -# define Symbol Elf64_Sym -# define Class ELFCLASS64 -# define SYMBOL_INFO ELF64_ST_INFO -#elif (BITS_PER_WORD == 32) -# define FileHeader Elf32_Ehdr -# define SectionHeader Elf32_Shdr -# define Symbol Elf32_Sym -# define Class ELFCLASS32 -# define SYMBOL_INFO ELF32_ST_INFO -#else -# error -#endif +#define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) #define OSABI ELFOSABI_SYSV namespace { -typedef uint16_t Elf64_Half; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Addr; -typedef uint64_t Elf64_Xword; -typedef uint16_t Elf64_Section; -typedef uint64_t Elf64_Off; +using namespace avian::tools; -struct Elf64_Ehdr { - unsigned char e_ident[EI_NIDENT]; - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; - Elf64_Off e_phoff; - Elf64_Off e_shoff; - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; +template +struct ElfTypes { + typedef uint16_t Half; + typedef uint32_t Word; + typedef AddrTy Addr; + typedef uint64_t Xword; + typedef uint16_t Section; + typedef AddrTy Off; + typedef AddrTy XFlags; + static const unsigned BytesPerWord = sizeof(AddrTy); }; -struct Elf64_Shdr { - Elf64_Word sh_name; - Elf64_Word sh_type; - Elf64_Xword sh_flags; - Elf64_Addr sh_addr; - Elf64_Off sh_offset; - Elf64_Xword sh_size; - Elf64_Word sh_link; - Elf64_Word sh_info; - Elf64_Xword sh_addralign; - Elf64_Xword sh_entsize; -}; +template +struct Symbol_Ty; -struct Elf64_Sym { - Elf64_Word st_name; +template<> +struct Symbol_Ty { + typedef ElfTypes Elf; + + Elf::Word st_name; unsigned char st_info; unsigned char st_other; - Elf64_Section st_shndx; - Elf64_Addr st_value; - Elf64_Xword st_size; + Elf::Section st_shndx; + Elf::Addr st_value; + Elf::Xword st_size; }; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Word; -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf32_Xword; -typedef uint16_t Elf32_Section; -typedef uint32_t Elf32_Off; +template<> +struct Symbol_Ty { + typedef ElfTypes Elf; -struct Elf32_Ehdr { - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -}; - -struct Elf32_Shdr { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -}; - -struct Elf32_Sym { - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; + Elf::Word st_name; + Elf::Addr st_value; + Elf::Word st_size; unsigned char st_info; unsigned char st_other; - Elf32_Section st_shndx; + Elf::Section st_shndx; }; -void -writeObject(const uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* sectionName, unsigned sectionFlags, - unsigned alignment, int machine, int encoding) -{ - const unsigned sectionCount = 5; - const unsigned symbolCount = 2; +using avian::endian::Endianness; - const unsigned sectionNameLength = strlen(sectionName) + 1; - const unsigned startNameLength = strlen(startName) + 1; - const unsigned endNameLength = strlen(endName) + 1; +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny - const char* const sectionStringTableName = ".shstrtab"; - const char* const stringTableName = ".strtab"; - const char* const symbolTableName = ".symtab"; +template +class ElfPlatform : public Platform { +public: - const unsigned sectionStringTableNameLength - = strlen(sectionStringTableName) + 1; - const unsigned stringTableNameLength = strlen(stringTableName) + 1; - const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; + typedef ElfTypes Elf; + static const unsigned Class = Elf::BytesPerWord / 4; - const unsigned nullStringOffset = 0; + struct FileHeader { + unsigned char e_ident[EI_NIDENT]; + typename Elf::Half e_type; + typename Elf::Half e_machine; + typename Elf::Word e_version; + typename Elf::Addr e_entry; + typename Elf::Off e_phoff; + typename Elf::Off e_shoff; + typename Elf::Word e_flags; + typename Elf::Half e_ehsize; + typename Elf::Half e_phentsize; + typename Elf::Half e_phnum; + typename Elf::Half e_shentsize; + typename Elf::Half e_shnum; + typename Elf::Half e_shstrndx; + }; - 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; + struct SectionHeader { + typename Elf::Word sh_name; + typename Elf::Word sh_type; + typename Elf::XFlags sh_flags; + typename Elf::Addr sh_addr; + typename Elf::Off sh_offset; + typename Elf::Off sh_size; + typename Elf::Word sh_link; + typename Elf::Word sh_info; + typename Elf::Addr sh_addralign; + typename Elf::Off sh_entsize; + }; - const unsigned startNameOffset = nullStringOffset + 1; - const unsigned endNameOffset = startNameOffset + startNameLength; - const unsigned stringTableLength = endNameOffset + endNameLength; + typedef Symbol_Ty Symbol; - const unsigned bodySectionNumber = 1; - const unsigned sectionStringTableSectionNumber = 2; - const unsigned stringTableSectionNumber = 3; + class ElfObjectWriter : public ObjectWriter { + public: - FileHeader fileHeader; - memset(&fileHeader, 0, sizeof(FileHeader)); - fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0); - fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1); - fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2); - fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3); - fileHeader.e_ident[EI_CLASS] = V1(Class); - fileHeader.e_ident[EI_DATA] = V1(encoding); - fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT); - fileHeader.e_ident[EI_OSABI] = V1(OSABI); - fileHeader.e_ident[EI_ABIVERSION] = V1(0); - fileHeader.e_type = V2(ET_REL); - fileHeader.e_machine = V2(machine); - fileHeader.e_version = V4(EV_CURRENT); - fileHeader.e_entry = VW(0); - fileHeader.e_phoff = VW(0); - fileHeader.e_shoff = VW(sizeof(FileHeader)); - fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); - fileHeader.e_ehsize = V2(sizeof(FileHeader)); - fileHeader.e_phentsize = V2(0); - fileHeader.e_phnum = V2(0); - fileHeader.e_shentsize = V2(sizeof(SectionHeader)); - fileHeader.e_shnum = V2(sectionCount); - fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber); + PlatformInfo::Architecture arch; - SectionHeader nullSection; - memset(&nullSection, 0, sizeof(SectionHeader)); + ElfObjectWriter(PlatformInfo::Architecture arch): + arch(arch) {} - SectionHeader bodySection; - bodySection.sh_name = V4(sectionNameOffset); - bodySection.sh_type = V4(SHT_PROGBITS); - bodySection.sh_flags = VW(sectionFlags); - bodySection.sh_addr = VW(0); - unsigned bodySectionOffset - = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); - bodySection.sh_offset = VW(bodySectionOffset); - unsigned bodySectionSize = size; - bodySection.sh_size = VW(bodySectionSize); - bodySection.sh_link = V4(0); - bodySection.sh_info = V4(0); - bodySection.sh_addralign = VW(alignment); - bodySection.sh_entsize = VW(0); + void writeObject(const uint8_t* data, unsigned size, FILE* out, + const char* startName, const char* endName, + const char* sectionName, unsigned sectionFlags, + unsigned alignment, int machine, int encoding) + { + const unsigned sectionCount = 5; + const unsigned symbolCount = 2; - SectionHeader sectionStringTableSection; - sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); - sectionStringTableSection.sh_type = V4(SHT_STRTAB); - sectionStringTableSection.sh_flags = VW(0); - sectionStringTableSection.sh_addr = VW(0); - unsigned sectionStringTableSectionOffset - = bodySectionOffset + bodySectionSize; - sectionStringTableSection.sh_offset = VW(sectionStringTableSectionOffset); - unsigned sectionStringTableSectionSize = sectionStringTableLength; - sectionStringTableSection.sh_size = VW(sectionStringTableSectionSize); - sectionStringTableSection.sh_link = V4(0); - sectionStringTableSection.sh_info = V4(0); - sectionStringTableSection.sh_addralign = VW(1); - sectionStringTableSection.sh_entsize = VW(0); + const unsigned sectionNameLength = strlen(sectionName) + 1; + const unsigned startNameLength = strlen(startName) + 1; + const unsigned endNameLength = strlen(endName) + 1; - SectionHeader stringTableSection; - stringTableSection.sh_name = V4(stringTableNameOffset); - stringTableSection.sh_type = V4(SHT_STRTAB); - stringTableSection.sh_flags = VW(0); - stringTableSection.sh_addr = VW(0); - unsigned stringTableSectionOffset - = sectionStringTableSectionOffset + sectionStringTableSectionSize; - stringTableSection.sh_offset = VW(stringTableSectionOffset); - unsigned stringTableSectionSize = stringTableLength; - stringTableSection.sh_size = VW(stringTableSectionSize); - stringTableSection.sh_link = V4(0); - stringTableSection.sh_info = V4(0); - stringTableSection.sh_addralign = VW(1); - stringTableSection.sh_entsize = VW(0); + const char* const sectionStringTableName = ".shstrtab"; + const char* const stringTableName = ".strtab"; + const char* const symbolTableName = ".symtab"; - SectionHeader symbolTableSection; - symbolTableSection.sh_name = V4(symbolTableNameOffset); - symbolTableSection.sh_type = V4(SHT_SYMTAB); - symbolTableSection.sh_flags = VW(0); - symbolTableSection.sh_addr = VW(0); - unsigned symbolTableSectionOffset - = stringTableSectionOffset + stringTableSectionSize; - symbolTableSection.sh_offset = VW(symbolTableSectionOffset); - unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; - symbolTableSection.sh_size = VW(symbolTableSectionSize); - symbolTableSection.sh_link = V4(stringTableSectionNumber); - symbolTableSection.sh_info = V4(0); - symbolTableSection.sh_addralign = VW(BITS_PER_WORD / 8); - symbolTableSection.sh_entsize = VW(sizeof(Symbol)); + const unsigned sectionStringTableNameLength + = strlen(sectionStringTableName) + 1; + const unsigned stringTableNameLength = strlen(stringTableName) + 1; + const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; - Symbol startSymbol; - startSymbol.st_name = V4(startNameOffset); - startSymbol.st_value = VW(0); - startSymbol.st_size = VW(0); - startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - startSymbol.st_other = V1(STV_DEFAULT); - startSymbol.st_shndx = V2(bodySectionNumber); + const unsigned nullStringOffset = 0; - Symbol endSymbol; - endSymbol.st_name = V4(endNameOffset); - endSymbol.st_value = VW(size); - endSymbol.st_size = VW(0); - endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - endSymbol.st_other = V1(STV_DEFAULT); - endSymbol.st_shndx = V2(bodySectionNumber); + 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; - 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); + const unsigned startNameOffset = nullStringOffset + 1; + const unsigned endNameOffset = startNameOffset + startNameLength; + const unsigned stringTableLength = endNameOffset + endNameLength; - fwrite(data, 1, size, out); + const unsigned bodySectionNumber = 1; + const unsigned sectionStringTableSectionNumber = 2; + const unsigned stringTableSectionNumber = 3; - fputc(0, out); - fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); - fwrite(stringTableName, 1, stringTableNameLength, out); - fwrite(symbolTableName, 1, symbolTableNameLength, out); - fwrite(sectionName, 1, sectionNameLength, out); + FileHeader fileHeader; + memset(&fileHeader, 0, sizeof(FileHeader)); + fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0); + fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1); + fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2); + fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3); + fileHeader.e_ident[EI_CLASS] = V1(Class); + fileHeader.e_ident[EI_DATA] = V1(encoding); + fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT); + fileHeader.e_ident[EI_OSABI] = V1(OSABI); + fileHeader.e_ident[EI_ABIVERSION] = V1(0); + fileHeader.e_type = V2(ET_REL); + fileHeader.e_machine = V2(machine); + fileHeader.e_version = V4(EV_CURRENT); + fileHeader.e_entry = VANY(static_cast(0)); + fileHeader.e_phoff = VANY(static_cast(0)); + fileHeader.e_shoff = VANY(static_cast(sizeof(FileHeader))); + fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); + fileHeader.e_ehsize = V2(sizeof(FileHeader)); + fileHeader.e_phentsize = V2(0); + fileHeader.e_phnum = V2(0); + fileHeader.e_shentsize = V2(sizeof(SectionHeader)); + fileHeader.e_shnum = V2(sectionCount); + fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber); - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + SectionHeader nullSection; + memset(&nullSection, 0, sizeof(SectionHeader)); + + SectionHeader bodySection; + bodySection.sh_name = V4(sectionNameOffset); + bodySection.sh_type = V4(SHT_PROGBITS); + bodySection.sh_flags = VANY(static_cast(sectionFlags)); + bodySection.sh_addr = VANY(static_cast(0)); + unsigned bodySectionOffset + = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); + bodySection.sh_offset = VANY(static_cast(bodySectionOffset)); + unsigned bodySectionSize = size; + bodySection.sh_size = VANY(static_cast(bodySectionSize)); + bodySection.sh_link = V4(0); + bodySection.sh_info = V4(0); + bodySection.sh_addralign = VANY(static_cast(alignment)); + bodySection.sh_entsize = VANY(static_cast(0)); + + SectionHeader sectionStringTableSection; + sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); + sectionStringTableSection.sh_type = V4(SHT_STRTAB); + sectionStringTableSection.sh_flags = VANY(static_cast(0)); + sectionStringTableSection.sh_addr = VANY(static_cast(0)); + unsigned sectionStringTableSectionOffset + = bodySectionOffset + bodySectionSize; + sectionStringTableSection.sh_offset = VANY(static_cast(sectionStringTableSectionOffset)); + unsigned sectionStringTableSectionSize = sectionStringTableLength; + sectionStringTableSection.sh_size = VANY(static_cast(sectionStringTableSectionSize)); + sectionStringTableSection.sh_link = V4(0); + sectionStringTableSection.sh_info = V4(0); + sectionStringTableSection.sh_addralign = VANY(static_cast(1)); + sectionStringTableSection.sh_entsize = VANY(static_cast(0)); + + SectionHeader stringTableSection; + stringTableSection.sh_name = V4(stringTableNameOffset); + stringTableSection.sh_type = V4(SHT_STRTAB); + stringTableSection.sh_flags = VANY(static_cast(0)); + stringTableSection.sh_addr = VANY(static_cast(0)); + unsigned stringTableSectionOffset + = sectionStringTableSectionOffset + sectionStringTableSectionSize; + stringTableSection.sh_offset = VANY(static_cast(stringTableSectionOffset)); + unsigned stringTableSectionSize = stringTableLength; + stringTableSection.sh_size = VANY(static_cast(stringTableSectionSize)); + stringTableSection.sh_link = V4(0); + stringTableSection.sh_info = V4(0); + stringTableSection.sh_addralign = VANY(static_cast(1)); + stringTableSection.sh_entsize = VANY(static_cast(0)); + + SectionHeader symbolTableSection; + symbolTableSection.sh_name = V4(symbolTableNameOffset); + symbolTableSection.sh_type = V4(SHT_SYMTAB); + symbolTableSection.sh_flags = VANY(static_cast(0)); + symbolTableSection.sh_addr = VANY(static_cast(0)); + unsigned symbolTableSectionOffset + = stringTableSectionOffset + stringTableSectionSize; + symbolTableSection.sh_offset = VANY(static_cast(symbolTableSectionOffset)); + unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; + symbolTableSection.sh_size = VANY(static_cast(symbolTableSectionSize)); + symbolTableSection.sh_link = V4(stringTableSectionNumber); + symbolTableSection.sh_info = V4(0); + symbolTableSection.sh_addralign = VANY(static_cast(Elf::BytesPerWord)); + symbolTableSection.sh_entsize = VANY(static_cast(sizeof(Symbol))); + + Symbol startSymbol; + startSymbol.st_name = V4(startNameOffset); + startSymbol.st_value = VANY(static_cast(0)); + startSymbol.st_size = VANY(static_cast(0)); + startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + startSymbol.st_other = V1(STV_DEFAULT); + startSymbol.st_shndx = V2(bodySectionNumber); + + Symbol endSymbol; + endSymbol.st_name = V4(endNameOffset); + endSymbol.st_value = VANY(static_cast(size)); + endSymbol.st_size = VANY(static_cast(0)); + endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + endSymbol.st_other = V1(STV_DEFAULT); + endSymbol.st_shndx = V2(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); + } + + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) + { + int machine; + int encoding; + if (arch == PlatformInfo::x86_64) { + machine = EM_X86_64; + encoding = ELFDATA2LSB; + } else if (arch == PlatformInfo::x86) { + machine = EM_386; + encoding = ELFDATA2LSB; + } else if (arch == PlatformInfo::Arm) { + machine = EM_ARM; + encoding = ELFDATA2LSB; + } else if (arch == PlatformInfo::PowerPC) { + machine = EM_PPC; + encoding = ELFDATA2MSB; + } else { + fprintf(stderr, "unsupported architecture: %s\n", arch); + return false; + } + + const char* sectionName; + unsigned sectionFlags = SHF_ALLOC; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + sectionName = ".rwx"; + sectionFlags |= SHF_WRITE | SHF_EXECINSTR; + } else { + sectionName = ".data"; + sectionFlags |= SHF_WRITE; + } + } else if (accessFlags & Executable) { + sectionName = ".text"; + sectionFlags |= SHF_EXECINSTR; + } else { + sectionName = ".rodata"; + } + + writeObject(data, size, out, startName, endName, sectionName, sectionFlags, + alignment, machine, encoding); + + return true; + } + + virtual void dispose() { + delete this; + } + }; + + ElfPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Linux, arch)) {} + + virtual ObjectWriter* makeObjectWriter() { + return new ElfObjectWriter(info.arch); + } +}; + +ElfPlatform elfx86Platform(PlatformInfo::x86); +ElfPlatform elfArmPlatform(PlatformInfo::Arm); +ElfPlatform elfPowerPCPlatform(PlatformInfo::PowerPC); +ElfPlatform elfx86_64Platform(PlatformInfo::x86_64); - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); -} } // namespace - -#define MACRO_MAKE_NAME(a, b, c) a##b##c -#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c) - -namespace binaryToObject { - -bool -MAKE_NAME(writeElf, BITS_PER_WORD, Object) - (uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - int machine; - int encoding; - if (strcmp(architecture, "x86_64") == 0) { - machine = EM_X86_64; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "i386") == 0) { - machine = EM_386; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "arm") == 0) { - machine = EM_ARM; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "powerpc") == 0) { - machine = EM_PPC; - encoding = ELFDATA2MSB; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } - - const char* sectionName; - unsigned sectionFlags = SHF_ALLOC; - if (writable) { - if (executable) { - sectionName = ".rwx"; - sectionFlags |= SHF_WRITE | SHF_EXECINSTR; - } else { - sectionName = ".data"; - sectionFlags |= SHF_WRITE; - } - } else if (executable) { - sectionName = ".text"; - sectionFlags |= SHF_EXECINSTR; - } else { - sectionName = ".rodata"; - } - - writeObject(data, size, out, startName, endName, sectionName, sectionFlags, - alignment, machine, encoding); - - return true; -} - -} // namespace binaryToObject diff --git a/src/binaryToObject/endianness.h b/src/binaryToObject/endianness.h index 46cfcd8b46..36c5675bac 100644 --- a/src/binaryToObject/endianness.h +++ b/src/binaryToObject/endianness.h @@ -1,38 +1,80 @@ -#ifndef ENDIANNESS_H -#define ENDIANNESS_H +/* Copyright (c) 2008-2011, Avian Contributors -#define V1(v) (v) + 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. -#ifdef OPPOSITE_ENDIAN -# define V2(v) \ - ((((v) >> 8) & 0xFF) | \ - (((v) << 8))) -# define V4(v) \ - ((((v) >> 24) & 0x000000FF) | \ - (((v) >> 8) & 0x0000FF00) | \ - (((v) << 8) & 0x00FF0000) | \ - (((v) << 24))) -# define V8(v) \ - (((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | \ - ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | \ - ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \ - ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) | \ - ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) | \ - ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) | \ - ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) | \ - ((static_cast(v) << 56))) + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_ENDIANNESS_H +#define AVIAN_ENDIANNESS_H + +namespace avian { + +namespace endian { + +#ifndef BIG_ENDIAN +const bool LittleEndian = true; #else -# define V2(v) (v) -# define V4(v) (v) -# define V8(v) (v) +const bool LittleEndian = false; #endif -#if (BITS_PER_WORD == 64) -# define VW(v) V8(v) -#elif (BITS_PER_WORD == 32) -# define VW(v) V4(v) -#else -# error -#endif +template +class Endianness { +public: + static inline uint8_t v1(uint8_t v) { + return v; + } -#endif//ENDIANNESS_H + static inline uint16_t v2(uint16_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return ((v >> 8) & 0xFF) | (v << 8); + } + } + + static inline uint32_t v4(uint32_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return + ((v >> 24) & 0x000000FF) | + ((v >> 8) & 0x0000FF00) | + ((v << 8) & 0x00FF0000) | + ((v << 24)); + } + } + + static inline uint32_t vAny(uint32_t v) { + return v4(v); + } + + static inline uint64_t v8(uint64_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return + ((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | + ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | + ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) | + ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) | + ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) | + ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) | + ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) | + ((static_cast(v) << 56)); + } + } + + static inline uint64_t vAny(uint64_t v) { + return v8(v); + } +}; + +} // namespace endian + +} // namespace avian + +#endif // AVIAN_ENDIANNESS_H diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 8b37e85aaf..6aab90a0b1 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -8,19 +8,19 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include #include "endianness.h" +#include "tools.h" + #define MH_MAGIC_64 0xfeedfacf #define MH_MAGIC 0xfeedface #define MH_OBJECT 1 -#define LC_SEGMENT_64 0x19 -#define LC_SEGMENT 1 #define LC_SYMTAB 2 #define S_REGULAR 0 @@ -40,322 +40,294 @@ #define CPU_SUBTYPE_POWERPC_ALL 0 #define CPU_SUBTYPE_ARM_V7 9 -#if (BITS_PER_WORD == 64) -# define Magic MH_MAGIC_64 -# define Segment LC_SEGMENT_64 -# define FileHeader mach_header_64 -# define SegmentCommand segment_command_64 -# define Section section_64 -# define NList struct nlist_64 -#elif (BITS_PER_WORD == 32) -# define Magic MH_MAGIC -# define Segment LC_SEGMENT -# define FileHeader mach_header -# define SegmentCommand segment_command -# define Section section -# define NList struct nlist -#else -# error -#endif - namespace { +using namespace avian::tools; + typedef int cpu_type_t; typedef int cpu_subtype_t; typedef int vm_prot_t; -struct mach_header_64 { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; - uint32_t reserved; -}; +using avian::endian::Endianness; -struct segment_command_64 { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint64_t vmaddr; - uint64_t vmsize; - uint64_t fileoff; - uint64_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; -}; +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny -struct section_64 { - char sectname[16]; - char segname[16]; - uint64_t addr; - uint64_t size; - uint32_t offset; - uint32_t align; - uint32_t reloff; - uint32_t nreloc; - uint32_t flags; - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; -}; +template +class MachOPlatform : public Platform { +public: -struct nlist_64 { - union { - uint32_t n_strx; - } n_un; - uint8_t n_type; - uint8_t n_sect; - uint16_t n_desc; - uint64_t n_value; -}; + struct FileHeader { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; -struct mach_header { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; -}; - -struct segment_command { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint32_t vmaddr; - uint32_t vmsize; - uint32_t fileoff; - uint32_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; -}; - -struct section { - char sectname[16]; - char segname[16]; - uint32_t addr; - uint32_t size; - uint32_t offset; - uint32_t align; - uint32_t reloff; - uint32_t nreloc; - uint32_t flags; - uint32_t reserved1; - uint32_t reserved2; -}; - -struct symtab_command { - uint32_t cmd; - uint32_t cmdsize; - uint32_t symoff; - uint32_t nsyms; - uint32_t stroff; - uint32_t strsize; -}; - -struct nlist { - union { - int32_t n_strx; - } n_un; - uint8_t n_type; - uint8_t n_sect; - int16_t n_desc; - uint32_t n_value; -}; - -inline unsigned -pad(unsigned n) -{ - return (n + ((BITS_PER_WORD / 8) - 1)) & ~((BITS_PER_WORD / 8) - 1); -} - -inline unsigned -log(unsigned n) -{ - unsigned r = 0; - for (unsigned i = 1; i < n; ++r) i <<= 1; - return r; -} - -void -writeObject(const uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* segmentName, const char* sectionName, - unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) -{ - unsigned startNameLength = strlen(startName) + 1; - unsigned endNameLength = strlen(endName) + 1; - - FileHeader header = { - V4(Magic), // magic - V4(cpuType), - V4(cpuSubType), - V4(MH_OBJECT), // filetype, - V4(2), // ncmds - V4(sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // sizeofcmds - V4(0) // flags + union { + uint32_t flags; + AddrTy flagsAndMaybeReserved; + }; }; - SegmentCommand segment = { - V4(Segment), // cmd - V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize - "", // segname - VW(0), // vmaddr - VW(pad(size)), // vmsize - VW(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // fileoff - VW(pad(size)), // filesize - V4(7), // maxprot - V4(7), // initprot - V4(1), // nsects - V4(0) // flags + + struct SegmentCommand { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + AddrTy vmaddr; + AddrTy vmsize; + AddrTy fileoff; + AddrTy filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; }; - strncpy(segment.segname, segmentName, sizeof(segment.segname)); - - Section sect = { - "", // sectname - "", // segname - VW(0), // addr - VW(pad(size)), // size - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // offset - V4(log(alignment)), // align - V4(0), // reloff - V4(0), // nreloc - V4(S_REGULAR), // flags - V4(0), // reserved1 - V4(0), // reserved2 + struct Section { + char sectname[16]; + char segname[16]; + AddrTy addr; + AddrTy size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + AddrTy reserved2AndMaybe3; }; - strncpy(sect.segname, segmentName, sizeof(sect.segname)); - strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); - - symtab_command symbolTable = { - V4(LC_SYMTAB), // cmd - V4(sizeof(symtab_command)), // cmdsize - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command) - + pad(size)), // symoff - V4(2), // nsyms - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command) - + pad(size) - + (sizeof(NList) * 2)), // stroff - V4(1 + startNameLength + endNameLength), // strsize + struct NList { + union { + uint32_t n_strx; + } n_un; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + AddrTy n_value; }; - NList symbolList[] = { + struct SymtabCommand { + uint32_t cmd; + uint32_t cmdsize; + uint32_t symoff; + uint32_t nsyms; + uint32_t stroff; + uint32_t strsize; + }; + + static const unsigned BytesPerWord = sizeof(AddrTy); + static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1; + static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface; + + static inline unsigned + pad(unsigned n) + { + return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1); + } + + static inline unsigned + log(unsigned n) + { + unsigned r = 0; + for (unsigned i = 1; i < n; ++r) i <<= 1; + return r; + } + + class MachOObjectWriter : public ObjectWriter { + public: + + PlatformInfo::Architecture arch; + + MachOObjectWriter(PlatformInfo::Architecture arch): + arch(arch) {} + + void writeObject(const uint8_t* data, unsigned size, FILE* out, + const char* startName, const char* endName, + const char* segmentName, const char* sectionName, + unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) { - V4(1), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VW(0) // n_value - }, + unsigned startNameLength = strlen(startName) + 1; + unsigned endNameLength = strlen(endName) + 1; + + FileHeader header = { + V4(Magic), // magic + V4(cpuType), + V4(cpuSubType), + V4(MH_OBJECT), // filetype, + V4(2), // ncmds + V4(sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // sizeofcmds + V4(0) // flags + }; + + SegmentCommand segment = { + V4(Segment), // cmd + V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize + "", // segname + VANY(static_cast(0)), // vmaddr + VANY(static_cast(pad(size))), // vmsize + VANY(static_cast(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand))), // fileoff + VANY(static_cast(pad(size))), // filesize + V4(7), // maxprot + V4(7), // initprot + V4(1), // nsects + V4(0) // flags + }; + + strncpy(segment.segname, segmentName, sizeof(segment.segname)); + + Section sect = { + "", // sectname + "", // segname + VANY(static_cast(0)), // addr + VANY(static_cast(pad(size))), // size + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // offset + V4(log(alignment)), // align + V4(0), // reloff + V4(0), // nreloc + V4(S_REGULAR), // flags + V4(0), // reserved1 + V4(0), // reserved2 + }; + + strncpy(sect.segname, segmentName, sizeof(sect.segname)); + strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); + + SymtabCommand symbolTable = { + V4(LC_SYMTAB), // cmd + V4(sizeof(SymtabCommand)), // cmdsize + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + pad(size)), // symoff + V4(2), // nsyms + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + pad(size) + + (sizeof(NList) * 2)), // stroff + V4(1 + startNameLength + endNameLength), // strsize + }; + + NList symbolList[] = { + { + V4(1), // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(0)) // n_value + }, + { + V4(1 + startNameLength), // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(size)) // n_value + } + }; + + fwrite(&header, 1, sizeof(header), out); + fwrite(&segment, 1, sizeof(segment), out); + fwrite(§, 1, sizeof(sect), out); + fwrite(&symbolTable, 1, sizeof(symbolTable), out); + + fwrite(data, 1, size, out); + for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + + fwrite(&symbolList, 1, sizeof(symbolList), out); + + fputc(0, out); + fwrite(startName, 1, startNameLength, out); + fwrite(endName, 1, endNameLength, out); + } + + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) { - V4(1 + startNameLength), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VW(size) // n_value + + cpu_type_t cpuType; + cpu_subtype_t cpuSubType; + if (arch == PlatformInfo::x86_64) { + cpuType = CPU_TYPE_X86_64; + cpuSubType = CPU_SUBTYPE_X86_64_ALL; + } else if (arch == PlatformInfo::x86) { + cpuType = CPU_TYPE_I386; + cpuSubType = CPU_SUBTYPE_I386_ALL; + } else if (arch == PlatformInfo::PowerPC) { + cpuType = CPU_TYPE_POWERPC; + cpuSubType = CPU_SUBTYPE_POWERPC_ALL; + } else if (arch == PlatformInfo::Arm) { + cpuType = CPU_TYPE_ARM; + cpuSubType = CPU_SUBTYPE_ARM_V7; + } else { + fprintf(stderr, "unsupported architecture: %d\n", arch); + return false; + } + + const char* segmentName; + const char* sectionName; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + segmentName = "__RWX"; + sectionName = "__rwx"; + } else { + segmentName = "__DATA"; + sectionName = "__data"; + } + } else { + segmentName = "__TEXT"; + sectionName = "__text"; + } + + unsigned startNameLength = strlen(startName); + char myStartName[startNameLength + 2]; + myStartName[0] = '_'; + memcpy(myStartName + 1, startName, startNameLength + 1); + + unsigned endNameLength = strlen(endName); + char myEndName[endNameLength + 2]; + myEndName[0] = '_'; + memcpy(myEndName + 1, endName, endNameLength + 1); + + writeObject(data, size, out, myStartName, myEndName, segmentName, + sectionName, alignment, cpuType, cpuSubType); + + return true; + } + + virtual void dispose() { + delete this; } }; + + MachOPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {} - fwrite(&header, 1, sizeof(header), out); - fwrite(&segment, 1, sizeof(segment), out); - fwrite(§, 1, sizeof(sect), out); - fwrite(&symbolTable, 1, sizeof(symbolTable), out); + virtual ObjectWriter* makeObjectWriter() { + return new MachOObjectWriter(info.arch); + } +}; - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); - - fwrite(&symbolList, 1, sizeof(symbolList), out); - - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); -} +MachOPlatform darwinx86Platform(PlatformInfo::x86); +MachOPlatform darwinArmPlatform(PlatformInfo::Arm); +MachOPlatform darwinPowerPCPlatform(PlatformInfo::PowerPC); +MachOPlatform darwinx86_64Platform(PlatformInfo::x86_64); } // namespace - -#define MACRO_MAKE_NAME(a, b, c) a##b##c -#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c) - -namespace binaryToObject { - -bool -MAKE_NAME(writeMachO, BITS_PER_WORD, Object) - (uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - cpu_type_t cpuType; - cpu_subtype_t cpuSubType; - if (strcmp(architecture, "x86_64") == 0) { - cpuType = CPU_TYPE_X86_64; - cpuSubType = CPU_SUBTYPE_X86_64_ALL; - } else if (strcmp(architecture, "i386") == 0) { - cpuType = CPU_TYPE_I386; - cpuSubType = CPU_SUBTYPE_I386_ALL; - } else if (strcmp(architecture, "powerpc") == 0) { - cpuType = CPU_TYPE_POWERPC; - cpuSubType = CPU_SUBTYPE_POWERPC_ALL; - } else if (strcmp(architecture, "arm") == 0) { - cpuType = CPU_TYPE_ARM; - cpuSubType = CPU_SUBTYPE_ARM_V7; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } - - const char* segmentName; - const char* sectionName; - if (writable) { - if (executable) { - segmentName = "__RWX"; - sectionName = "__rwx"; - } else { - segmentName = "__DATA"; - sectionName = "__data"; - } - } else { - segmentName = "__TEXT"; - sectionName = "__text"; - } - - unsigned startNameLength = strlen(startName); - char myStartName[startNameLength + 2]; - myStartName[0] = '_'; - memcpy(myStartName + 1, startName, startNameLength + 1); - - unsigned endNameLength = strlen(endName); - char myEndName[endNameLength + 2]; - myEndName[0] = '_'; - memcpy(myEndName + 1, endName, endNameLength + 1); - - writeObject(data, size, out, myStartName, myEndName, segmentName, - sectionName, alignment, cpuType, cpuSubType); - - return true; -} - -} // namespace binaryToObject diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index ffc6f1e017..6dcdf9734d 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -8,110 +8,61 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "stdlib.h" -#include "string.h" +#include +#include +#include +#include -#include "sys/stat.h" +#include #ifdef WIN32 #include #else -#include "sys/mman.h" +#include #endif -#include "fcntl.h" -#include "unistd.h" +#include +#include -namespace binaryToObject { +#include "tools.h" -bool -writeElf64Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); +extern "C" +void __cxa_pure_virtual() { + abort(); +} -bool -writeElf32Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); +void* operator new(size_t size) { + return malloc(size); +} -bool -writeMachO64Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); - -bool -writeMachO32Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); - -bool -writePEObject(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, - unsigned alignment, bool writable, bool executable); - -} // namespace binaryToObject +void operator delete(void* mem) { + if(mem) { + free(mem); + } +} namespace { +using namespace avian::tools; + bool writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* platform, + const char* endName, const char* os, const char* architecture, unsigned alignment, bool writable, bool executable) { - using namespace binaryToObject; + Platform* platform = Platform::getPlatform(PlatformInfo(os, architecture)); - bool found = false; - bool success = false; - if (strcmp("linux", platform) == 0) { - if (strcmp("x86_64", architecture) == 0) { - found = true; - success = writeElf64Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } else if (strcmp("i386", architecture) == 0 - or strcmp("arm", architecture) == 0 - or strcmp("powerpc", architecture) == 0) - { - found = true; - success = writeElf32Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } - } else if (strcmp("darwin", platform) == 0) { - if (strcmp("x86_64", architecture) == 0) { - found = true; - success = writeMachO64Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } else if (strcmp("i386", architecture) == 0 - or strcmp("powerpc", architecture) == 0 - or strcmp("arm", architecture) == 0) - { - found = true; - success = writeMachO32Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } - } else if (strcmp("windows", platform) == 0 - and ((strcmp("x86_64", architecture) == 0 - or strcmp("i386", architecture) == 0))) - { - found = true; - success = writePEObject - (data, size, out, startName, endName, architecture, alignment, writable, - executable); - } - - if (not found) { - fprintf(stderr, "unsupported platform: %s/%s\n", platform, architecture); + if(!platform) { + fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); return false; } + ObjectWriter* writer = platform->makeObjectWriter(); + + bool success = writer->write(data, size, out, startName, endName, alignment, + ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0)); + + writer->dispose(); + return success; } diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 45cc9556a9..67fe684153 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -8,16 +8,20 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include + +#include "tools.h" + +namespace { #define IMAGE_SIZEOF_SHORT_NAME 8 #define IMAGE_FILE_RELOCS_STRIPPED 1 #define IMAGE_FILE_LINE_NUMS_STRIPPED 4 #define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_32BIT_MACHINE 256 #define IMAGE_SCN_ALIGN_1BYTES 0x100000 @@ -29,8 +33,6 @@ #define IMAGE_SCN_MEM_WRITE 0x80000000 #define IMAGE_SCN_CNT_CODE 32 -namespace { - struct IMAGE_FILE_HEADER { uint16_t Machine; uint16_t NumberOfSections; @@ -161,71 +163,89 @@ writeObject(const uint8_t* data, unsigned size, FILE* out, fwrite(endName, 1, endNameLength, out); } -} // namespace +using namespace avian::tools; -namespace binaryToObject { +template +class WindowsPlatform : public Platform { +public: -bool -writePEObject -(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - int machine; - int machineMask; - if (strcmp(architecture, "x86_64") == 0) { - machine = IMAGE_FILE_MACHINE_AMD64; - machineMask = 0; - } else if (strcmp(architecture, "i386") == 0) { - machine = IMAGE_FILE_MACHINE_I386; - machineMask = IMAGE_FILE_32BIT_MACHINE; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } + class PEObjectWriter : public ObjectWriter { + public: - int sectionMask; - switch (alignment) { - case 0: - case 1: - sectionMask = IMAGE_SCN_ALIGN_1BYTES; - break; - case 2: - sectionMask = IMAGE_SCN_ALIGN_2BYTES; - break; - case 4: - sectionMask = IMAGE_SCN_ALIGN_4BYTES; - break; - case 8: - sectionMask = IMAGE_SCN_ALIGN_8BYTES; - break; - default: - fprintf(stderr, "unsupported alignment: %d\n", alignment); - return false; - } + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) + { + int machine; + int machineMask; - sectionMask |= IMAGE_SCN_MEM_READ; + if (BytesPerWord == 8) { + machine = IMAGE_FILE_MACHINE_AMD64; + machineMask = 0; + } else { // if (BytesPerWord == 8) + machine = IMAGE_FILE_MACHINE_I386; + machineMask = IMAGE_FILE_32BIT_MACHINE; + } - const char* sectionName; - if (writable) { - if (executable) { - sectionName = ".rwx"; - sectionMask |= IMAGE_SCN_MEM_WRITE - | IMAGE_SCN_MEM_EXECUTE - | IMAGE_SCN_CNT_CODE; - } else { - sectionName = ".data"; - sectionMask |= IMAGE_SCN_MEM_WRITE; + int sectionMask; + switch (alignment) { + case 0: + case 1: + sectionMask = IMAGE_SCN_ALIGN_1BYTES; + break; + case 2: + sectionMask = IMAGE_SCN_ALIGN_2BYTES; + break; + case 4: + sectionMask = IMAGE_SCN_ALIGN_4BYTES; + break; + case 8: + sectionMask = IMAGE_SCN_ALIGN_8BYTES; + break; + default: + fprintf(stderr, "unsupported alignment: %d\n", alignment); + return false; + } + + sectionMask |= IMAGE_SCN_MEM_READ; + + const char* sectionName; + if (accessFlags & ObjectWriter::Writable) { + if (accessFlags & ObjectWriter::Executable) { + sectionName = ".rwx"; + sectionMask |= IMAGE_SCN_MEM_WRITE + | IMAGE_SCN_MEM_EXECUTE + | IMAGE_SCN_CNT_CODE; + } else { + sectionName = ".data"; + sectionMask |= IMAGE_SCN_MEM_WRITE; + } + } else { + sectionName = ".text"; + sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + } + + writeObject(data, size, out, startName, endName, sectionName, machine, + machineMask, sectionMask); + + return true; } - } else { - sectionName = ".text"; - sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + + virtual void dispose() { + delete this; + } + + }; + + virtual ObjectWriter* makeObjectWriter() { + return new PEObjectWriter(); } - writeObject(data, size, out, startName, endName, sectionName, machine, - machineMask, sectionMask); + WindowsPlatform(): + Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {} +}; + +WindowsPlatform<4> windows32Platform; +WindowsPlatform<8> windows64Platform; - return true; } - -} // namespace binaryToObject diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp new file mode 100644 index 0000000000..531fd2f246 --- /dev/null +++ b/src/binaryToObject/tools.cpp @@ -0,0 +1,62 @@ +/* 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 +#include +#include +#include + +#include "tools.h" + +namespace avian { + +namespace tools { + + +Platform* Platform::first = 0; + +PlatformInfo::OperatingSystem PlatformInfo::osFromString(const char* os) { + if(strcmp(os, "linux") == 0) { + return Linux; + } else if(strcmp(os, "windows") == 0) { + return Windows; + } else if(strcmp(os, "darwin") == 0) { + return Darwin; + } else { + return UnknownOS; + } +} + +PlatformInfo::Architecture PlatformInfo::archFromString(const char* arch) { + if(strcmp(arch, "i386") == 0) { + return x86; + } else if(strcmp(arch, "x86_64") == 0) { + return x86_64; + } else if(strcmp(arch, "powerpc") == 0) { + return PowerPC; + } else if(strcmp(arch, "arm") == 0) { + return Arm; + } else { + return UnknownArch; + } +} + +Platform* Platform::getPlatform(PlatformInfo info) { + for(Platform* p = first; p; p = p->next) { + if(p->info == info) { + return p; + } + } + return 0; +} + +} // namespace tools + +} // namespace avian \ No newline at end of file diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h new file mode 100644 index 0000000000..1d1b2d2a34 --- /dev/null +++ b/src/binaryToObject/tools.h @@ -0,0 +1,90 @@ +/* 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. */ + +#ifndef AVIAN_TOOLS_H_ +#define AVIAN_TOOLS_H_ + +namespace avian { + +namespace tools { + +class ObjectWriter { +public: + + enum AccessFlags { + Readable = 1 << 0, + Writable = 1 << 1, + Executable = 1 << 2 + }; + + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) = 0; + + virtual void dispose() = 0; +}; + +class PlatformInfo { +public: + enum OperatingSystem { + Linux, Windows, Darwin, UnknownOS + }; + + enum Architecture { + x86, x86_64, PowerPC, Arm, UnknownArch + }; + + const OperatingSystem os; + const Architecture arch; + + static OperatingSystem osFromString(const char* os); + static Architecture archFromString(const char* arch); + + inline PlatformInfo(OperatingSystem os, Architecture arch): + os(os), + arch(arch) {} + + inline PlatformInfo(const char* os, const char* arch): + os(osFromString(os)), + arch(archFromString(arch)) {} + + inline bool operator == (const PlatformInfo& other) { + return os == other.os && arch == other.arch; + } + + inline bool isLittleEndian() { + return arch != PowerPC; + } +}; + +class Platform { +private: + Platform* next; + static Platform* first; +public: + PlatformInfo info; + + inline Platform(PlatformInfo info): + next(first), + info(info) + { + first = this; + } + + virtual ObjectWriter* makeObjectWriter() = 0; + + static Platform* getPlatform(PlatformInfo info); +}; + +} // namespace tools + +} // namespace avian + +#endif \ No newline at end of file From 175db9ec5413e5d17cdf8bf7a6e0adda9e5ea456 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 25 Apr 2012 08:43:51 -0600 Subject: [PATCH 2/6] allow streaming to more than just files in binaryToObject --- src/binaryToObject/elf.cpp | 39 +++++++++++++++++------------------ src/binaryToObject/mach-o.cpp | 25 +++++++++++----------- src/binaryToObject/main.cpp | 10 ++++----- src/binaryToObject/pe.cpp | 26 +++++++++++------------ src/binaryToObject/tools.cpp | 31 ++++++++++++++++++++++++++++ src/binaryToObject/tools.h | 22 +++++++++++++++++++- 6 files changed, 101 insertions(+), 52 deletions(-) diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index 51c7d7c587..5235c8f0a7 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -166,7 +166,7 @@ public: ElfObjectWriter(PlatformInfo::Architecture arch): arch(arch) {} - void writeObject(const uint8_t* data, unsigned size, FILE* out, + void writeObject(const uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* sectionName, unsigned sectionFlags, unsigned alignment, int machine, int encoding) @@ -311,31 +311,30 @@ public: endSymbol.st_other = V1(STV_DEFAULT); endSymbol.st_shndx = V2(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); + out->writeChunk(&fileHeader, sizeof(fileHeader)); + out->writeChunk(&nullSection, sizeof(nullSection)); + out->writeChunk(&bodySection, sizeof(bodySection)); + out->writeChunk(§ionStringTableSection, sizeof(sectionStringTableSection)); + out->writeChunk(&stringTableSection, sizeof(stringTableSection)); + out->writeChunk(&symbolTableSection, sizeof(symbolTableSection)); - fwrite(data, 1, size, out); + out->writeChunk(data, size); - fputc(0, out); - fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); - fwrite(stringTableName, 1, stringTableNameLength, out); - fwrite(symbolTableName, 1, symbolTableNameLength, out); - fwrite(sectionName, 1, sectionNameLength, out); + out->write(0); + out->writeChunk(sectionStringTableName, sectionStringTableNameLength); + out->writeChunk(stringTableName, stringTableNameLength); + out->writeChunk(symbolTableName, symbolTableNameLength); + out->writeChunk(sectionName, sectionNameLength); - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + out->write(0); + out->writeChunk(startName, startNameLength); + out->writeChunk(endName, endNameLength); - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); + out->writeChunk(&startSymbol, sizeof(startSymbol)); + out->writeChunk(&endSymbol, sizeof(endSymbol)); } - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 6aab90a0b1..e040569212 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -148,7 +148,7 @@ public: MachOObjectWriter(PlatformInfo::Architecture arch): arch(arch) {} - void writeObject(const uint8_t* data, unsigned size, FILE* out, + void writeObject(const uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* segmentName, const char* sectionName, unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) @@ -242,22 +242,23 @@ public: } }; - fwrite(&header, 1, sizeof(header), out); - fwrite(&segment, 1, sizeof(segment), out); - fwrite(§, 1, sizeof(sect), out); - fwrite(&symbolTable, 1, sizeof(symbolTable), out); + out->writeChunk(&header, sizeof(header)); + out->writeChunk(&segment, sizeof(segment)); + out->writeChunk(§, sizeof(sect)); + out->writeChunk(&symbolTable, sizeof(symbolTable)); - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + out->writeChunk(data, size); + out->writeRepeat(0, pad(size) - size); - fwrite(&symbolList, 1, sizeof(symbolList), out); + out->writeChunk(&symbolList, sizeof(symbolList)); - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + out->write(0); + + out->writeChunk(startName, startNameLength); + out->writeChunk(endName, endNameLength); } - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index 6dcdf9734d..197bcbf0f6 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -44,7 +44,7 @@ namespace { using namespace avian::tools; bool -writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName, +writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* os, const char* architecture, unsigned alignment, bool writable, bool executable) @@ -142,13 +142,11 @@ main(int argc, const char** argv) bool success = false; if (data) { - FILE* out = fopen(argv[2], "wb"); - if (out) { + FileOutputStream out(argv[2]); + if (out.isValid()) { success = writeObject - (data, size, out, argv[3], argv[4], argv[5], argv[6], alignment, + (data, size, &out, argv[3], argv[4], argv[5], argv[6], alignment, writable, executable); - - fclose(out); } else { fprintf(stderr, "unable to open %s\n", argv[2]); } diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 67fe684153..9fcdbe8949 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -79,8 +79,10 @@ pad(unsigned n) return (n + (4 - 1)) & ~(4 - 1); } +using namespace avian::tools; + void -writeObject(const uint8_t* data, unsigned size, FILE* out, +writeObject(const uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* sectionName, int machine, int machineMask, int sectionMask) @@ -147,24 +149,22 @@ writeObject(const uint8_t* data, unsigned size, FILE* out, }; endSymbol.N.Name.Long = endNameOffset; - fwrite(&fileHeader, 1, sizeof(fileHeader), out); - fwrite(§ionHeader, 1, sizeof(sectionHeader), out); + out->writeChunk(&fileHeader, sizeof(fileHeader)); + out->writeChunk(§ionHeader, sizeof(sectionHeader)); - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + out->writeChunk(data, size); + out->writeRepeat(0, pad(size) - size); - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); + out->writeChunk(&startSymbol, sizeof(startSymbol)); + out->writeChunk(&endSymbol, sizeof(endSymbol)); uint32_t symbolTableSize = endNameOffset + endNameLength; - fwrite(&symbolTableSize, 1, 4, out); + out->writeChunk(&symbolTableSize, 4); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + out->writeChunk(startName, startNameLength); + out->writeChunk(endName, endNameLength); } -using namespace avian::tools; - template class WindowsPlatform : public Platform { public: @@ -172,7 +172,7 @@ public: class PEObjectWriter : public ObjectWriter { public: - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp index 531fd2f246..0768e8a24b 100644 --- a/src/binaryToObject/tools.cpp +++ b/src/binaryToObject/tools.cpp @@ -19,6 +19,37 @@ namespace avian { namespace tools { +void OutputStream::write(uint8_t byte) { + writeChunk(&byte, 1); +} + +void OutputStream::writeRepeat(uint8_t byte, size_t size) { + for(size_t i = 0; i < size; i++) { + write(byte); + } +} + +FileOutputStream::FileOutputStream(const char* name): + file(fopen(name, "wb")) {} + +FileOutputStream::~FileOutputStream() { + if(file) { + fclose(file); + } +} + +bool FileOutputStream::isValid() { + return file; +} + +void FileOutputStream::writeChunk(const void* data, size_t size) { + fwrite(data, size, 1, file); +} + +void FileOutputStream::write(uint8_t byte) { + fputc(byte, file); +} + Platform* Platform::first = 0; diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 1d1b2d2a34..359068fe4d 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -15,6 +15,26 @@ namespace avian { namespace tools { +class OutputStream { +public: + virtual void writeChunk(const void* data, size_t size) = 0; + virtual void write(uint8_t byte); + virtual void writeRepeat(uint8_t byte, size_t size); +}; + +class FileOutputStream : public OutputStream { +private: + FILE* file; +public: + FileOutputStream(const char* name); + ~FileOutputStream(); + + bool isValid(); + + virtual void writeChunk(const void* data, size_t size); + virtual void write(uint8_t byte); +}; + class ObjectWriter { public: @@ -24,7 +44,7 @@ public: Executable = 1 << 2 }; - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) = 0; From a9ba4782ef8e261c30da2b19cf26968bec0436d2 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 25 Apr 2012 09:09:26 -0600 Subject: [PATCH 3/6] improve build for binaryToObject --- makefile | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/makefile b/makefile index 7389967ddb..1705b53986 100755 --- a/makefile +++ b/makefile @@ -623,14 +623,17 @@ generator-objects = \ $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) generator = $(build)/generator -converter-objects = \ - $(build)/binaryToObject-main.o \ - $(build)/binaryToObject-tools.o \ - $(build)/binaryToObject-elf.o \ - $(build)/binaryToObject-mach-o64.o \ - $(build)/binaryToObject-mach-o32.o \ - $(build)/binaryToObject-pe.o -converter = $(build)/binaryToObject +converter-depends = $(src)/binaryToObject/tools.h + +converter-sources = \ + $(src)/binaryToObject/main.cpp \ + $(src)/binaryToObject/tools.cpp \ + $(src)/binaryToObject/elf.cpp \ + $(src)/binaryToObject/mach-o.cpp \ + $(src)/binaryToObject/pe.cpp + +converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) +converter = $(build)/binaryToObject/binaryToObject static-library = $(build)/lib$(name).a executable = $(build)/$(name)${exe-suffix} @@ -838,23 +841,9 @@ $(boot-object): $(boot-source) $(boot-javahome-object): $(src)/boot-javahome.cpp $(compile-object) -$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) - -$(build)/binaryToObject-tools.o: $(src)/binaryToObject/tools.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) - -$(build)/binaryToObject-elf.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) - -$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) - -$(build)/binaryToObject-mach-o32.o: $(src)/binaryToObject/mach-o.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@) - -$(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) +$(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends) + @mkdir -p $(dir $(@)) + $(build-cxx) $(converter-cflags) -c $(<) -o $(@) $(converter): $(converter-objects) $(build-cc) $(^) -o $(@) From ca9b5b2f59c18f36e9cd1ef79f799f4e9c60e634 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 25 Apr 2012 09:09:39 -0600 Subject: [PATCH 4/6] move OutputStream to ObjectWriter constructor in binaryToObject --- src/binaryToObject/elf.cpp | 16 +++++++++------- src/binaryToObject/mach-o.cpp | 16 +++++++++------- src/binaryToObject/main.cpp | 4 ++-- src/binaryToObject/pe.cpp | 21 +++++++++++++-------- src/binaryToObject/tools.h | 4 ++-- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index 5235c8f0a7..4e752104a1 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -162,11 +162,13 @@ public: public: PlatformInfo::Architecture arch; + OutputStream* out; - ElfObjectWriter(PlatformInfo::Architecture arch): - arch(arch) {} + ElfObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): + arch(arch), + out(out) {} - void writeObject(const uint8_t* data, unsigned size, OutputStream* out, + void writeObject(const uint8_t* data, unsigned size, const char* startName, const char* endName, const char* sectionName, unsigned sectionFlags, unsigned alignment, int machine, int encoding) @@ -334,7 +336,7 @@ public: out->writeChunk(&endSymbol, sizeof(endSymbol)); } - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { @@ -374,7 +376,7 @@ public: sectionName = ".rodata"; } - writeObject(data, size, out, startName, endName, sectionName, sectionFlags, + writeObject(data, size, startName, endName, sectionName, sectionFlags, alignment, machine, encoding); return true; @@ -388,8 +390,8 @@ public: ElfPlatform(PlatformInfo::Architecture arch): Platform(PlatformInfo(PlatformInfo::Linux, arch)) {} - virtual ObjectWriter* makeObjectWriter() { - return new ElfObjectWriter(info.arch); + virtual ObjectWriter* makeObjectWriter(OutputStream* out) { + return new ElfObjectWriter(info.arch, out); } }; diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index e040569212..5899c652ff 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -144,11 +144,13 @@ public: public: PlatformInfo::Architecture arch; + OutputStream* out; - MachOObjectWriter(PlatformInfo::Architecture arch): - arch(arch) {} + MachOObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): + arch(arch), + out(out) {} - void writeObject(const uint8_t* data, unsigned size, OutputStream* out, + void writeObject(const uint8_t* data, unsigned size, const char* startName, const char* endName, const char* segmentName, const char* sectionName, unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) @@ -258,7 +260,7 @@ public: out->writeChunk(endName, endNameLength); } - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { @@ -307,7 +309,7 @@ public: myEndName[0] = '_'; memcpy(myEndName + 1, endName, endNameLength + 1); - writeObject(data, size, out, myStartName, myEndName, segmentName, + writeObject(data, size, myStartName, myEndName, segmentName, sectionName, alignment, cpuType, cpuSubType); return true; @@ -321,8 +323,8 @@ public: MachOPlatform(PlatformInfo::Architecture arch): Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {} - virtual ObjectWriter* makeObjectWriter() { - return new MachOObjectWriter(info.arch); + virtual ObjectWriter* makeObjectWriter(OutputStream* out) { + return new MachOObjectWriter(info.arch, out); } }; diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index 197bcbf0f6..c9a3fb8d75 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -56,9 +56,9 @@ writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startNa return false; } - ObjectWriter* writer = platform->makeObjectWriter(); + ObjectWriter* writer = platform->makeObjectWriter(out); - bool success = writer->write(data, size, out, startName, endName, alignment, + bool success = writer->write(data, size, startName, endName, alignment, ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0)); writer->dispose(); diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 9fcdbe8949..37bf643a95 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -103,13 +103,13 @@ writeObject(const uint8_t* data, unsigned size, OutputStream* out, sectionCount, // NumberOfSections 0, // TimeDateStamp sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER) - + pad(size), // PointerToSymbolTable + + sizeof(IMAGE_SECTION_HEADER) + + pad(size), // PointerToSymbolTable symbolCount, // NumberOfSymbols 0, // SizeOfOptionalHeader IMAGE_FILE_RELOCS_STRIPPED - | IMAGE_FILE_LINE_NUMS_STRIPPED - | machineMask // Characteristics + | IMAGE_FILE_LINE_NUMS_STRIPPED + | machineMask // Characteristics }; IMAGE_SECTION_HEADER sectionHeader = { @@ -118,7 +118,7 @@ writeObject(const uint8_t* data, unsigned size, OutputStream* out, 0, // VirtualAddress pad(size), // SizeOfRawData sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER), // PointerToRawData + + sizeof(IMAGE_SECTION_HEADER), // PointerToRawData 0, // PointerToRelocations 0, // PointerToLinenumbers 0, // NumberOfRelocations @@ -172,7 +172,12 @@ public: class PEObjectWriter : public ObjectWriter { public: - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + OutputStream* out; + + PEObjectWriter(OutputStream* out): + out(out) {} + + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { @@ -237,8 +242,8 @@ public: }; - virtual ObjectWriter* makeObjectWriter() { - return new PEObjectWriter(); + virtual ObjectWriter* makeObjectWriter(OutputStream* out) { + return new PEObjectWriter(out); } WindowsPlatform(): diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 359068fe4d..9ba285dd66 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -44,7 +44,7 @@ public: Executable = 1 << 2 }; - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) = 0; @@ -98,7 +98,7 @@ public: first = this; } - virtual ObjectWriter* makeObjectWriter() = 0; + virtual ObjectWriter* makeObjectWriter(OutputStream* out) = 0; static Platform* getPlatform(PlatformInfo info); }; From 661f6c28a8be920a5118f6bb32d3a964ee68d1d8 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 27 Apr 2012 12:08:44 -0600 Subject: [PATCH 5/6] refactor binaryToObject to allow more flexibilty (in particular, allowing arbitrary symbols per object) --- makefile | 19 +- src/binaryToObject/elf.cpp | 422 +++++++++++++++----------------- src/binaryToObject/endianness.h | 25 +- src/binaryToObject/mach-o.cpp | 339 +++++++++++-------------- src/binaryToObject/main.cpp | 20 +- src/binaryToObject/pe.cpp | 323 +++++++++++++----------- src/binaryToObject/tools.cpp | 32 +++ src/binaryToObject/tools.h | 69 +++++- 8 files changed, 640 insertions(+), 609 deletions(-) diff --git a/makefile b/makefile index 1705b53986..ff6cf9855b 100755 --- a/makefile +++ b/makefile @@ -236,7 +236,6 @@ ifeq ($(arch),powerpc) ifneq ($(platform),darwin) ifneq ($(arch),$(build-arch)) - converter-cflags += -DOPPOSITE_ENDIAN cxx = powerpc-linux-gnu-g++ cc = powerpc-linux-gnu-gcc ar = powerpc-linux-gnu-ar @@ -342,10 +341,6 @@ ifeq ($(platform),darwin) lflags += $(flags) endif - ifeq ($(build-arch),powerpc) - converter-cflags += -DBIG_ENDIAN - endif - ifeq ($(arch),powerpc) openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} @@ -428,6 +423,7 @@ endif ifeq ($(mode),debug) optimization-cflags = -O0 -g3 + converter-cflags += -O0 -g3 strip = : endif ifeq ($(mode),debug-fast) @@ -606,9 +602,6 @@ driver-object = $(build)/main.o driver-dynamic-objects = \ $(build)/main-dynamic.o -gdb-plugin-object = $(build)/gdb-plugin.o -gdb-plugin-source = $(src)/gdb-plugin.cpp - boot-source = $(src)/boot.cpp boot-object = $(build)/boot.o @@ -623,7 +616,10 @@ generator-objects = \ $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) generator = $(build)/generator -converter-depends = $(src)/binaryToObject/tools.h +converter-depends = \ + $(src)/binaryToObject/tools.h \ + $(src)/binaryToObject/endianness.h + converter-sources = \ $(src)/binaryToObject/main.cpp \ @@ -826,9 +822,6 @@ $(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(driver-object): $(driver-source) $(compile-object) -$(gdb-plugin-object): $(gdb-plugin-source) - $(compile-object) - $(build)/main-dynamic.o: $(driver-source) @echo "compiling $(@)" @mkdir -p $(dir $(@)) @@ -846,7 +839,7 @@ $(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $ $(build-cxx) $(converter-cflags) -c $(<) -o $(@) $(converter): $(converter-objects) - $(build-cc) $(^) -o $(@) + $(build-cc) $(^) -g -o $(@) $(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) @echo "creating $(@)" diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index 4e752104a1..3548ac8431 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "endianness.h" @@ -119,6 +120,39 @@ using avian::endian::Endianness; #define V4 Endianness::v4 #define VANY Endianness::vAny + +unsigned getElfPlatform(PlatformInfo::Architecture arch) { + switch(arch) { + case PlatformInfo::x86_64: + return EM_X86_64; + case PlatformInfo::x86: + return EM_386; + case PlatformInfo::Arm: + return EM_ARM; + case PlatformInfo::PowerPC: + return EM_PPC; + } + return ~0; +} + +const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) { + sectionFlags = SHF_ALLOC; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_WRITE | SHF_EXECINSTR; + return ".rwx"; + } else { + sectionFlags |= SHF_WRITE; + return ".data"; + } + } else if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_EXECINSTR; + return ".text"; + } else { + return ".rodata"; + } +} + template class ElfPlatform : public Platform { public: @@ -158,240 +192,182 @@ public: typedef Symbol_Ty Symbol; - class ElfObjectWriter : public ObjectWriter { + static const unsigned Encoding = TargetLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; + + const unsigned machine; + + ElfPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Linux, arch)), + machine(getElfPlatform(arch)) {} + + class FileWriter { public: + unsigned sectionCount; + unsigned sectionStringTableSectionNumber; - PlatformInfo::Architecture arch; - OutputStream* out; + AddrTy dataOffset; - ElfObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): - arch(arch), - out(out) {} + FileHeader header; + StringTable strings; - void writeObject(const uint8_t* data, unsigned size, - const char* startName, const char* endName, - const char* sectionName, unsigned sectionFlags, - unsigned alignment, int machine, int encoding) + FileWriter(unsigned machine): + sectionCount(0), + dataOffset(sizeof(FileHeader)) { - 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; - memset(&fileHeader, 0, sizeof(FileHeader)); - fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0); - fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1); - fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2); - fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3); - fileHeader.e_ident[EI_CLASS] = V1(Class); - fileHeader.e_ident[EI_DATA] = V1(encoding); - fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT); - fileHeader.e_ident[EI_OSABI] = V1(OSABI); - fileHeader.e_ident[EI_ABIVERSION] = V1(0); - fileHeader.e_type = V2(ET_REL); - fileHeader.e_machine = V2(machine); - fileHeader.e_version = V4(EV_CURRENT); - fileHeader.e_entry = VANY(static_cast(0)); - fileHeader.e_phoff = VANY(static_cast(0)); - fileHeader.e_shoff = VANY(static_cast(sizeof(FileHeader))); - fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); - fileHeader.e_ehsize = V2(sizeof(FileHeader)); - fileHeader.e_phentsize = V2(0); - fileHeader.e_phnum = V2(0); - fileHeader.e_shentsize = V2(sizeof(SectionHeader)); - fileHeader.e_shnum = V2(sectionCount); - fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber); - - SectionHeader nullSection; - memset(&nullSection, 0, sizeof(SectionHeader)); - - SectionHeader bodySection; - bodySection.sh_name = V4(sectionNameOffset); - bodySection.sh_type = V4(SHT_PROGBITS); - bodySection.sh_flags = VANY(static_cast(sectionFlags)); - bodySection.sh_addr = VANY(static_cast(0)); - unsigned bodySectionOffset - = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); - bodySection.sh_offset = VANY(static_cast(bodySectionOffset)); - unsigned bodySectionSize = size; - bodySection.sh_size = VANY(static_cast(bodySectionSize)); - bodySection.sh_link = V4(0); - bodySection.sh_info = V4(0); - bodySection.sh_addralign = VANY(static_cast(alignment)); - bodySection.sh_entsize = VANY(static_cast(0)); - - SectionHeader sectionStringTableSection; - sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); - sectionStringTableSection.sh_type = V4(SHT_STRTAB); - sectionStringTableSection.sh_flags = VANY(static_cast(0)); - sectionStringTableSection.sh_addr = VANY(static_cast(0)); - unsigned sectionStringTableSectionOffset - = bodySectionOffset + bodySectionSize; - sectionStringTableSection.sh_offset = VANY(static_cast(sectionStringTableSectionOffset)); - unsigned sectionStringTableSectionSize = sectionStringTableLength; - sectionStringTableSection.sh_size = VANY(static_cast(sectionStringTableSectionSize)); - sectionStringTableSection.sh_link = V4(0); - sectionStringTableSection.sh_info = V4(0); - sectionStringTableSection.sh_addralign = VANY(static_cast(1)); - sectionStringTableSection.sh_entsize = VANY(static_cast(0)); - - SectionHeader stringTableSection; - stringTableSection.sh_name = V4(stringTableNameOffset); - stringTableSection.sh_type = V4(SHT_STRTAB); - stringTableSection.sh_flags = VANY(static_cast(0)); - stringTableSection.sh_addr = VANY(static_cast(0)); - unsigned stringTableSectionOffset - = sectionStringTableSectionOffset + sectionStringTableSectionSize; - stringTableSection.sh_offset = VANY(static_cast(stringTableSectionOffset)); - unsigned stringTableSectionSize = stringTableLength; - stringTableSection.sh_size = VANY(static_cast(stringTableSectionSize)); - stringTableSection.sh_link = V4(0); - stringTableSection.sh_info = V4(0); - stringTableSection.sh_addralign = VANY(static_cast(1)); - stringTableSection.sh_entsize = VANY(static_cast(0)); - - SectionHeader symbolTableSection; - symbolTableSection.sh_name = V4(symbolTableNameOffset); - symbolTableSection.sh_type = V4(SHT_SYMTAB); - symbolTableSection.sh_flags = VANY(static_cast(0)); - symbolTableSection.sh_addr = VANY(static_cast(0)); - unsigned symbolTableSectionOffset - = stringTableSectionOffset + stringTableSectionSize; - symbolTableSection.sh_offset = VANY(static_cast(symbolTableSectionOffset)); - unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; - symbolTableSection.sh_size = VANY(static_cast(symbolTableSectionSize)); - symbolTableSection.sh_link = V4(stringTableSectionNumber); - symbolTableSection.sh_info = V4(0); - symbolTableSection.sh_addralign = VANY(static_cast(Elf::BytesPerWord)); - symbolTableSection.sh_entsize = VANY(static_cast(sizeof(Symbol))); - - Symbol startSymbol; - startSymbol.st_name = V4(startNameOffset); - startSymbol.st_value = VANY(static_cast(0)); - startSymbol.st_size = VANY(static_cast(0)); - startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - startSymbol.st_other = V1(STV_DEFAULT); - startSymbol.st_shndx = V2(bodySectionNumber); - - Symbol endSymbol; - endSymbol.st_name = V4(endNameOffset); - endSymbol.st_value = VANY(static_cast(size)); - endSymbol.st_size = VANY(static_cast(0)); - endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - endSymbol.st_other = V1(STV_DEFAULT); - endSymbol.st_shndx = V2(bodySectionNumber); - - out->writeChunk(&fileHeader, sizeof(fileHeader)); - out->writeChunk(&nullSection, sizeof(nullSection)); - out->writeChunk(&bodySection, sizeof(bodySection)); - out->writeChunk(§ionStringTableSection, sizeof(sectionStringTableSection)); - out->writeChunk(&stringTableSection, sizeof(stringTableSection)); - out->writeChunk(&symbolTableSection, sizeof(symbolTableSection)); - - out->writeChunk(data, size); - - out->write(0); - out->writeChunk(sectionStringTableName, sectionStringTableNameLength); - out->writeChunk(stringTableName, stringTableNameLength); - out->writeChunk(symbolTableName, symbolTableNameLength); - out->writeChunk(sectionName, sectionNameLength); - - out->write(0); - out->writeChunk(startName, startNameLength); - out->writeChunk(endName, endNameLength); - - out->writeChunk(&startSymbol, sizeof(startSymbol)); - out->writeChunk(&endSymbol, sizeof(endSymbol)); + memset(&header, 0, sizeof(FileHeader)); + header.e_ident[EI_MAG0] = V1(ELFMAG0); + header.e_ident[EI_MAG1] = V1(ELFMAG1); + header.e_ident[EI_MAG2] = V1(ELFMAG2); + header.e_ident[EI_MAG3] = V1(ELFMAG3); + header.e_ident[EI_CLASS] = V1(Class); + header.e_ident[EI_DATA] = V1(Encoding); + header.e_ident[EI_VERSION] = V1(EV_CURRENT); + header.e_ident[EI_OSABI] = V1(OSABI); + header.e_ident[EI_ABIVERSION] = V1(0); + header.e_type = V2(ET_REL); + header.e_machine = V2(machine); + header.e_version = V4(EV_CURRENT); + header.e_entry = VANY(static_cast(0)); + header.e_phoff = VANY(static_cast(0)); + header.e_shoff = VANY(static_cast(sizeof(FileHeader))); + header.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); + header.e_ehsize = V2(sizeof(FileHeader)); + header.e_phentsize = V2(0); + header.e_phnum = V2(0); + header.e_shentsize = V2(sizeof(SectionHeader)); } - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) - { - int machine; - int encoding; - if (arch == PlatformInfo::x86_64) { - machine = EM_X86_64; - encoding = ELFDATA2LSB; - } else if (arch == PlatformInfo::x86) { - machine = EM_386; - encoding = ELFDATA2LSB; - } else if (arch == PlatformInfo::Arm) { - machine = EM_ARM; - encoding = ELFDATA2LSB; - } else if (arch == PlatformInfo::PowerPC) { - machine = EM_PPC; - encoding = ELFDATA2MSB; - } else { - fprintf(stderr, "unsupported architecture: %s\n", arch); - return false; - } - - const char* sectionName; - unsigned sectionFlags = SHF_ALLOC; - if (accessFlags & Writable) { - if (accessFlags & Executable) { - sectionName = ".rwx"; - sectionFlags |= SHF_WRITE | SHF_EXECINSTR; - } else { - sectionName = ".data"; - sectionFlags |= SHF_WRITE; - } - } else if (accessFlags & Executable) { - sectionName = ".text"; - sectionFlags |= SHF_EXECINSTR; - } else { - sectionName = ".rodata"; - } - - writeObject(data, size, startName, endName, sectionName, sectionFlags, - alignment, machine, encoding); - - return true; - } - - virtual void dispose() { - delete this; + void writeHeader(OutputStream* out) { + header.e_shnum = V2(sectionCount); + header.e_shstrndx = V2(sectionStringTableSectionNumber); + out->writeChunk(&header, sizeof(FileHeader)); } }; - ElfPlatform(PlatformInfo::Architecture arch): - Platform(PlatformInfo(PlatformInfo::Linux, arch)) {} + class SectionWriter { + public: + FileWriter& file; + String name; + SectionHeader header; + const size_t* dataSize; + const uint8_t* const* data; - virtual ObjectWriter* makeObjectWriter(OutputStream* out) { - return new ElfObjectWriter(info.arch, out); + SectionWriter(FileWriter& file): + file(file), + name(""), + data(0), + dataSize(0) + { + memset(&header, 0, sizeof(SectionHeader)); + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + header.sh_name = V4(nameOffset); + } + + SectionWriter( + FileWriter& file, + const char* chname, + unsigned type, + AddrTy flags, + unsigned alignment, + AddrTy addr, + const uint8_t* const* data, + size_t* dataSize, + size_t entsize = 0, + unsigned link = 0): + + file(file), + name(chname), + data(data), + dataSize(dataSize) + { + if(strcmp(chname, ".shstrtab") == 0) { + file.sectionStringTableSectionNumber = file.sectionCount; + } + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + + header.sh_name = V4(nameOffset); + header.sh_type = V4(type); + header.sh_flags = VANY(flags); + header.sh_addr = VANY(addr); + // header.sh_offset = VANY(static_cast(bodySectionOffset)); + // header.sh_size = VANY(static_cast(*dataSize)); + header.sh_link = V4(link); + header.sh_info = V4(0); + header.sh_addralign = VANY(static_cast(alignment)); + header.sh_entsize = VANY(static_cast(entsize)); + } + + void writeHeader(OutputStream* out) { + if(dataSize) { + header.sh_offset = VANY(file.dataOffset); + header.sh_size = VANY(static_cast(*dataSize)); + file.dataOffset += *dataSize; + } + + out->writeChunk(&header, sizeof(SectionHeader)); + } + + void writeData(OutputStream* out) { + if(data) { + out->writeChunk(*data, *dataSize); + } + } + + + }; + + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + + unsigned sectionFlags; + const char* sectionName = getSectionName(accessFlags, sectionFlags); + + StringTable symbolStringTable; + Buffer symbolTable; + + FileWriter file(machine); + + const int bodySectionNumber = 1; + const int stringTableSectionNumber = 3; + + SectionWriter sections[] = { + SectionWriter(file), // null section + SectionWriter(file, sectionName, SHT_PROGBITS, sectionFlags, alignment, 0, &data.items, &data.count), // body section + SectionWriter(file, ".shstrtab", SHT_STRTAB, 0, 1, 0, &file.strings.data, &file.strings.length), + SectionWriter(file, ".strtab", SHT_STRTAB, 0, 1, 0, &symbolStringTable.data, &symbolStringTable.length), + SectionWriter(file, ".symtab", SHT_SYMTAB, 0, 8, 0, &symbolTable.data, &symbolTable.length, sizeof(Symbol), stringTableSectionNumber) + }; + + // for some reason, string tables require a null first element... + symbolStringTable.add(""); + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + size_t nameOffset = symbolStringTable.add(sym->name); + + Symbol symbolStruct; + symbolStruct.st_name = V4(nameOffset); + symbolStruct.st_value = VANY(static_cast(sym->addr)); + symbolStruct.st_size = VANY(static_cast(0)); + symbolStruct.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + symbolStruct.st_other = V1(STV_DEFAULT); + symbolStruct.st_shndx = V2(bodySectionNumber); + symbolTable.write(&symbolStruct, sizeof(Symbol)); + } + + file.writeHeader(out); + + for(int i = 0; i < file.sectionCount; i++) { + sections[i].writeHeader(out); + } + + for(int i = 0; i < file.sectionCount; i++) { + sections[i].writeData(out); + } + + return true; } }; diff --git a/src/binaryToObject/endianness.h b/src/binaryToObject/endianness.h index 36c5675bac..0537fb8bfe 100644 --- a/src/binaryToObject/endianness.h +++ b/src/binaryToObject/endianness.h @@ -15,11 +15,12 @@ namespace avian { namespace endian { -#ifndef BIG_ENDIAN -const bool LittleEndian = true; -#else -const bool LittleEndian = false; -#endif +static union { + uint32_t i; + char c[4]; +} _DetectEndianness = {1}; + +const bool LittleEndian = _DetectEndianness.c[0] == 1; template class Endianness { @@ -57,13 +58,13 @@ public: return v; } else { return - ((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | - ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | - ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) | - ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) | - ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) | - ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) | - ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) | + ((static_cast(v) >> 56) & (static_cast(0xff) << 0)) | + ((static_cast(v) >> 40) & (static_cast(0xff) << 8)) | + ((static_cast(v) >> 24) & (static_cast(0xff) << 16)) | + ((static_cast(v) >> 8) & (static_cast(0xff) << 24)) | + ((static_cast(v) << 8) & (static_cast(0xff) << 32)) | + ((static_cast(v) << 24) & (static_cast(0xff) << 40)) | + ((static_cast(v) << 40) & (static_cast(0xff) << 48)) | ((static_cast(v) << 56)); } } diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 5899c652ff..246940329f 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -56,6 +56,14 @@ using avian::endian::Endianness; #define V4 Endianness::v4 #define VANY Endianness::vAny +inline unsigned +log(unsigned n) +{ + unsigned r = 0; + for (unsigned i = 1; i < n; ++r) i <<= 1; + return r; +} + template class MachOPlatform : public Platform { public: @@ -132,200 +140,151 @@ public: return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1); } - static inline unsigned - log(unsigned n) - { - unsigned r = 0; - for (unsigned i = 1; i < n; ++r) i <<= 1; - return r; + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + cpu_type_t cpuType; + cpu_subtype_t cpuSubType; + switch(info.arch) { + case PlatformInfo::x86_64: + cpuType = CPU_TYPE_X86_64; + cpuSubType = CPU_SUBTYPE_X86_64_ALL; + break; + case PlatformInfo::x86: + cpuType = CPU_TYPE_I386; + cpuSubType = CPU_SUBTYPE_I386_ALL; + break; + case PlatformInfo::PowerPC: + cpuType = CPU_TYPE_POWERPC; + cpuSubType = CPU_SUBTYPE_POWERPC_ALL; + break; + case PlatformInfo::Arm: + cpuType = CPU_TYPE_ARM; + cpuSubType = CPU_SUBTYPE_ARM_V7; + default: + // should never happen (see MachOPlatform declarations at bottom) + fprintf(stderr, "unsupported architecture: %d\n", info.arch); + return false; + } + + const char* segmentName; + const char* sectionName; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + segmentName = "__RWX"; + sectionName = "__rwx"; + } else { + segmentName = "__DATA"; + sectionName = "__data"; + } + } else { + segmentName = "__TEXT"; + sectionName = "__text"; + } + + FileHeader header = { + V4(Magic), // magic + V4(cpuType), + V4(cpuSubType), + V4(MH_OBJECT), // filetype, + V4(2), // ncmds + V4(sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // sizeofcmds + V4(0) // flags + }; + + AddrTy finalSize = pad(data.count); + + SegmentCommand segment = { + V4(Segment), // cmd + V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize + "", // segname + VANY(static_cast(0)), // vmaddr + VANY(static_cast(finalSize)), // vmsize + VANY(static_cast(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand))), // fileoff + VANY(static_cast(finalSize)), // filesize + V4(7), // maxprot + V4(7), // initprot + V4(1), // nsects + V4(0) // flags + }; + + strncpy(segment.segname, segmentName, sizeof(segment.segname)); + + Section sect = { + "", // sectname + "", // segname + VANY(static_cast(0)), // addr + VANY(static_cast(finalSize)), // size + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // offset + V4(log(alignment)), // align + V4(0), // reloff + V4(0), // nreloc + V4(S_REGULAR), // flags + V4(0), // reserved1 + V4(0), // reserved2 + }; + + strncpy(sect.segname, segmentName, sizeof(sect.segname)); + strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); + + StringTable strings; + strings.add(""); + Buffer symbolList; + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + unsigned offset = strings.length; + strings.write("_", 1); + strings.add(sym->name); + NList symbol = { + V4(offset), // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(sym->addr)) // n_value + }; + symbolList.write(&symbol, sizeof(NList)); + } + + SymtabCommand symbolTable = { + V4(LC_SYMTAB), // cmd + V4(sizeof(SymtabCommand)), // cmdsize + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + finalSize), // symoff + V4(symbols.count), // nsyms + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + finalSize + + (sizeof(NList) * symbols.count)), // stroff + V4(strings.length), // strsize + }; + + out->writeChunk(&header, sizeof(header)); + out->writeChunk(&segment, sizeof(segment)); + out->writeChunk(§, sizeof(sect)); + out->writeChunk(&symbolTable, sizeof(symbolTable)); + + out->writeChunk(data.items, data.count); + out->writeRepeat(0, finalSize - data.count); + + out->writeChunk(symbolList.data, symbolList.length); + + out->writeChunk(strings.data, strings.length); } - - class MachOObjectWriter : public ObjectWriter { - public: - - PlatformInfo::Architecture arch; - OutputStream* out; - - MachOObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): - arch(arch), - out(out) {} - - void writeObject(const uint8_t* data, unsigned size, - const char* startName, const char* endName, - const char* segmentName, const char* sectionName, - unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) - { - unsigned startNameLength = strlen(startName) + 1; - unsigned endNameLength = strlen(endName) + 1; - - FileHeader header = { - V4(Magic), // magic - V4(cpuType), - V4(cpuSubType), - V4(MH_OBJECT), // filetype, - V4(2), // ncmds - V4(sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand)), // sizeofcmds - V4(0) // flags - }; - - SegmentCommand segment = { - V4(Segment), // cmd - V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize - "", // segname - VANY(static_cast(0)), // vmaddr - VANY(static_cast(pad(size))), // vmsize - VANY(static_cast(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand))), // fileoff - VANY(static_cast(pad(size))), // filesize - V4(7), // maxprot - V4(7), // initprot - V4(1), // nsects - V4(0) // flags - }; - - strncpy(segment.segname, segmentName, sizeof(segment.segname)); - - Section sect = { - "", // sectname - "", // segname - VANY(static_cast(0)), // addr - VANY(static_cast(pad(size))), // size - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand)), // offset - V4(log(alignment)), // align - V4(0), // reloff - V4(0), // nreloc - V4(S_REGULAR), // flags - V4(0), // reserved1 - V4(0), // reserved2 - }; - - strncpy(sect.segname, segmentName, sizeof(sect.segname)); - strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); - - SymtabCommand symbolTable = { - V4(LC_SYMTAB), // cmd - V4(sizeof(SymtabCommand)), // cmdsize - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand) - + pad(size)), // symoff - V4(2), // nsyms - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand) - + pad(size) - + (sizeof(NList) * 2)), // stroff - V4(1 + startNameLength + endNameLength), // strsize - }; - - NList symbolList[] = { - { - V4(1), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VANY(static_cast(0)) // n_value - }, - { - V4(1 + startNameLength), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VANY(static_cast(size)) // n_value - } - }; - - out->writeChunk(&header, sizeof(header)); - out->writeChunk(&segment, sizeof(segment)); - out->writeChunk(§, sizeof(sect)); - out->writeChunk(&symbolTable, sizeof(symbolTable)); - - out->writeChunk(data, size); - out->writeRepeat(0, pad(size) - size); - - out->writeChunk(&symbolList, sizeof(symbolList)); - - out->write(0); - - out->writeChunk(startName, startNameLength); - out->writeChunk(endName, endNameLength); - } - - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) - { - - cpu_type_t cpuType; - cpu_subtype_t cpuSubType; - if (arch == PlatformInfo::x86_64) { - cpuType = CPU_TYPE_X86_64; - cpuSubType = CPU_SUBTYPE_X86_64_ALL; - } else if (arch == PlatformInfo::x86) { - cpuType = CPU_TYPE_I386; - cpuSubType = CPU_SUBTYPE_I386_ALL; - } else if (arch == PlatformInfo::PowerPC) { - cpuType = CPU_TYPE_POWERPC; - cpuSubType = CPU_SUBTYPE_POWERPC_ALL; - } else if (arch == PlatformInfo::Arm) { - cpuType = CPU_TYPE_ARM; - cpuSubType = CPU_SUBTYPE_ARM_V7; - } else { - fprintf(stderr, "unsupported architecture: %d\n", arch); - return false; - } - - const char* segmentName; - const char* sectionName; - if (accessFlags & Writable) { - if (accessFlags & Executable) { - segmentName = "__RWX"; - sectionName = "__rwx"; - } else { - segmentName = "__DATA"; - sectionName = "__data"; - } - } else { - segmentName = "__TEXT"; - sectionName = "__text"; - } - - unsigned startNameLength = strlen(startName); - char myStartName[startNameLength + 2]; - myStartName[0] = '_'; - memcpy(myStartName + 1, startName, startNameLength + 1); - - unsigned endNameLength = strlen(endName); - char myEndName[endNameLength + 2]; - myEndName[0] = '_'; - memcpy(myEndName + 1, endName, endNameLength + 1); - - writeObject(data, size, myStartName, myEndName, segmentName, - sectionName, alignment, cpuType, cpuSubType); - - return true; - } - - virtual void dispose() { - delete this; - } - }; MachOPlatform(PlatformInfo::Architecture arch): Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {} - - virtual ObjectWriter* makeObjectWriter(OutputStream* out) { - return new MachOObjectWriter(info.arch, out); - } + }; MachOPlatform darwinx86Platform(PlatformInfo::x86); diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index c9a3fb8d75..e9bc749abc 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -33,18 +33,14 @@ void* operator new(size_t size) { return malloc(size); } -void operator delete(void* mem) { - if(mem) { - free(mem); - } -} +void operator delete(void* mem) { abort(); } namespace { using namespace avian::tools; bool -writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startName, +writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, const char* os, const char* architecture, unsigned alignment, bool writable, bool executable) @@ -56,14 +52,16 @@ writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startNa return false; } - ObjectWriter* writer = platform->makeObjectWriter(out); + SymbolInfo symbols[2]; + symbols[0].name = startName; + symbols[0].addr = 0; + symbols[1].name = endName; + symbols[1].addr = size; - bool success = writer->write(data, size, startName, endName, alignment, - ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0)); + unsigned accessFlags = (writable ? Platform::Writable : 0) | (executable ? Platform::Executable : 0); - writer->dispose(); + return platform->writeObject(out, Slice(symbols, 2), Slice(data, size), accessFlags, alignment); - return success; } void diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 37bf643a95..aab60feb90 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "tools.h" @@ -81,169 +82,193 @@ pad(unsigned n) using namespace avian::tools; -void -writeObject(const uint8_t* data, unsigned size, OutputStream* out, - const char* startName, const char* endName, - const char* sectionName, int machine, int machineMask, - int sectionMask) -{ - const unsigned sectionCount = 1; - const unsigned symbolCount = 2; - - const unsigned sectionNumber = 1; - - const unsigned startNameLength = strlen(startName) + 1; - const unsigned endNameLength = strlen(endName) + 1; - - const unsigned startNameOffset = 4; - const unsigned endNameOffset = startNameOffset + startNameLength; - - IMAGE_FILE_HEADER fileHeader = { - machine, // Machine - sectionCount, // NumberOfSections - 0, // TimeDateStamp - sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER) - + pad(size), // PointerToSymbolTable - symbolCount, // NumberOfSymbols - 0, // SizeOfOptionalHeader - IMAGE_FILE_RELOCS_STRIPPED - | IMAGE_FILE_LINE_NUMS_STRIPPED - | machineMask // Characteristics - }; - - IMAGE_SECTION_HEADER sectionHeader = { - "", // Name - 0, // PhysicalAddress - 0, // VirtualAddress - pad(size), // SizeOfRawData - sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER), // PointerToRawData - 0, // PointerToRelocations - 0, // PointerToLinenumbers - 0, // NumberOfRelocations - 0, // NumberOfLinenumbers - sectionMask // Characteristics - }; - - strncpy(reinterpret_cast(sectionHeader.Name), sectionName, - sizeof(sectionHeader.Name)); - - IMAGE_SYMBOL startSymbol = { - { 0 }, // Name - 0, // Value - sectionNumber, // SectionNumber - 0, // Type - 2, // StorageClass - 0, // NumberOfAuxSymbols - }; - startSymbol.N.Name.Long = startNameOffset; - - IMAGE_SYMBOL endSymbol = { - { 0 }, // Name - size, // Value - sectionNumber, // SectionNumber - 0, // Type - 2, // StorageClass - 0, // NumberOfAuxSymbols - }; - endSymbol.N.Name.Long = endNameOffset; - - out->writeChunk(&fileHeader, sizeof(fileHeader)); - out->writeChunk(§ionHeader, sizeof(sectionHeader)); - - out->writeChunk(data, size); - out->writeRepeat(0, pad(size) - size); - - out->writeChunk(&startSymbol, sizeof(startSymbol)); - out->writeChunk(&endSymbol, sizeof(endSymbol)); - - uint32_t symbolTableSize = endNameOffset + endNameLength; - out->writeChunk(&symbolTableSize, 4); - - out->writeChunk(startName, startNameLength); - out->writeChunk(endName, endNameLength); -} - template class WindowsPlatform : public Platform { public: - class PEObjectWriter : public ObjectWriter { + + class FileWriter { public: + unsigned sectionCount; + unsigned symbolCount; + unsigned dataStart; + unsigned dataOffset; - OutputStream* out; + IMAGE_FILE_HEADER header; - PEObjectWriter(OutputStream* out): - out(out) {} + StringTable strings; + Buffer symbols; - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) + FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount): + sectionCount(0), + symbolCount(symbolCount), + dataStart(sizeof(IMAGE_FILE_HEADER)), + dataOffset(0) { - int machine; - int machineMask; - - if (BytesPerWord == 8) { - machine = IMAGE_FILE_MACHINE_AMD64; - machineMask = 0; - } else { // if (BytesPerWord == 8) - machine = IMAGE_FILE_MACHINE_I386; - machineMask = IMAGE_FILE_32BIT_MACHINE; - } - - int sectionMask; - switch (alignment) { - case 0: - case 1: - sectionMask = IMAGE_SCN_ALIGN_1BYTES; - break; - case 2: - sectionMask = IMAGE_SCN_ALIGN_2BYTES; - break; - case 4: - sectionMask = IMAGE_SCN_ALIGN_4BYTES; - break; - case 8: - sectionMask = IMAGE_SCN_ALIGN_8BYTES; - break; - default: - fprintf(stderr, "unsupported alignment: %d\n", alignment); - return false; - } - - sectionMask |= IMAGE_SCN_MEM_READ; - - const char* sectionName; - if (accessFlags & ObjectWriter::Writable) { - if (accessFlags & ObjectWriter::Executable) { - sectionName = ".rwx"; - sectionMask |= IMAGE_SCN_MEM_WRITE - | IMAGE_SCN_MEM_EXECUTE - | IMAGE_SCN_CNT_CODE; - } else { - sectionName = ".data"; - sectionMask |= IMAGE_SCN_MEM_WRITE; - } - } else { - sectionName = ".text"; - sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; - } - - writeObject(data, size, out, startName, endName, sectionName, machine, - machineMask, sectionMask); - - return true; + header.Machine = machine; + // header.NumberOfSections = sectionCount; + header.TimeDateStamp = 0; + // header.PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER) + // + sizeof(IMAGE_SECTION_HEADER) + // + pad(size); + // header.NumberOfSymbols = symbolCount; + header.SizeOfOptionalHeader = 0; + header.Characteristics = IMAGE_FILE_RELOCS_STRIPPED + | IMAGE_FILE_LINE_NUMS_STRIPPED + | machineMask; } - virtual void dispose() { - delete this; + void writeHeader(OutputStream* out) { + header.NumberOfSections = sectionCount; + header.PointerToSymbolTable = dataStart + dataOffset; + printf("symbol table start: 0x%x\n", header.PointerToSymbolTable); + dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL)); + printf("string table start: 0x%x\n", dataStart + dataOffset); + header.NumberOfSymbols = symbolCount; + out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER)); } + void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) { + unsigned nameOffset = strings.add(name); + IMAGE_SYMBOL symbol = { + { 0 }, // Name + addr, // Value + sectionNumber, // SectionNumber + type, // Type + storageClass, // StorageClass + 0, // NumberOfAuxSymbols + }; + symbol.N.Name.Long = nameOffset+4; + symbols.write(&symbol, sizeof(IMAGE_SYMBOL)); + } + + void writeData(OutputStream* out) { + out->writeChunk(symbols.data, symbols.length); + uint32_t size = strings.length + 4; + out->writeChunk(&size, 4); + out->writeChunk(strings.data, strings.length); + } + }; + + class SectionWriter { + public: + FileWriter& file; + IMAGE_SECTION_HEADER header; + size_t dataSize; + size_t finalSize; + const uint8_t* data; + unsigned dataOffset; + + SectionWriter( + FileWriter& file, + const char* name, + unsigned sectionMask, + const uint8_t* data, + size_t dataSize): + + file(file), + data(data), + dataSize(dataSize), + finalSize(pad(dataSize)) + { + file.sectionCount++; + file.dataStart += sizeof(IMAGE_SECTION_HEADER); + strcpy(reinterpret_cast(header.Name), name); + header.Misc.VirtualSize = 0; + header.SizeOfRawData = finalSize; + // header.PointerToRawData = file.dataOffset; + dataOffset = file.dataOffset; + file.dataOffset += finalSize; + header.PointerToRelocations = 0; + header.PointerToLinenumbers = 0; + header.NumberOfRelocations = 0; + header.NumberOfLinenumbers = 0; + header.Characteristics = sectionMask; + } + + void writeHeader(OutputStream* out) { + header.PointerToRawData = dataOffset + file.dataStart; + printf("section %s: data at 0x%x, ending at 0x%x\n", header.Name, header.PointerToRawData, header.PointerToRawData + header.SizeOfRawData); + out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER)); + } + + void writeData(OutputStream* out) { + out->writeChunk(data, dataSize); + out->writeRepeat(0, finalSize - dataSize); + } + + }; - virtual ObjectWriter* makeObjectWriter(OutputStream* out) { - return new PEObjectWriter(out); + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + + int machine; + int machineMask; + + if (BytesPerWord == 8) { + machine = IMAGE_FILE_MACHINE_AMD64; + machineMask = 0; + } else { // if (BytesPerWord == 8) + machine = IMAGE_FILE_MACHINE_I386; + machineMask = IMAGE_FILE_32BIT_MACHINE; + } + + int sectionMask; + switch (alignment) { + case 0: + case 1: + sectionMask = IMAGE_SCN_ALIGN_1BYTES; + break; + case 2: + sectionMask = IMAGE_SCN_ALIGN_2BYTES; + break; + case 4: + sectionMask = IMAGE_SCN_ALIGN_4BYTES; + break; + case 8: + sectionMask = IMAGE_SCN_ALIGN_8BYTES; + break; + default: + fprintf(stderr, "unsupported alignment: %d\n", alignment); + return false; + } + + sectionMask |= IMAGE_SCN_MEM_READ; + + const char* sectionName; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionName = ".rwx"; + sectionMask |= IMAGE_SCN_MEM_WRITE + | IMAGE_SCN_MEM_EXECUTE + | IMAGE_SCN_CNT_CODE; + } else { + sectionName = ".data"; + sectionMask |= IMAGE_SCN_MEM_WRITE; + } + } else { + sectionName = ".text"; + sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + } + + FileWriter file(machine, machineMask, symbols.count); + + SectionWriter section(file, sectionName, sectionMask, data.items, data.count); + + file.writeHeader(out); + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + file.addSymbol(sym->name, sym->addr, 1, 0, 2); + } + + section.writeHeader(out); + + section.writeData(out); + + file.writeData(out); + + return true; + } WindowsPlatform(): @@ -253,4 +278,4 @@ public: WindowsPlatform<4> windows32Platform; WindowsPlatform<8> windows64Platform; -} +} // namespace diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp index 0768e8a24b..4f8b8170d0 100644 --- a/src/binaryToObject/tools.cpp +++ b/src/binaryToObject/tools.cpp @@ -19,6 +19,38 @@ namespace avian { namespace tools { +String::String(const char* text): + text(text), + length(strlen(text)) {} + +Buffer::Buffer(): + capacity(100), + length(0), + data((uint8_t*)malloc(capacity)) {} + +Buffer::~Buffer() { + free(data); +} + +void Buffer::ensure(size_t more) { + if(length + more > capacity) { + capacity = capacity * 2 + more; + data = (uint8_t*)realloc(data, capacity); + } +} + +void Buffer::write(const void* d, size_t size) { + ensure(size); + memcpy(data + length, d, size); + length += size; +} + +unsigned StringTable::add(String str) { + unsigned offset = Buffer::length; + Buffer::write(str.text, str.length + 1); + return offset; +} + void OutputStream::write(uint8_t byte) { writeChunk(&byte, 1); } diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 9ba285dd66..bc3d1f4f19 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -35,20 +35,62 @@ public: virtual void write(uint8_t byte); }; -class ObjectWriter { +class String { public: + const char* text; + size_t length; - enum AccessFlags { - Readable = 1 << 0, - Writable = 1 << 1, - Executable = 1 << 2 - }; + String(const char* text); +}; - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) = 0; +class SymbolInfo { +public: + unsigned addr; + String name; - virtual void dispose() = 0; + inline SymbolInfo(uint64_t addr, const char* name): + addr(addr), + name(name) {} + + inline SymbolInfo(): + name("") {} +}; + +class Buffer { +public: + size_t capacity; + size_t length; + uint8_t* data; + + Buffer(); + ~Buffer(); + + void ensure(size_t more); + void write(const void* d, size_t size); +}; + +class StringTable : public Buffer { +public: + unsigned add(String str); +}; + +template +class Slice { +public: + T* items; + size_t count; + + inline Slice(T* items, size_t count): + items(items), + count(count) {} + + inline T* begin() { + return items; + } + + inline T* end() { + return items + count; + } }; class PlatformInfo { @@ -98,7 +140,12 @@ public: first = this; } - virtual ObjectWriter* makeObjectWriter(OutputStream* out) = 0; + enum AccessFlags { + Writable = 1 << 0, + Executable = 1 << 1 + }; + + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) = 0; static Platform* getPlatform(PlatformInfo info); }; From b0dd39aa864b9aab10a95f27d4dbf813d4e505bb Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 30 Apr 2012 09:43:24 -0600 Subject: [PATCH 6/6] fix darwin arm binaryToObject support (just a missing break...) --- src/binaryToObject/mach-o.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 246940329f..ef9cbe5f30 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -159,6 +159,7 @@ public: case PlatformInfo::Arm: cpuType = CPU_TYPE_ARM; cpuSubType = CPU_SUBTYPE_ARM_V7; + break; default: // should never happen (see MachOPlatform declarations at bottom) fprintf(stderr, "unsupported architecture: %d\n", info.arch);