refactor binaryToObject, to better support (eventually) putting symbols for compiled code in objects

This commit is contained in:
Joshua Warner 2012-04-24 16:17:52 -06:00
parent ba1f8aa68e
commit 9c308f751c
8 changed files with 932 additions and 799 deletions

View File

@ -334,9 +334,6 @@ ifeq ($(platform),darwin)
x := $(error "couldn't find SDK for iOS version") x := $(error "couldn't find SDK for iOS version")
endif endif
ifeq ($(build-arch),powerpc)
converter-cflags += -DOPPOSITE_ENDIAN
endif
flags = -arch armv7 -isysroot \ flags = -arch armv7 -isysroot \
$(sdk-dir)/iPhoneOS$(ios-version).sdk/ $(sdk-dir)/iPhoneOS$(ios-version).sdk/
openjdk-extra-cflags += $(flags) openjdk-extra-cflags += $(flags)
@ -345,10 +342,11 @@ ifeq ($(platform),darwin)
lflags += $(flags) lflags += $(flags)
endif endif
ifeq ($(build-arch),powerpc)
converter-cflags += -DBIG_ENDIAN
endif
ifeq ($(arch),powerpc) 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} openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
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} asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
@ -356,9 +354,6 @@ ifeq ($(platform),darwin)
endif endif
ifeq ($(arch),i386) ifeq ($(arch),i386)
ifeq ($(build-arch),powerpc)
converter-cflags += -DOPPOSITE_ENDIAN
endif
openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
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} asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
@ -366,9 +361,6 @@ ifeq ($(platform),darwin)
endif endif
ifeq ($(arch),x86_64) ifeq ($(arch),x86_64)
ifeq ($(build-arch),powerpc)
converter-cflags += -DOPPOSITE_ENDIAN
endif
openjdk-extra-cflags += -arch x86_64 openjdk-extra-cflags += -arch x86_64
cflags += -arch x86_64 cflags += -arch x86_64
asmflags += -arch x86_64 asmflags += -arch x86_64
@ -614,6 +606,9 @@ driver-object = $(build)/main.o
driver-dynamic-objects = \ driver-dynamic-objects = \
$(build)/main-dynamic.o $(build)/main-dynamic.o
gdb-plugin-object = $(build)/gdb-plugin.o
gdb-plugin-source = $(src)/gdb-plugin.cpp
boot-source = $(src)/boot.cpp boot-source = $(src)/boot.cpp
boot-object = $(build)/boot.o boot-object = $(build)/boot.o
@ -630,8 +625,8 @@ generator = $(build)/generator
converter-objects = \ converter-objects = \
$(build)/binaryToObject-main.o \ $(build)/binaryToObject-main.o \
$(build)/binaryToObject-elf64.o \ $(build)/binaryToObject-tools.o \
$(build)/binaryToObject-elf32.o \ $(build)/binaryToObject-elf.o \
$(build)/binaryToObject-mach-o64.o \ $(build)/binaryToObject-mach-o64.o \
$(build)/binaryToObject-mach-o32.o \ $(build)/binaryToObject-mach-o32.o \
$(build)/binaryToObject-pe.o $(build)/binaryToObject-pe.o
@ -828,6 +823,9 @@ $(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends)
$(driver-object): $(driver-source) $(driver-object): $(driver-source)
$(compile-object) $(compile-object)
$(gdb-plugin-object): $(gdb-plugin-source)
$(compile-object)
$(build)/main-dynamic.o: $(driver-source) $(build)/main-dynamic.o: $(driver-source)
@echo "compiling $(@)" @echo "compiling $(@)"
@mkdir -p $(dir $(@)) @mkdir -p $(dir $(@))
@ -843,11 +841,11 @@ $(boot-javahome-object): $(src)/boot-javahome.cpp
$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp $(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
$(build-cxx) $(converter-cflags) -c $(^) -o $(@) $(build-cxx) $(converter-cflags) -c $(^) -o $(@)
$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp $(build)/binaryToObject-tools.o: $(src)/binaryToObject/tools.cpp
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) $(build-cxx) $(converter-cflags) -c $(^) -o $(@)
$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp $(build)/binaryToObject-elf.o: $(src)/binaryToObject/elf.cpp
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@) $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp $(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)

View File

