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 ($(arch),powerpc) ifeq ($(build-arch),powerpc)
ifneq (,$(filter i386 x86_64 arm,$(build-arch))) converter-cflags += -DBIG_ENDIAN
converter-cflags += -DOPPOSITE_ENDIAN
endif endif
ifeq ($(arch),powerpc)
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,123 +64,109 @@
#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,
#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
template<class AddrTy, bool TargetLittleEndian = true>
class ElfPlatform : public Platform {
public:
typedef ElfTypes<AddrTy> Elf;
static const unsigned Class = Elf::BytesPerWord / 4;
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;
};
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;
};
typedef Symbol_Ty<AddrTy> Symbol;
class ElfObjectWriter : public ObjectWriter {
public:
PlatformInfo::Architecture arch;
ElfObjectWriter(PlatformInfo::Architecture arch):
arch(arch) {}
void writeObject(const uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName, const char* startName, const char* endName,
const char* sectionName, unsigned sectionFlags, const char* sectionName, unsigned sectionFlags,
unsigned alignment, int machine, int encoding) unsigned alignment, int machine, int encoding)
@ -233,9 +221,9 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
fileHeader.e_type = V2(ET_REL); fileHeader.e_type = V2(ET_REL);
fileHeader.e_machine = V2(machine); fileHeader.e_machine = V2(machine);
fileHeader.e_version = V4(EV_CURRENT); fileHeader.e_version = V4(EV_CURRENT);
fileHeader.e_entry = VW(0); fileHeader.e_entry = VANY(static_cast<AddrTy>(0));
fileHeader.e_phoff = VW(0); fileHeader.e_phoff = VANY(static_cast<AddrTy>(0));
fileHeader.e_shoff = VW(sizeof(FileHeader)); fileHeader.e_shoff = VANY(static_cast<AddrTy>(sizeof(FileHeader)));
fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
fileHeader.e_ehsize = V2(sizeof(FileHeader)); fileHeader.e_ehsize = V2(sizeof(FileHeader));
fileHeader.e_phentsize = V2(0); fileHeader.e_phentsize = V2(0);
@ -250,75 +238,75 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
SectionHeader bodySection; SectionHeader bodySection;
bodySection.sh_name = V4(sectionNameOffset); bodySection.sh_name = V4(sectionNameOffset);
bodySection.sh_type = V4(SHT_PROGBITS); bodySection.sh_type = V4(SHT_PROGBITS);
bodySection.sh_flags = VW(sectionFlags); bodySection.sh_flags = VANY(static_cast<AddrTy>(sectionFlags));
bodySection.sh_addr = VW(0); bodySection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned bodySectionOffset unsigned bodySectionOffset
= sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount);
bodySection.sh_offset = VW(bodySectionOffset); bodySection.sh_offset = VANY(static_cast<AddrTy>(bodySectionOffset));
unsigned bodySectionSize = size; unsigned bodySectionSize = size;
bodySection.sh_size = VW(bodySectionSize); bodySection.sh_size = VANY(static_cast<AddrTy>(bodySectionSize));
bodySection.sh_link = V4(0); bodySection.sh_link = V4(0);
bodySection.sh_info = V4(0); bodySection.sh_info = V4(0);
bodySection.sh_addralign = VW(alignment); bodySection.sh_addralign = VANY(static_cast<AddrTy>(alignment));
bodySection.sh_entsize = VW(0); bodySection.sh_entsize = VANY(static_cast<AddrTy>(0));
SectionHeader sectionStringTableSection; SectionHeader sectionStringTableSection;
sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset);
sectionStringTableSection.sh_type = V4(SHT_STRTAB); sectionStringTableSection.sh_type = V4(SHT_STRTAB);
sectionStringTableSection.sh_flags = VW(0); sectionStringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
sectionStringTableSection.sh_addr = VW(0); sectionStringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned sectionStringTableSectionOffset unsigned sectionStringTableSectionOffset
= bodySectionOffset + bodySectionSize; = bodySectionOffset + bodySectionSize;
sectionStringTableSection.sh_offset = VW(sectionStringTableSectionOffset); sectionStringTableSection.sh_offset = VANY(static_cast<AddrTy>(sectionStringTableSectionOffset));
unsigned sectionStringTableSectionSize = sectionStringTableLength; unsigned sectionStringTableSectionSize = sectionStringTableLength;
sectionStringTableSection.sh_size = VW(sectionStringTableSectionSize); sectionStringTableSection.sh_size = VANY(static_cast<AddrTy>(sectionStringTableSectionSize));
sectionStringTableSection.sh_link = V4(0); sectionStringTableSection.sh_link = V4(0);
sectionStringTableSection.sh_info = V4(0); sectionStringTableSection.sh_info = V4(0);
sectionStringTableSection.sh_addralign = VW(1); sectionStringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
sectionStringTableSection.sh_entsize = VW(0); sectionStringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
SectionHeader stringTableSection; SectionHeader stringTableSection;
stringTableSection.sh_name = V4(stringTableNameOffset); stringTableSection.sh_name = V4(stringTableNameOffset);
stringTableSection.sh_type = V4(SHT_STRTAB); stringTableSection.sh_type = V4(SHT_STRTAB);
stringTableSection.sh_flags = VW(0); stringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
stringTableSection.sh_addr = VW(0); stringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned stringTableSectionOffset unsigned stringTableSectionOffset
= sectionStringTableSectionOffset + sectionStringTableSectionSize; = sectionStringTableSectionOffset + sectionStringTableSectionSize;
stringTableSection.sh_offset = VW(stringTableSectionOffset); stringTableSection.sh_offset = VANY(static_cast<AddrTy>(stringTableSectionOffset));
unsigned stringTableSectionSize = stringTableLength; unsigned stringTableSectionSize = stringTableLength;
stringTableSection.sh_size = VW(stringTableSectionSize); stringTableSection.sh_size = VANY(static_cast<AddrTy>(stringTableSectionSize));
stringTableSection.sh_link = V4(0); stringTableSection.sh_link = V4(0);
stringTableSection.sh_info = V4(0); stringTableSection.sh_info = V4(0);
stringTableSection.sh_addralign = VW(1); stringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
stringTableSection.sh_entsize = VW(0); stringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
SectionHeader symbolTableSection; SectionHeader symbolTableSection;
symbolTableSection.sh_name = V4(symbolTableNameOffset); symbolTableSection.sh_name = V4(symbolTableNameOffset);
symbolTableSection.sh_type = V4(SHT_SYMTAB); symbolTableSection.sh_type = V4(SHT_SYMTAB);
symbolTableSection.sh_flags = VW(0); symbolTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
symbolTableSection.sh_addr = VW(0); symbolTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
unsigned symbolTableSectionOffset unsigned symbolTableSectionOffset
= stringTableSectionOffset + stringTableSectionSize; = stringTableSectionOffset + stringTableSectionSize;
symbolTableSection.sh_offset = VW(symbolTableSectionOffset); symbolTableSection.sh_offset = VANY(static_cast<AddrTy>(symbolTableSectionOffset));
unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount;
symbolTableSection.sh_size = VW(symbolTableSectionSize); symbolTableSection.sh_size = VANY(static_cast<AddrTy>(symbolTableSectionSize));
symbolTableSection.sh_link = V4(stringTableSectionNumber); symbolTableSection.sh_link = V4(stringTableSectionNumber);
symbolTableSection.sh_info = V4(0); symbolTableSection.sh_info = V4(0);
symbolTableSection.sh_addralign = VW(BITS_PER_WORD / 8); symbolTableSection.sh_addralign = VANY(static_cast<AddrTy>(Elf::BytesPerWord));
symbolTableSection.sh_entsize = VW(sizeof(Symbol)); symbolTableSection.sh_entsize = VANY(static_cast<AddrTy>(sizeof(Symbol)));
Symbol startSymbol; Symbol startSymbol;
startSymbol.st_name = V4(startNameOffset); startSymbol.st_name = V4(startNameOffset);
startSymbol.st_value = VW(0); startSymbol.st_value = VANY(static_cast<AddrTy>(0));
startSymbol.st_size = VW(0); startSymbol.st_size = VANY(static_cast<AddrTy>(0));
startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
startSymbol.st_other = V1(STV_DEFAULT); startSymbol.st_other = V1(STV_DEFAULT);
startSymbol.st_shndx = V2(bodySectionNumber); startSymbol.st_shndx = V2(bodySectionNumber);
Symbol endSymbol; Symbol endSymbol;
endSymbol.st_name = V4(endNameOffset); endSymbol.st_name = V4(endNameOffset);
endSymbol.st_value = VW(size); endSymbol.st_value = VANY(static_cast<AddrTy>(size));
endSymbol.st_size = VW(0); endSymbol.st_size = VANY(static_cast<AddrTy>(0));
endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
endSymbol.st_other = V1(STV_DEFAULT); endSymbol.st_other = V1(STV_DEFAULT);
endSymbol.st_shndx = V2(bodySectionNumber); endSymbol.st_shndx = V2(bodySectionNumber);
@ -347,49 +335,40 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
fwrite(&endSymbol, 1, sizeof(endSymbol), out); fwrite(&endSymbol, 1, sizeof(endSymbol), out);
} }
} // namespace virtual bool write(uint8_t* data, size_t size, FILE* out,
const char* startName, const char* endName,
#define MACRO_MAKE_NAME(a, b, c) a##b##c unsigned alignment, unsigned accessFlags)
#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 machine;
int encoding; int encoding;
if (strcmp(architecture, "x86_64") == 0) { if (arch == PlatformInfo::x86_64) {
machine = EM_X86_64; machine = EM_X86_64;
encoding = ELFDATA2LSB; encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "i386") == 0) { } else if (arch == PlatformInfo::x86) {
machine = EM_386; machine = EM_386;
encoding = ELFDATA2LSB; encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "arm") == 0) { } else if (arch == PlatformInfo::Arm) {
machine = EM_ARM; machine = EM_ARM;
encoding = ELFDATA2LSB; encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "powerpc") == 0) { } else if (arch == PlatformInfo::PowerPC) {
machine = EM_PPC; machine = EM_PPC;
encoding = ELFDATA2MSB; encoding = ELFDATA2MSB;
} else { } else {
fprintf(stderr, "unsupported architecture: %s\n", architecture); fprintf(stderr, "unsupported architecture: %s\n", arch);
return false; return false;
} }
const char* sectionName; const char* sectionName;
unsigned sectionFlags = SHF_ALLOC; unsigned sectionFlags = SHF_ALLOC;
if (writable) { if (accessFlags & Writable) {
if (executable) { if (accessFlags & Executable) {
sectionName = ".rwx"; sectionName = ".rwx";
sectionFlags |= SHF_WRITE | SHF_EXECINSTR; sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
} else { } else {
sectionName = ".data"; sectionName = ".data";
sectionFlags |= SHF_WRITE; sectionFlags |= SHF_WRITE;
} }
} else if (executable) { } else if (accessFlags & Executable) {
sectionName = ".text"; sectionName = ".text";
sectionFlags |= SHF_EXECINSTR; sectionFlags |= SHF_EXECINSTR;
} else { } else {
@ -402,4 +381,23 @@ MAKE_NAME(writeElf, BITS_PER_WORD, Object)
return true; return true;
} }
} // namespace binaryToObject 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);
} // namespace

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,119 +40,80 @@
#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;
#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
template<class AddrTy, bool TargetLittleEndian = true>
class MachOPlatform : public Platform {
public:
struct FileHeader {
uint32_t magic; uint32_t magic;
cpu_type_t cputype; cpu_type_t cputype;
cpu_subtype_t cpusubtype; cpu_subtype_t cpusubtype;
uint32_t filetype; uint32_t filetype;
uint32_t ncmds; uint32_t ncmds;
uint32_t sizeofcmds; uint32_t sizeofcmds;
union {
uint32_t flags; uint32_t flags;
uint32_t reserved; AddrTy flagsAndMaybeReserved;
};
}; };
struct segment_command_64 {
struct SegmentCommand {
uint32_t cmd; uint32_t cmd;
uint32_t cmdsize; uint32_t cmdsize;
char segname[16]; char segname[16];
uint64_t vmaddr; AddrTy vmaddr;
uint64_t vmsize; AddrTy vmsize;
uint64_t fileoff; AddrTy fileoff;
uint64_t filesize; AddrTy filesize;
vm_prot_t maxprot; vm_prot_t maxprot;
vm_prot_t initprot; vm_prot_t initprot;
uint32_t nsects; uint32_t nsects;
uint32_t flags; uint32_t flags;
}; };
struct section_64 { struct Section {
char sectname[16]; char sectname[16];
char segname[16]; char segname[16];
uint64_t addr; AddrTy addr;
uint64_t size; AddrTy size;
uint32_t offset; uint32_t offset;
uint32_t align; uint32_t align;
uint32_t reloff; uint32_t reloff;
uint32_t nreloc; uint32_t nreloc;
uint32_t flags; uint32_t flags;
uint32_t reserved1; uint32_t reserved1;
uint32_t reserved2; AddrTy reserved2AndMaybe3;
uint32_t reserved3;
}; };
struct nlist_64 { struct NList {
union { union {
uint32_t n_strx; uint32_t n_strx;
} n_un; } n_un;
uint8_t n_type; uint8_t n_type;
uint8_t n_sect; uint8_t n_sect;
uint16_t n_desc; uint16_t n_desc;
uint64_t n_value; AddrTy n_value;
}; };
struct mach_header { struct SymtabCommand {
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 cmd;
uint32_t cmdsize; uint32_t cmdsize;
uint32_t symoff; uint32_t symoff;
@ -161,23 +122,17 @@ struct symtab_command {
uint32_t strsize; uint32_t strsize;
}; };
struct nlist { static const unsigned BytesPerWord = sizeof(AddrTy);
union { static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1;
int32_t n_strx; static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface;
} n_un;
uint8_t n_type;
uint8_t n_sect;
int16_t n_desc;
uint32_t n_value;
};
inline unsigned static inline unsigned
pad(unsigned n) pad(unsigned n)
{ {
return (n + ((BITS_PER_WORD / 8) - 1)) & ~((BITS_PER_WORD / 8) - 1); return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
} }
inline unsigned static inline unsigned
log(unsigned n) log(unsigned n)
{ {
unsigned r = 0; unsigned r = 0;
@ -185,8 +140,15 @@ log(unsigned n)
return r; return r;
} }
void class MachOObjectWriter : public ObjectWriter {
writeObject(const uint8_t* data, unsigned size, FILE* out, 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* startName, const char* endName,
const char* segmentName, const char* sectionName, const char* segmentName, const char* sectionName,
unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType)
@ -202,7 +164,7 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
V4(2), // ncmds V4(2), // ncmds
V4(sizeof(SegmentCommand) V4(sizeof(SegmentCommand)
+ sizeof(Section) + sizeof(Section)
+ sizeof(symtab_command)), // sizeofcmds + sizeof(SymtabCommand)), // sizeofcmds
V4(0) // flags V4(0) // flags
}; };
@ -210,13 +172,13 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
V4(Segment), // cmd V4(Segment), // cmd
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
"", // segname "", // segname
VW(0), // vmaddr VANY(static_cast<AddrTy>(0)), // vmaddr
VW(pad(size)), // vmsize VANY(static_cast<AddrTy>(pad(size))), // vmsize
VW(sizeof(FileHeader) VANY(static_cast<AddrTy>(sizeof(FileHeader)
+ sizeof(SegmentCommand) + sizeof(SegmentCommand)
+ sizeof(Section) + sizeof(Section)
+ sizeof(symtab_command)), // fileoff + sizeof(SymtabCommand))), // fileoff
VW(pad(size)), // filesize VANY(static_cast<AddrTy>(pad(size))), // filesize
V4(7), // maxprot V4(7), // maxprot
V4(7), // initprot V4(7), // initprot
V4(1), // nsects V4(1), // nsects
@ -228,12 +190,12 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
Section sect = { Section sect = {
"", // sectname "", // sectname
"", // segname "", // segname
VW(0), // addr VANY(static_cast<AddrTy>(0)), // addr
VW(pad(size)), // size VANY(static_cast<AddrTy>(pad(size))), // size
V4(sizeof(FileHeader) V4(sizeof(FileHeader)
+ sizeof(SegmentCommand) + sizeof(SegmentCommand)
+ sizeof(Section) + sizeof(Section)
+ sizeof(symtab_command)), // offset + sizeof(SymtabCommand)), // offset
V4(log(alignment)), // align V4(log(alignment)), // align
V4(0), // reloff V4(0), // reloff
V4(0), // nreloc V4(0), // nreloc
@ -245,19 +207,19 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
strncpy(sect.segname, segmentName, sizeof(sect.segname)); strncpy(sect.segname, segmentName, sizeof(sect.segname));
strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
symtab_command symbolTable = { SymtabCommand symbolTable = {
V4(LC_SYMTAB), // cmd V4(LC_SYMTAB), // cmd
V4(sizeof(symtab_command)), // cmdsize V4(sizeof(SymtabCommand)), // cmdsize
V4(sizeof(FileHeader) V4(sizeof(FileHeader)
+ sizeof(SegmentCommand) + sizeof(SegmentCommand)
+ sizeof(Section) + sizeof(Section)
+ sizeof(symtab_command) + sizeof(SymtabCommand)
+ pad(size)), // symoff + pad(size)), // symoff
V4(2), // nsyms V4(2), // nsyms
V4(sizeof(FileHeader) V4(sizeof(FileHeader)
+ sizeof(SegmentCommand) + sizeof(SegmentCommand)
+ sizeof(Section) + sizeof(Section)
+ sizeof(symtab_command) + sizeof(SymtabCommand)
+ pad(size) + pad(size)
+ (sizeof(NList) * 2)), // stroff + (sizeof(NList) * 2)), // stroff
V4(1 + startNameLength + endNameLength), // strsize V4(1 + startNameLength + endNameLength), // strsize
@ -269,14 +231,14 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
V1(N_SECT | N_EXT), // n_type V1(N_SECT | N_EXT), // n_type
V1(1), // n_sect V1(1), // n_sect
V2(0), // n_desc V2(0), // n_desc
VW(0) // n_value VANY(static_cast<AddrTy>(0)) // n_value
}, },
{ {
V4(1 + startNameLength), // n_un V4(1 + startNameLength), // n_un
V1(N_SECT | N_EXT), // n_type V1(N_SECT | N_EXT), // n_type
V1(1), // n_sect V1(1), // n_sect
V2(0), // n_desc V2(0), // n_desc
VW(size) // n_value VANY(static_cast<AddrTy>(size)) // n_value
} }
}; };
@ -295,42 +257,34 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
fwrite(endName, 1, endNameLength, out); fwrite(endName, 1, endNameLength, out);
} }
} // namespace virtual bool write(uint8_t* data, size_t size, FILE* out,
const char* startName, const char* endName,
#define MACRO_MAKE_NAME(a, b, c) a##b##c unsigned alignment, unsigned accessFlags)
#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_type_t cpuType;
cpu_subtype_t cpuSubType; cpu_subtype_t cpuSubType;
if (strcmp(architecture, "x86_64") == 0) { if (arch == PlatformInfo::x86_64) {
cpuType = CPU_TYPE_X86_64; cpuType = CPU_TYPE_X86_64;
cpuSubType = CPU_SUBTYPE_X86_64_ALL; cpuSubType = CPU_SUBTYPE_X86_64_ALL;
} else if (strcmp(architecture, "i386") == 0) { } else if (arch == PlatformInfo::x86) {
cpuType = CPU_TYPE_I386; cpuType = CPU_TYPE_I386;
cpuSubType = CPU_SUBTYPE_I386_ALL; cpuSubType = CPU_SUBTYPE_I386_ALL;
} else if (strcmp(architecture, "powerpc") == 0) { } else if (arch == PlatformInfo::PowerPC) {
cpuType = CPU_TYPE_POWERPC; cpuType = CPU_TYPE_POWERPC;
cpuSubType = CPU_SUBTYPE_POWERPC_ALL; cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
} else if (strcmp(architecture, "arm") == 0) { } else if (arch == PlatformInfo::Arm) {
cpuType = CPU_TYPE_ARM; cpuType = CPU_TYPE_ARM;
cpuSubType = CPU_SUBTYPE_ARM_V7; cpuSubType = CPU_SUBTYPE_ARM_V7;
} else { } else {
fprintf(stderr, "unsupported architecture: %s\n", architecture); fprintf(stderr, "unsupported architecture: %d\n", arch);
return false; return false;
} }
const char* segmentName; const char* segmentName;
const char* sectionName; const char* sectionName;
if (writable) { if (accessFlags & Writable) {
if (executable) { if (accessFlags & Executable) {
segmentName = "__RWX"; segmentName = "__RWX";
sectionName = "__rwx"; sectionName = "__rwx";
} else { } else {
@ -358,4 +312,22 @@ MAKE_NAME(writeMachO, BITS_PER_WORD, Object)
return true; return true;
} }
} // namespace binaryToObject virtual void dispose() {
delete this;
}
};
MachOPlatform(PlatformInfo::Architecture arch):
Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {}
virtual ObjectWriter* makeObjectWriter() {
return new MachOObjectWriter(info.arch);
}
};
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

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,9 +8,13 @@
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
@ -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,27 +163,28 @@ 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, virtual bool write(uint8_t* data, size_t size, FILE* out,
bool writable, bool executable) const char* startName, const char* endName,
unsigned alignment, unsigned accessFlags)
{ {
int machine; int machine;
int machineMask; int machineMask;
if (strcmp(architecture, "x86_64") == 0) {
if (BytesPerWord == 8) {
machine = IMAGE_FILE_MACHINE_AMD64; machine = IMAGE_FILE_MACHINE_AMD64;
machineMask = 0; machineMask = 0;
} else if (strcmp(architecture, "i386") == 0) { } else { // if (BytesPerWord == 8)
machine = IMAGE_FILE_MACHINE_I386; machine = IMAGE_FILE_MACHINE_I386;
machineMask = IMAGE_FILE_32BIT_MACHINE; machineMask = IMAGE_FILE_32BIT_MACHINE;
} else {
fprintf(stderr, "unsupported architecture: %s\n", architecture);
return false;
} }
int sectionMask; int sectionMask;
@ -207,8 +210,8 @@ writePEObject
sectionMask |= IMAGE_SCN_MEM_READ; sectionMask |= IMAGE_SCN_MEM_READ;
const char* sectionName; const char* sectionName;
if (writable) { if (accessFlags & ObjectWriter::Writable) {
if (executable) { if (accessFlags & ObjectWriter::Executable) {
sectionName = ".rwx"; sectionName = ".rwx";
sectionMask |= IMAGE_SCN_MEM_WRITE sectionMask |= IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_EXECUTE
@ -228,4 +231,21 @@ writePEObject
return true; return true;
} }
} // namespace binaryToObject virtual void dispose() {
delete this;
}
};
virtual ObjectWriter* makeObjectWriter() {
return new PEObjectWriter();
}
WindowsPlatform():
Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {}
};
WindowsPlatform<4> windows32Platform;
WindowsPlatform<8> windows64Platform;
}

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