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")
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 $(@)

View File

@ -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 <stdint.h>
#include <stdio.h>
#include <string.h>
#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<class AddrTy>
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<class AddrTy>
struct Symbol_Ty;
struct Elf64_Sym {
Elf64_Word st_name;
template<>
struct Symbol_Ty<uint64_t> {
typedef ElfTypes<uint64_t> 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<uint32_t> {
typedef ElfTypes<uint32_t> 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<TargetLittleEndian>::v1
#define V2 Endianness<TargetLittleEndian>::v2
#define V3 Endianness<TargetLittleEndian>::v3
#define V4 Endianness<TargetLittleEndian>::v4
#define VANY Endianness<TargetLittleEndian>::vAny
const char* const sectionStringTableName = ".shstrtab";
const char* const stringTableName = ".strtab";
const char* const symbolTableName = ".symtab";
template<class AddrTy, bool TargetLittleEndian = true>
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<AddrTy> 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<AddrTy> 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(&sectionStringTableSection, 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<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);
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<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
#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
#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<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)))
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<bool TargetLittleEndian>
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<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
details. */
#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#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<TargetLittleEndian>::v1
#define V2 Endianness<TargetLittleEndian>::v2
#define V3 Endianness<TargetLittleEndian>::v3
#define V4 Endianness<TargetLittleEndian>::v4
#define VANY Endianness<TargetLittleEndian>::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 AddrTy, bool TargetLittleEndian = true>
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<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
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(&sect, 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<uint32_t> darwinx86Platform(PlatformInfo::x86);
MachOPlatform<uint32_t> darwinArmPlatform(PlatformInfo::Arm);
MachOPlatform<uint32_t, false> darwinPowerPCPlatform(PlatformInfo::PowerPC);
MachOPlatform<uint64_t> 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

View File

@ -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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sys/stat.h"
#include <sys/stat.h>
#ifdef WIN32
#include <windows.h>
#else
#include "sys/mman.h"
#include <sys/mman.h>
#endif
#include "fcntl.h"
#include "unistd.h"
#include <fcntl.h>
#include <unistd.h>
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;
}

View File

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

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