@ -8,12 +8,14 @@
There is NO WARRANTY for this software. See license.txt for There is NO WARRANTY for this software. See license.txt for
details. */ details. */
#include "stdint.h" #include <stdint.h>
#include "stdio.h" #include <stdio.h>
#include "string.h" #include <string.h>
#include "endianness.h" #include "endianness.h"
#include "tools.h"
#define EI_NIDENT 16 #define EI_NIDENT 16
#define EI_MAG0 0 #define EI_MAG0 0
@ -62,344 +64,340 @@
#define STV_DEFAULT 0 #define STV_DEFAULT 0
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) #define SYMBOL_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 OSABI ELFOSABI_SYSV #define OSABI ELFOSABI_SYSV
namespace { namespace {
typedef uint16_t Elf64_Half; using namespace avian::tools;
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;
struct Elf64_Ehdr { template<class AddrTy>
unsigned char e_ident[EI_NIDENT]; struct ElfTypes {
Elf64_Half e_type; typedef uint16_t Half;
Elf64_Half e_machine; typedef uint32_t Word;
Elf64_Word e_version; typedef AddrTy Addr;
Elf64_Addr e_entry; typedef uint64_t Xword;
Elf64_Off e_phoff; typedef uint16_t Section;
Elf64_Off e_shoff; typedef AddrTy Off;
Elf64_Word e_flags; typedef AddrTy XFlags;
Elf64_Half e_ehsize; static const unsigned BytesPerWord = sizeof(AddrTy);
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
}; };
struct Elf64_Shdr { template<class AddrTy>
Elf64_Word sh_name; struct Symbol_Ty;
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;
};
struct Elf64_Sym { template<>
Elf64_Word st_name; struct Symbol_Ty<uint64_t> {
typedef ElfTypes<uint64_t> Elf;
Elf::Word st_name;
unsigned char st_info; unsigned char st_info;
unsigned char st_other; unsigned char st_other;
Elf64_Section st_shndx; Elf::Section st_shndx;
Elf64_Addr st_value; Elf::Addr st_value;
Elf64_Xword st_size; Elf::Xword st_size;
}; };
typedef uint16_t Elf32_Half; template<>
typedef uint32_t Elf32_Word; struct Symbol_Ty<uint32_t> {
typedef uint32_t Elf32_Addr; typedef ElfTypes<uint32_t> Elf;
typedef uint64_t Elf32_Xword;
typedef uint16_t Elf32_Section;
typedef uint32_t Elf32_Off;
struct Elf32_Ehdr { Elf::Word st_name;
unsigned char e_ident[EI_NIDENT]; Elf::Addr st_value;
Elf32_Half e_type; Elf::Word st_size;
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;
unsigned char st_info; unsigned char st_info;
unsigned char st_other; unsigned char st_other;
Elf32_Section st_shndx; Elf::Section st_shndx;
}; };
void using avian::endian::Endianness;
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;
const unsigned sectionNameLength = strlen(sectionName) + 1; #define V1 Endianness<TargetLittleEndian>::v1
const unsigned startNameLength = strlen(startName) + 1; #define V2 Endianness<TargetLittleEndian>::v2
const unsigned endNameLength = strlen(endName) + 1; #define V3 Endianness<TargetLittleEndian>::v3
#define V4 Endianness<TargetLittleEndian>::v4
#define VANY Endianness<TargetLittleEndian>::vAny
const char* const sectionStringTableName = ".shstrtab"; template<class AddrTy, bool TargetLittleEndian = true>
const char* const stringTableName = ".strtab"; class ElfPlatform : public Platform {
const char* const symbolTableName = ".symtab"; public:
const unsigned sectionStringTableNameLength typedef ElfTypes<AddrTy> Elf;
= strlen(sectionStringTableName) + 1; static const unsigned Class = Elf::BytesPerWord / 4;
const unsigned stringTableNameLength = strlen(stringTableName) + 1;
const unsigned symbolTableNameLength = strlen(symbolTableName) + 1;
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; struct SectionHeader {
const unsigned stringTableNameOffset typename Elf::Word sh_name;
= sectionStringTableNameOffset + sectionStringTableNameLength; typename Elf::Word sh_type;
const unsigned symbolTableNameOffset typename Elf::XFlags sh_flags;
= stringTableNameOffset + stringTableNameLength; typename Elf::Addr sh_addr;
const unsigned sectionNameOffset typename Elf::Off sh_offset;
= symbolTableNameOffset + symbolTableNameLength; typename Elf::Off sh_size;
const unsigned sectionStringTableLength typename Elf::Word sh_link;
= sectionNameOffset + sectionNameLength; typename Elf::Word sh_info;
typename Elf::Addr sh_addralign;
typename Elf::Off sh_entsize;
};
const unsigned startNameOffset = nullStringOffset + 1; typedef Symbol_Ty<AddrTy> Symbol;
const unsigned endNameOffset = startNameOffset + startNameLength;
const unsigned stringTableLength = endNameOffset + endNameLength;
const unsigned bodySectionNumber = 1; class ElfObjectWriter : public ObjectWriter {
const unsigned sectionStringTableSectionNumber = 2; public:
const unsigned stringTableSectionNumber = 3;
FileHeader fileHeader; PlatformInfo::Architecture arch;
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);
SectionHeader nullSection; ElfObjectWriter(PlatformInfo::Architecture arch):
memset(&nullSection, 0, sizeof(SectionHeader)); arch(arch) {}
SectionHeader bodySection; void writeObject(const uint8_t* data, unsigned size, FILE* out,
bodySection.sh_name = V4(sectionNameOffset); const char* startName, const char* endName,
bodySection.sh_type = V4(SHT_PROGBITS); const char* sectionName, unsigned sectionFlags,
bodySection.sh_flags = VW(sectionFlags); unsigned alignment, int machine, int encoding)
bodySection.sh_addr = VW(0); {
unsigned bodySectionOffset const unsigned sectionCount = 5;
= sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); const unsigned symbolCount = 2;
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);
SectionHeader sectionStringTableSection; const unsigned sectionNameLength = strlen(sectionName) + 1;
sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); const unsigned startNameLength = strlen(startName) + 1;
sectionStringTableSection.sh_type = V4(SHT_STRTAB); const unsigned endNameLength = strlen(endName) + 1;
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);
SectionHeader stringTableSection; const char* const sectionStringTableName = ".shstrtab";
stringTableSection.sh_name = V4(stringTableNameOffset); const char* const stringTableName = ".strtab";
stringTableSection.sh_type = V4(SHT_STRTAB); const char* const symbolTableName = ".symtab";
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);
SectionHeader symbolTableSection; const unsigned sectionStringTableNameLength
symbolTableSection.sh_name = V4(symbolTableNameOffset); = strlen(sectionStringTableName) + 1;
symbolTableSection.sh_type = V4(SHT_SYMTAB); const unsigned stringTableNameLength = strlen(stringTableName) + 1;
symbolTableSection.sh_flags = VW(0); const unsigned symbolTableNameLength = strlen(symbolTableName) + 1;
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));
Symbol startSymbol; const unsigned nullStringOffset = 0;
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);
Symbol endSymbol; const unsigned sectionStringTableNameOffset = nullStringOffset + 1;
endSymbol.st_name = V4(endNameOffset); const unsigned stringTableNameOffset
endSymbol.st_value = VW(size); = sectionStringTableNameOffset + sectionStringTableNameLength;
endSymbol.st_size = VW(0); const unsigned symbolTableNameOffset
endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); = stringTableNameOffset + stringTableNameLength;
endSymbol.st_other = V1(STV_DEFAULT); const unsigned sectionNameOffset
endSymbol.st_shndx = V2(bodySectionNumber); = symbolTableNameOffset + symbolTableNameLength;
const unsigned sectionStringTableLength
= sectionNameOffset + sectionNameLength;
fwrite(&fileHeader, 1, sizeof(fileHeader), out); const unsigned startNameOffset = nullStringOffset + 1;
fwrite(&nullSection, 1, sizeof(nullSection), out); const unsigned endNameOffset = startNameOffset + startNameLength;
fwrite(&bodySection, 1, sizeof(bodySection), out); const unsigned stringTableLength = endNameOffset + endNameLength;
fwrite(&sectionStringTableSection, 1, sizeof(sectionStringTableSection),
out);
fwrite(&stringTableSection, 1, sizeof(stringTableSection), out);
fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out);
fwrite(data, 1, size, out); const unsigned bodySectionNumber = 1;
const unsigned sectionStringTableSectionNumber = 2;
const unsigned stringTableSectionNumber = 3;
fputc(0, out); FileHeader fileHeader;
fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); memset(&fileHeader, 0, sizeof(FileHeader));
fwrite(stringTableName, 1, stringTableNameLength, out); fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0);
fwrite(symbolTableName, 1, symbolTableNameLength, out); fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1);
fwrite(sectionName, 1, sectionNameLength, out); 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<AddrTy>(0));
fileHeader.e_phoff = VANY(static_cast<AddrTy>(0));
fileHeader.e_shoff = VANY(static_cast<AddrTy>(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); SectionHeader nullSection;
fwrite(startName, 1, startNameLength, out); memset(&nullSection, 0, sizeof(SectionHeader));
fwrite(endName, 1, endNameLength, out);
SectionHeader bodySection;
bodySection.sh_name = V4(sectionNameOffset);
bodySection.sh_type = V4(SHT_PROGBITS);
bodySection.sh_flags = VANY(static_cast<AddrTy>(sectionFlags));
bodySection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned bodySectionOffset
= sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount);
bodySection.sh_offset = VANY(static_cast<AddrTy>(bodySectionOffset));
unsigned bodySectionSize = size;
bodySection.sh_size = VANY(static_cast<AddrTy>(bodySectionSize));
bodySection.sh_link = V4(0);
bodySection.sh_info = V4(0);
bodySection.sh_addralign = VANY(static_cast<AddrTy>(alignment));
bodySection.sh_entsize = VANY(static_cast<AddrTy>(0));
SectionHeader sectionStringTableSection;
sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset);
sectionStringTableSection.sh_type = V4(SHT_STRTAB);
sectionStringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
sectionStringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned sectionStringTableSectionOffset
= bodySectionOffset + bodySectionSize;
sectionStringTableSection.sh_offset = VANY(static_cast<AddrTy>(sectionStringTableSectionOffset));
unsigned sectionStringTableSectionSize = sectionStringTableLength;
sectionStringTableSection.sh_size = VANY(static_cast<AddrTy>(sectionStringTableSectionSize));
sectionStringTableSection.sh_link = V4(0);
sectionStringTableSection.sh_info = V4(0);
sectionStringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
sectionStringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
SectionHeader stringTableSection;
stringTableSection.sh_name = V4(stringTableNameOffset);
stringTableSection.sh_type = V4(SHT_STRTAB);
stringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
stringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned stringTableSectionOffset
= sectionStringTableSectionOffset + sectionStringTableSectionSize;
stringTableSection.sh_offset = VANY(static_cast<AddrTy>(stringTableSectionOffset));
unsigned stringTableSectionSize = stringTableLength;
stringTableSection.sh_size = VANY(static_cast<AddrTy>(stringTableSectionSize));
stringTableSection.sh_link = V4(0);
stringTableSection.sh_info = V4(0);
stringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
stringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
SectionHeader symbolTableSection;
symbolTableSection.sh_name = V4(symbolTableNameOffset);
symbolTableSection.sh_type = V4(SHT_SYMTAB);
symbolTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
symbolTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned symbolTableSectionOffset
= stringTableSectionOffset + stringTableSectionSize;
symbolTableSection.sh_offset = VANY(static_cast<AddrTy>(symbolTableSectionOffset));
unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount;
symbolTableSection.sh_size = VANY(static_cast<AddrTy>(symbolTableSectionSize));
symbolTableSection.sh_link = V4(stringTableSectionNumber);
symbolTableSection.sh_info = V4(0);
symbolTableSection.sh_addralign = VANY(static_cast<AddrTy>(Elf::BytesPerWord));
symbolTableSection.sh_entsize = VANY(static_cast<AddrTy>(sizeof(Symbol)));
Symbol startSymbol;
startSymbol.st_name = V4(startNameOffset);
startSymbol.st_value = VANY(static_cast<AddrTy>(0));
startSymbol.st_size = VANY(static_cast<AddrTy>(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<AddrTy>(size));
endSymbol.st_size = VANY(static_cast<AddrTy>(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(&sectionStringTableSection, 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<uint32_t> elfx86Platform(PlatformInfo::x86);
ElfPlatform<uint32_t> elfArmPlatform(PlatformInfo::Arm);
ElfPlatform<uint32_t, false> elfPowerPCPlatform(PlatformInfo::PowerPC);
ElfPlatform<uint64_t> elfx86_64Platform(PlatformInfo::x86_64);
fwrite(&startSymbol, 1, sizeof(startSymbol), out);
fwrite(&endSymbol, 1, sizeof(endSymbol), out);
}
} // namespace } // 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

View File

@ -1,38 +1,80 @@
#ifndef ENDIANNESS_H /* Copyright (c) 2008-2011, Avian Contributors
#define ENDIANNESS_H
#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 There is NO WARRANTY for this software. See license.txt for
# define V2(v) \ details. */
((((v) >> 8) & 0xFF) | \
(((v) << 8))) #ifndef AVIAN_ENDIANNESS_H
# define V4(v) \ #define AVIAN_ENDIANNESS_H
((((v) >> 24) & 0x000000FF) | \
(((v) >> 8) & 0x0000FF00) | \ namespace avian {
(((v) << 8) & 0x00FF0000) | \
(((v) << 24))) namespace endian {
# define V8(v) \
(((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) | \ #ifndef BIG_ENDIAN
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) | \ const bool LittleEndian = true;
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) | \
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) | \
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) | \
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) | \
((static_cast<uint64_t>(v) << 56)))
#else #else
# define V2(v) (v) const bool LittleEndian = false;
# define V4(v) (v)
# define V8(v) (v)
#endif #endif
#if (BITS_PER_WORD == 64) template<bool TargetLittleEndian>
# define VW(v) V8(v) class Endianness {
#elif (BITS_PER_WORD == 32) public:
# define VW(v) V4(v) static inline uint8_t v1(uint8_t v) {
#else return v;
# error }
#endif
#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<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) |
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) |
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) |
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) |
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) |
((static_cast<uint64_t>(v) << 56));
}
}
static inline uint64_t vAny(uint64_t v) {
return v8(v);
}
};
} // namespace endian
} // namespace avian
#endif // AVIAN_ENDIANNESS_H

View File

@ -8,19 +8,19 @@
There is NO WARRANTY for this software. See license.txt for There is NO WARRANTY for this software. See license.txt for
details. */ details. */
#include "stdint.h" #include <stdint.h>
#include "stdio.h" #include <stdio.h>
#include "string.h" #include <string.h>
#include "endianness.h" #include "endianness.h"
#include "tools.h"
#define MH_MAGIC_64 0xfeedfacf #define MH_MAGIC_64 0xfeedfacf
#define MH_MAGIC 0xfeedface #define MH_MAGIC 0xfeedface
#define MH_OBJECT 1 #define MH_OBJECT 1
#define LC_SEGMENT_64 0x19
#define LC_SEGMENT 1
#define LC_SYMTAB 2 #define LC_SYMTAB 2
#define S_REGULAR 0 #define S_REGULAR 0
@ -40,322 +40,294 @@
#define CPU_SUBTYPE_POWERPC_ALL 0 #define CPU_SUBTYPE_POWERPC_ALL 0
#define CPU_SUBTYPE_ARM_V7 9 #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 { namespace {
using namespace avian::tools;
typedef int cpu_type_t; typedef int cpu_type_t;
typedef int cpu_subtype_t; typedef int cpu_subtype_t;
typedef int vm_prot_t; typedef int vm_prot_t;
struct mach_header_64 { using avian::endian::Endianness;
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;
};
struct segment_command_64 { #define V1 Endianness<TargetLittleEndian>::v1
uint32_t cmd; #define V2 Endianness<TargetLittleEndian>::v2
uint32_t cmdsize; #define V3 Endianness<TargetLittleEndian>::v3
char segname[16]; #define V4 Endianness<TargetLittleEndian>::v4
uint64_t vmaddr; #define VANY Endianness<TargetLittleEndian>::vAny
uint64_t vmsize;
uint64_t fileoff;
uint64_t filesize;
vm_prot_t maxprot;
vm_prot_t initprot;
uint32_t nsects;
uint32_t flags;
};
struct section_64 { template<class AddrTy, bool TargetLittleEndian = true>
char sectname[16]; class MachOPlatform : public Platform {
char segname[16]; public:
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;
};
struct nlist_64 { struct FileHeader {
union { uint32_t magic;
uint32_t n_strx; cpu_type_t cputype;
} n_un; cpu_subtype_t cpusubtype;
uint8_t n_type; uint32_t filetype;
uint8_t n_sect; uint32_t ncmds;
uint16_t n_desc; uint32_t sizeofcmds;
uint64_t n_value;
};
struct mach_header { union {
uint32_t magic; uint32_t flags;
cpu_type_t cputype; AddrTy flagsAndMaybeReserved;
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
}; };
SegmentCommand segment = {
V4(Segment), // cmd struct SegmentCommand {
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize uint32_t cmd;
"", // segname uint32_t cmdsize;
VW(0), // vmaddr char segname[16];
VW(pad(size)), // vmsize AddrTy vmaddr;
VW(sizeof(FileHeader) AddrTy vmsize;
+ sizeof(SegmentCommand) AddrTy fileoff;
+ sizeof(Section) AddrTy filesize;
+ sizeof(symtab_command)), // fileoff vm_prot_t maxprot;
VW(pad(size)), // filesize vm_prot_t initprot;
V4(7), // maxprot uint32_t nsects;
V4(7), // initprot uint32_t flags;
V4(1), // nsects
V4(0) // flags
}; };
strncpy(segment.segname, segmentName, sizeof(segment.segname)); struct Section {
char sectname[16];
Section sect = { char segname[16];
"", // sectname AddrTy addr;
"", // segname AddrTy size;
VW(0), // addr uint32_t offset;
VW(pad(size)), // size uint32_t align;
V4(sizeof(FileHeader) uint32_t reloff;
+ sizeof(SegmentCommand) uint32_t nreloc;
+ sizeof(Section) uint32_t flags;
+ sizeof(symtab_command)), // offset uint32_t reserved1;
V4(log(alignment)), // align AddrTy reserved2AndMaybe3;
V4(0), // reloff
V4(0), // nreloc
V4(S_REGULAR), // flags
V4(0), // reserved1
V4(0), // reserved2
}; };
strncpy(sect.segname, segmentName, sizeof(sect.segname)); struct NList {
strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); union {
uint32_t n_strx;
symtab_command symbolTable = { } n_un;
V4(LC_SYMTAB), // cmd uint8_t n_type;
V4(sizeof(symtab_command)), // cmdsize uint8_t n_sect;
V4(sizeof(FileHeader) uint16_t n_desc;
+ sizeof(SegmentCommand) AddrTy n_value;
+ 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
}; };
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 unsigned startNameLength = strlen(startName) + 1;
V1(N_SECT | N_EXT), // n_type unsigned endNameLength = strlen(endName) + 1;
V1(1), // n_sect
V2(0), // n_desc FileHeader header = {
VW(0) // n_value 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<AddrTy>(0)), // vmaddr
VANY(static_cast<AddrTy>(pad(size))), // vmsize
VANY(static_cast<AddrTy>(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(SymtabCommand))), // fileoff
VANY(static_cast<AddrTy>(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<AddrTy>(0)), // addr
VANY(static_cast<AddrTy>(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<AddrTy>(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<AddrTy>(size)) // n_value
}
};
fwrite(&header, 1, sizeof(header), out);
fwrite(&segment, 1, sizeof(segment), out);
fwrite(&sect, 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 cpu_type_t cpuType;
V1(1), // n_sect cpu_subtype_t cpuSubType;
V2(0), // n_desc if (arch == PlatformInfo::x86_64) {
VW(size) // n_value 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); virtual ObjectWriter* makeObjectWriter() {
fwrite(&segment, 1, sizeof(segment), out); return new MachOObjectWriter(info.arch);
fwrite(&sect, 1, sizeof(sect), out); }
fwrite(&symbolTable, 1, sizeof(symbolTable), out); };
fwrite(data, 1, size, out); MachOPlatform<uint32_t> darwinx86Platform(PlatformInfo::x86);
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); MachOPlatform<uint32_t> darwinArmPlatform(PlatformInfo::Arm);
MachOPlatform<uint32_t, false> darwinPowerPCPlatform(PlatformInfo::PowerPC);
fwrite(&symbolList, 1, sizeof(symbolList), out); MachOPlatform<uint64_t> darwinx86_64Platform(PlatformInfo::x86_64);
fputc(0, out);
fwrite(startName, 1, startNameLength, out);
fwrite(endName, 1, endNameLength, out);
}
} // namespace } // 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

View File

@ -8,110 +8,61 @@
There is NO WARRANTY for this software. See license.txt for There is NO WARRANTY for this software. See license.txt for
details. */ details. */
#include "stdint.h" #include <stdint.h>
#include "stdio.h" #include <stdio.h>
#include "stdlib.h" #include <stdlib.h>
#include "string.h" #include <string.h>
#include "sys/stat.h" #include <sys/stat.h>
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
#else #else
#include "sys/mman.h" #include <sys/mman.h>
#endif #endif
#include "fcntl.h" #include <fcntl.h>
#include "unistd.h" #include <unistd.h>
namespace binaryToObject { #include "tools.h"
bool extern "C"
writeElf64Object(uint8_t* data, unsigned size, FILE* out, void __cxa_pure_virtual() {
const char* startName, const char* endName, abort();
const char* architecture, unsigned alignment, bool writable, }
bool executable);
bool void* operator new(size_t size) {
writeElf32Object(uint8_t* data, unsigned size, FILE* out, return malloc(size);
const char* startName, const char* endName, }
const char* architecture, unsigned alignment, bool writable,
bool executable);
bool void operator delete(void* mem) {
writeMachO64Object(uint8_t* data, unsigned size, FILE* out, if(mem) {
const char* startName, const char* endName, free(mem);
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
namespace { namespace {
using namespace avian::tools;
bool bool
writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName, 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, const char* architecture, unsigned alignment, bool writable,
bool executable) bool executable)
{ {
using namespace binaryToObject; Platform* platform = Platform::getPlatform(PlatformInfo(os, architecture));
bool found = false; if(!platform) {
bool success = false; fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture);
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);
return false; 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; return success;
} }

View File

@ -8,16 +8,20 @@
There is NO WARRANTY for this software. See license.txt for There is NO WARRANTY for this software. See license.txt for
details. */ details. */
#include "stdint.h" #include <stdint.h>
#include "stdio.h" #include <stdio.h>
#include "string.h" #include <string.h>
#include "tools.h"
namespace {
#define IMAGE_SIZEOF_SHORT_NAME 8 #define IMAGE_SIZEOF_SHORT_NAME 8
#define IMAGE_FILE_RELOCS_STRIPPED 1 #define IMAGE_FILE_RELOCS_STRIPPED 1
#define IMAGE_FILE_LINE_NUMS_STRIPPED 4 #define IMAGE_FILE_LINE_NUMS_STRIPPED 4
#define IMAGE_FILE_MACHINE_AMD64 0x8664 #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_FILE_32BIT_MACHINE 256
#define IMAGE_SCN_ALIGN_1BYTES 0x100000 #define IMAGE_SCN_ALIGN_1BYTES 0x100000
@ -29,8 +33,6 @@
#define IMAGE_SCN_MEM_WRITE 0x80000000 #define IMAGE_SCN_MEM_WRITE 0x80000000
#define IMAGE_SCN_CNT_CODE 32 #define IMAGE_SCN_CNT_CODE 32
namespace {
struct IMAGE_FILE_HEADER { struct IMAGE_FILE_HEADER {
uint16_t Machine; uint16_t Machine;
uint16_t NumberOfSections; uint16_t NumberOfSections;
@ -161,71 +163,89 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
fwrite(endName, 1, endNameLength, out); fwrite(endName, 1, endNameLength, out);
} }
} // namespace using namespace avian::tools;
namespace binaryToObject { template<unsigned BytesPerWord>
class WindowsPlatform : public Platform {
public:
bool class PEObjectWriter : public ObjectWriter {
writePEObject public:
(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;
}
int sectionMask; virtual bool write(uint8_t* data, size_t size, FILE* out,
switch (alignment) { const char* startName, const char* endName,
case 0: unsigned alignment, unsigned accessFlags)
case 1: {
sectionMask = IMAGE_SCN_ALIGN_1BYTES; int machine;
break; int machineMask;
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; 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; int sectionMask;
if (writable) { switch (alignment) {
if (executable) { case 0:
sectionName = ".rwx"; case 1:
sectionMask |= IMAGE_SCN_MEM_WRITE sectionMask = IMAGE_SCN_ALIGN_1BYTES;
| IMAGE_SCN_MEM_EXECUTE break;
| IMAGE_SCN_CNT_CODE; case 2:
} else { sectionMask = IMAGE_SCN_ALIGN_2BYTES;
sectionName = ".data"; break;
sectionMask |= IMAGE_SCN_MEM_WRITE; 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"; virtual void dispose() {
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; delete this;
}
};
virtual ObjectWriter* makeObjectWriter() {
return new PEObjectWriter();
} }
writeObject(data, size, out, startName, endName, sectionName, machine, WindowsPlatform():
machineMask, sectionMask); Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {}
};
WindowsPlatform<4> windows32Platform;
WindowsPlatform<8> windows64Platform;
return true;
} }
} // namespace binaryToObject

View File

@ -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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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

View File

@ -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