Merge remote-tracking branch 'origin/master' into jdk7

This commit is contained in:
Joel Dice 2012-05-02 11:44:24 -06:00
commit 20a0823a74
8 changed files with 1128 additions and 916 deletions

View File

@ -241,7 +241,6 @@ ifeq ($(arch),powerpc)
ifneq ($(platform),darwin) ifneq ($(platform),darwin)
ifneq ($(arch),$(build-arch)) ifneq ($(arch),$(build-arch))
converter-cflags += -DOPPOSITE_ENDIAN
cxx = powerpc-linux-gnu-g++ cxx = powerpc-linux-gnu-g++
cc = powerpc-linux-gnu-gcc cc = powerpc-linux-gnu-gcc
ar = powerpc-linux-gnu-ar ar = powerpc-linux-gnu-ar
@ -341,9 +340,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)
@ -353,9 +349,6 @@ ifeq ($(platform),darwin)
endif endif
ifeq ($(arch),powerpc) ifeq ($(arch),powerpc)
ifneq (,$(filter i386 x86_64 arm,$(build-arch)))
converter-cflags += -DOPPOSITE_ENDIAN
endif
openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
@ -363,9 +356,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}
@ -373,9 +363,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
@ -444,6 +431,7 @@ endif
ifeq ($(mode),debug) ifeq ($(mode),debug)
optimization-cflags = -O0 -g3 optimization-cflags = -O0 -g3
converter-cflags += -O0 -g3
strip = : strip = :
endif endif
ifeq ($(mode),debug-fast) ifeq ($(mode),debug-fast)
@ -636,14 +624,20 @@ generator-objects = \
$(call generator-cpp-objects,$(generator-sources),$(src),$(build)) $(call generator-cpp-objects,$(generator-sources),$(src),$(build))
generator = $(build)/generator generator = $(build)/generator
converter-objects = \ converter-depends = \
$(build)/binaryToObject-main.o \ $(src)/binaryToObject/tools.h \
$(build)/binaryToObject-elf64.o \ $(src)/binaryToObject/endianness.h
$(build)/binaryToObject-elf32.o \
$(build)/binaryToObject-mach-o64.o \
$(build)/binaryToObject-mach-o32.o \ converter-sources = \
$(build)/binaryToObject-pe.o $(src)/binaryToObject/main.cpp \
converter = $(build)/binaryToObject $(src)/binaryToObject/tools.cpp \
$(src)/binaryToObject/elf.cpp \
$(src)/binaryToObject/mach-o.cpp \
$(src)/binaryToObject/pe.cpp
converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build))
converter = $(build)/binaryToObject/binaryToObject
static-library = $(build)/lib$(name).a static-library = $(build)/lib$(name).a
executable = $(build)/$(name)${exe-suffix} executable = $(build)/$(name)${exe-suffix}
@ -848,26 +842,12 @@ $(boot-object): $(boot-source)
$(boot-javahome-object): $(src)/boot-javahome.cpp $(boot-javahome-object): $(src)/boot-javahome.cpp
$(compile-object) $(compile-object)
$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp $(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends)
$(build-cxx) $(converter-cflags) -c $(^) -o $(@) @mkdir -p $(dir $(@))
$(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-elf32.o: $(src)/binaryToObject/elf.cpp
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@)
$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
$(build)/binaryToObject-mach-o32.o: $(src)/binaryToObject/mach-o.cpp
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@)
$(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp
$(build-cxx) $(converter-cflags) -c $(^) -o $(@)
$(converter): $(converter-objects) $(converter): $(converter-objects)
$(build-cc) $(^) -o $(@) $(build-cc) $(^) -g -o $(@)
$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) $(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep)
@echo "creating $(@)" @echo "creating $(@)"

View File

@ -8,12 +8,15 @@
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 <stdlib.h>
#include "endianness.h" #include "endianness.h"
#include "tools.h"
#define EI_NIDENT 16 #define EI_NIDENT 16
#define EI_MAG0 0 #define EI_MAG0 0
@ -62,344 +65,316 @@
#define STV_DEFAULT 0 #define STV_DEFAULT 0
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) #define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
#define ELF32_ST_INFO(bind, type) ELF64_ST_INFO((bind), (type))
#if (BITS_PER_WORD == 64)
# define FileHeader Elf64_Ehdr
# define SectionHeader Elf64_Shdr
# define Symbol Elf64_Sym
# define Class ELFCLASS64
# define SYMBOL_INFO ELF64_ST_INFO
#elif (BITS_PER_WORD == 32)
# define FileHeader Elf32_Ehdr
# define SectionHeader Elf32_Shdr
# define Symbol Elf32_Sym
# define Class ELFCLASS32
# define SYMBOL_INFO ELF32_ST_INFO
#else
# error
#endif
#define OSABI ELFOSABI_SYSV #define OSABI ELFOSABI_SYSV
namespace { namespace {
typedef uint16_t Elf64_Half; using namespace avian::tools;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Xword;
typedef uint16_t Elf64_Section;
typedef uint64_t Elf64_Off;
struct Elf64_Ehdr { template<class AddrTy>
unsigned char e_ident[EI_NIDENT]; struct ElfTypes {
Elf64_Half e_type; typedef uint16_t Half;
Elf64_Half e_machine; typedef uint32_t Word;
Elf64_Word e_version; typedef AddrTy Addr;
Elf64_Addr e_entry; typedef uint64_t Xword;
Elf64_Off e_phoff; typedef uint16_t Section;
Elf64_Off e_shoff; typedef AddrTy Off;
Elf64_Word e_flags; typedef AddrTy XFlags;
Elf64_Half e_ehsize; static const unsigned BytesPerWord = sizeof(AddrTy);
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
}; };
struct Elf64_Shdr { template<class AddrTy>
Elf64_Word sh_name; struct Symbol_Ty;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
};
struct Elf64_Sym { template<>
Elf64_Word st_name; struct Symbol_Ty<uint64_t> {
typedef ElfTypes<uint64_t> Elf;
Elf::Word st_name;
unsigned char st_info; unsigned char st_info;
unsigned char st_other; unsigned char st_other;
Elf64_Section st_shndx; Elf::Section st_shndx;
Elf64_Addr st_value; Elf::Addr st_value;
Elf64_Xword st_size; Elf::Xword st_size;
}; };
typedef uint16_t Elf32_Half; template<>
typedef uint32_t Elf32_Word; struct Symbol_Ty<uint32_t> {
typedef uint32_t Elf32_Addr; typedef ElfTypes<uint32_t> Elf;
typedef uint64_t Elf32_Xword;
typedef uint16_t Elf32_Section;
typedef uint32_t Elf32_Off;
struct Elf32_Ehdr { Elf::Word st_name;
unsigned char e_ident[EI_NIDENT]; Elf::Addr st_value;
Elf32_Half e_type; Elf::Word st_size;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
};
struct Elf32_Shdr {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
};
struct Elf32_Sym {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info; unsigned char st_info;
unsigned char st_other; unsigned char st_other;
Elf32_Section st_shndx; Elf::Section st_shndx;
}; };
void using avian::endian::Endianness;
writeObject(const uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* sectionName, unsigned sectionFlags,
unsigned alignment, int machine, int encoding)
{
const unsigned sectionCount = 5;
const unsigned symbolCount = 2;
const unsigned sectionNameLength = strlen(sectionName) + 1; #define V1 Endianness<TargetLittleEndian>::v1
const unsigned startNameLength = strlen(startName) + 1; #define V2 Endianness<TargetLittleEndian>::v2
const unsigned endNameLength = strlen(endName) + 1; #define V3 Endianness<TargetLittleEndian>::v3
#define V4 Endianness<TargetLittleEndian>::v4
#define VANY Endianness<TargetLittleEndian>::vAny
const char* const sectionStringTableName = ".shstrtab";
const char* const stringTableName = ".strtab";
const char* const symbolTableName = ".symtab";
const unsigned sectionStringTableNameLength unsigned getElfPlatform(PlatformInfo::Architecture arch) {
= strlen(sectionStringTableName) + 1; switch(arch) {
const unsigned stringTableNameLength = strlen(stringTableName) + 1; case PlatformInfo::x86_64:
const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; return EM_X86_64;
case PlatformInfo::x86:
const unsigned nullStringOffset = 0; return EM_386;
case PlatformInfo::Arm:
const unsigned sectionStringTableNameOffset = nullStringOffset + 1; return EM_ARM;
const unsigned stringTableNameOffset case PlatformInfo::PowerPC:
= sectionStringTableNameOffset + sectionStringTableNameLength; return EM_PPC;
const unsigned symbolTableNameOffset }
= stringTableNameOffset + stringTableNameLength; return ~0;
const unsigned sectionNameOffset
= symbolTableNameOffset + symbolTableNameLength;
const unsigned sectionStringTableLength
= sectionNameOffset + sectionNameLength;
const unsigned startNameOffset = nullStringOffset + 1;
const unsigned endNameOffset = startNameOffset + startNameLength;
const unsigned stringTableLength = endNameOffset + endNameLength;
const unsigned bodySectionNumber = 1;
const unsigned sectionStringTableSectionNumber = 2;
const unsigned stringTableSectionNumber = 3;
FileHeader fileHeader;
memset(&fileHeader, 0, sizeof(FileHeader));
fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0);
fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1);
fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2);
fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3);
fileHeader.e_ident[EI_CLASS] = V1(Class);
fileHeader.e_ident[EI_DATA] = V1(encoding);
fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT);
fileHeader.e_ident[EI_OSABI] = V1(OSABI);
fileHeader.e_ident[EI_ABIVERSION] = V1(0);
fileHeader.e_type = V2(ET_REL);
fileHeader.e_machine = V2(machine);
fileHeader.e_version = V4(EV_CURRENT);
fileHeader.e_entry = VW(0);
fileHeader.e_phoff = VW(0);
fileHeader.e_shoff = VW(sizeof(FileHeader));
fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
fileHeader.e_ehsize = V2(sizeof(FileHeader));
fileHeader.e_phentsize = V2(0);
fileHeader.e_phnum = V2(0);
fileHeader.e_shentsize = V2(sizeof(SectionHeader));
fileHeader.e_shnum = V2(sectionCount);
fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber);
SectionHeader nullSection;
memset(&nullSection, 0, sizeof(SectionHeader));
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);
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);
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);
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));
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);
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);
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);
} }
} // namespace const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) {
sectionFlags = SHF_ALLOC;
#define MACRO_MAKE_NAME(a, b, c) a##b##c if (accessFlags & Platform::Writable) {
#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c) if (accessFlags & Platform::Executable) {
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; sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
return ".rwx";
} else { } else {
sectionName = ".data";
sectionFlags |= SHF_WRITE; sectionFlags |= SHF_WRITE;
return ".data";
} }
} else if (executable) { } else if (accessFlags & Platform::Executable) {
sectionName = ".text";
sectionFlags |= SHF_EXECINSTR; sectionFlags |= SHF_EXECINSTR;
return ".text";
} else { } else {
sectionName = ".rodata"; return ".rodata";
}
}
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;
static const unsigned Encoding = TargetLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
const unsigned machine;
ElfPlatform(PlatformInfo::Architecture arch):
Platform(PlatformInfo(PlatformInfo::Linux, arch)),
machine(getElfPlatform(arch)) {}
class FileWriter {
public:
unsigned sectionCount;
unsigned sectionStringTableSectionNumber;
AddrTy dataOffset;
FileHeader header;
StringTable strings;
FileWriter(unsigned machine):
sectionCount(0),
dataOffset(sizeof(FileHeader))
{
memset(&header, 0, sizeof(FileHeader));
header.e_ident[EI_MAG0] = V1(ELFMAG0);
header.e_ident[EI_MAG1] = V1(ELFMAG1);
header.e_ident[EI_MAG2] = V1(ELFMAG2);
header.e_ident[EI_MAG3] = V1(ELFMAG3);
header.e_ident[EI_CLASS] = V1(Class);
header.e_ident[EI_DATA] = V1(Encoding);
header.e_ident[EI_VERSION] = V1(EV_CURRENT);
header.e_ident[EI_OSABI] = V1(OSABI);
header.e_ident[EI_ABIVERSION] = V1(0);
header.e_type = V2(ET_REL);
header.e_machine = V2(machine);
header.e_version = V4(EV_CURRENT);
header.e_entry = VANY(static_cast<AddrTy>(0));
header.e_phoff = VANY(static_cast<AddrTy>(0));
header.e_shoff = VANY(static_cast<AddrTy>(sizeof(FileHeader)));
header.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
header.e_ehsize = V2(sizeof(FileHeader));
header.e_phentsize = V2(0);
header.e_phnum = V2(0);
header.e_shentsize = V2(sizeof(SectionHeader));
} }
writeObject(data, size, out, startName, endName, sectionName, sectionFlags, void writeHeader(OutputStream* out) {
alignment, machine, encoding); header.e_shnum = V2(sectionCount);
header.e_shstrndx = V2(sectionStringTableSectionNumber);
out->writeChunk(&header, sizeof(FileHeader));
}
};
class SectionWriter {
public:
FileWriter& file;
String name;
SectionHeader header;
const size_t* dataSize;
const uint8_t* const* data;
SectionWriter(FileWriter& file):
file(file),
name(""),
data(0),
dataSize(0)
{
memset(&header, 0, sizeof(SectionHeader));
file.sectionCount++;
file.dataOffset += sizeof(SectionHeader);
size_t nameOffset = file.strings.add(name);
header.sh_name = V4(nameOffset);
}
SectionWriter(
FileWriter& file,
const char* chname,
unsigned type,
AddrTy flags,
unsigned alignment,
AddrTy addr,
const uint8_t* const* data,
size_t* dataSize,
size_t entsize = 0,
unsigned link = 0):
file(file),
name(chname),
data(data),
dataSize(dataSize)
{
if(strcmp(chname, ".shstrtab") == 0) {
file.sectionStringTableSectionNumber = file.sectionCount;
}
file.sectionCount++;
file.dataOffset += sizeof(SectionHeader);
size_t nameOffset = file.strings.add(name);
header.sh_name = V4(nameOffset);
header.sh_type = V4(type);
header.sh_flags = VANY(flags);
header.sh_addr = VANY(addr);
// header.sh_offset = VANY(static_cast<AddrTy>(bodySectionOffset));
// header.sh_size = VANY(static_cast<AddrTy>(*dataSize));
header.sh_link = V4(link);
header.sh_info = V4(0);
header.sh_addralign = VANY(static_cast<AddrTy>(alignment));
header.sh_entsize = VANY(static_cast<AddrTy>(entsize));
}
void writeHeader(OutputStream* out) {
if(dataSize) {
header.sh_offset = VANY(file.dataOffset);
header.sh_size = VANY(static_cast<AddrTy>(*dataSize));
file.dataOffset += *dataSize;
}
out->writeChunk(&header, sizeof(SectionHeader));
}
void writeData(OutputStream* out) {
if(data) {
out->writeChunk(*data, *dataSize);
}
}
};
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
unsigned sectionFlags;
const char* sectionName = getSectionName(accessFlags, sectionFlags);
StringTable symbolStringTable;
Buffer symbolTable;
FileWriter file(machine);
const int bodySectionNumber = 1;
const int stringTableSectionNumber = 3;
SectionWriter sections[] = {
SectionWriter(file), // null section
SectionWriter(file, sectionName, SHT_PROGBITS, sectionFlags, alignment, 0, &data.items, &data.count), // body section
SectionWriter(file, ".shstrtab", SHT_STRTAB, 0, 1, 0, &file.strings.data, &file.strings.length),
SectionWriter(file, ".strtab", SHT_STRTAB, 0, 1, 0, &symbolStringTable.data, &symbolStringTable.length),
SectionWriter(file, ".symtab", SHT_SYMTAB, 0, 8, 0, &symbolTable.data, &symbolTable.length, sizeof(Symbol), stringTableSectionNumber)
};
// for some reason, string tables require a null first element...
symbolStringTable.add("");
for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) {
size_t nameOffset = symbolStringTable.add(sym->name);
Symbol symbolStruct;
symbolStruct.st_name = V4(nameOffset);
symbolStruct.st_value = VANY(static_cast<AddrTy>(sym->addr));
symbolStruct.st_size = VANY(static_cast<AddrTy>(0));
symbolStruct.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
symbolStruct.st_other = V1(STV_DEFAULT);
symbolStruct.st_shndx = V2(bodySectionNumber);
symbolTable.write(&symbolStruct, sizeof(Symbol));
}
file.writeHeader(out);
for(int i = 0; i < file.sectionCount; i++) {
sections[i].writeHeader(out);
}
for(int i = 0; i < file.sectionCount; i++) {
sections[i].writeData(out);
}
return true; return true;
} }
};
} // namespace binaryToObject 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,81 @@
#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)))
# 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)))
#else
# define V2(v) (v)
# define V4(v) (v)
# define V8(v) (v)
#endif
#if (BITS_PER_WORD == 64) #ifndef AVIAN_ENDIANNESS_H
# define VW(v) V8(v) #define AVIAN_ENDIANNESS_H
#elif (BITS_PER_WORD == 32)
# define VW(v) V4(v)
#else
# error
#endif
#endif//ENDIANNESS_H namespace avian {
namespace endian {
static union {
uint32_t i;
char c[4];
} _DetectEndianness = {1};
const bool LittleEndian = _DetectEndianness.c[0] == 1;
template<bool TargetLittleEndian>
class Endianness {
public:
static inline uint8_t v1(uint8_t v) {
return v;
}
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) & (static_cast<uint64_t>(0xff) << 0)) |
((static_cast<uint64_t>(v) >> 40) & (static_cast<uint64_t>(0xff) << 8)) |
((static_cast<uint64_t>(v) >> 24) & (static_cast<uint64_t>(0xff) << 16)) |
((static_cast<uint64_t>(v) >> 8) & (static_cast<uint64_t>(0xff) << 24)) |
((static_cast<uint64_t>(v) << 8) & (static_cast<uint64_t>(0xff) << 32)) |
((static_cast<uint64_t>(v) << 24) & (static_cast<uint64_t>(0xff) << 40)) |
((static_cast<uint64_t>(v) << 40) & (static_cast<uint64_t>(0xff) << 48)) |
((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,142 +40,21 @@
#define CPU_SUBTYPE_POWERPC_ALL 0 #define CPU_SUBTYPE_POWERPC_ALL 0
#define CPU_SUBTYPE_ARM_V7 9 #define CPU_SUBTYPE_ARM_V7 9
#if (BITS_PER_WORD == 64)
# define Magic MH_MAGIC_64
# define Segment LC_SEGMENT_64
# define FileHeader mach_header_64
# define SegmentCommand segment_command_64
# define Section section_64
# define NList struct nlist_64
#elif (BITS_PER_WORD == 32)
# define Magic MH_MAGIC
# define Segment LC_SEGMENT
# define FileHeader mach_header
# define SegmentCommand segment_command
# define Section section
# define NList struct nlist
#else
# error
#endif
namespace { namespace {
using namespace avian::tools;
typedef int cpu_type_t; typedef int cpu_type_t;
typedef int cpu_subtype_t; typedef int cpu_subtype_t;
typedef int vm_prot_t; typedef int vm_prot_t;
struct mach_header_64 { using avian::endian::Endianness;
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
};
struct segment_command_64 { #define V1 Endianness<TargetLittleEndian>::v1
uint32_t cmd; #define V2 Endianness<TargetLittleEndian>::v2
uint32_t cmdsize; #define V3 Endianness<TargetLittleEndian>::v3
char segname[16]; #define V4 Endianness<TargetLittleEndian>::v4
uint64_t vmaddr; #define VANY Endianness<TargetLittleEndian>::vAny
uint64_t vmsize;
uint64_t fileoff;
uint64_t filesize;
vm_prot_t maxprot;
vm_prot_t initprot;
uint32_t nsects;
uint32_t flags;
};
struct section_64 {
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;
};
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 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 inline unsigned
log(unsigned n) log(unsigned n)
@ -185,152 +64,112 @@ log(unsigned n)
return r; return r;
} }
void template<class AddrTy, bool TargetLittleEndian = true>
writeObject(const uint8_t* data, unsigned size, FILE* out, class MachOPlatform : public Platform {
const char* startName, const char* endName, public:
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 = { struct FileHeader {
V4(Magic), // magic uint32_t magic;
V4(cpuType), cpu_type_t cputype;
V4(cpuSubType), cpu_subtype_t cpusubtype;
V4(MH_OBJECT), // filetype, uint32_t filetype;
V4(2), // ncmds uint32_t ncmds;
V4(sizeof(SegmentCommand) uint32_t sizeofcmds;
+ sizeof(Section)
+ sizeof(symtab_command)), // sizeofcmds union {
V4(0) // flags uint32_t flags;
AddrTy flagsAndMaybeReserved;
};
}; };
SegmentCommand segment = {
V4(Segment), // cmd struct SegmentCommand {
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize uint32_t cmd;
"", // segname uint32_t cmdsize;
VW(0), // vmaddr char segname[16];
VW(pad(size)), // vmsize AddrTy vmaddr;
VW(sizeof(FileHeader) AddrTy vmsize;
+ sizeof(SegmentCommand) AddrTy fileoff;
+ sizeof(Section) AddrTy filesize;
+ sizeof(symtab_command)), // fileoff vm_prot_t maxprot;
VW(pad(size)), // filesize vm_prot_t initprot;
V4(7), // maxprot uint32_t nsects;
V4(7), // initprot uint32_t flags;
V4(1), // nsects
V4(0) // flags
}; };
strncpy(segment.segname, segmentName, sizeof(segment.segname)); struct Section {
char sectname[16];
Section sect = { char segname[16];
"", // sectname AddrTy addr;
"", // segname AddrTy size;
VW(0), // addr uint32_t offset;
VW(pad(size)), // size uint32_t align;
V4(sizeof(FileHeader) uint32_t reloff;
+ sizeof(SegmentCommand) uint32_t nreloc;
+ sizeof(Section) uint32_t flags;
+ sizeof(symtab_command)), // offset uint32_t reserved1;
V4(log(alignment)), // align AddrTy reserved2AndMaybe3;
V4(0), // reloff
V4(0), // nreloc
V4(S_REGULAR), // flags
V4(0), // reserved1
V4(0), // reserved2
}; };
strncpy(sect.segname, segmentName, sizeof(sect.segname)); struct NList {
strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); union {
uint32_t n_strx;
symtab_command symbolTable = { } n_un;
V4(LC_SYMTAB), // cmd uint8_t n_type;
V4(sizeof(symtab_command)), // cmdsize uint8_t n_sect;
V4(sizeof(FileHeader) uint16_t n_desc;
+ sizeof(SegmentCommand) AddrTy n_value;
+ sizeof(Section)
+ sizeof(symtab_command)
+ pad(size)), // symoff
V4(2), // nsyms
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)
+ pad(size)
+ (sizeof(NList) * 2)), // stroff
V4(1 + startNameLength + endNameLength), // strsize
}; };
NList symbolList[] = { struct SymtabCommand {
uint32_t cmd;
uint32_t cmdsize;
uint32_t symoff;
uint32_t nsyms;
uint32_t stroff;
uint32_t strsize;
};
static const unsigned BytesPerWord = sizeof(AddrTy);
static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1;
static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface;
static inline unsigned
pad(unsigned n)
{ {
V4(1), // n_un return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
V1(N_SECT | N_EXT), // n_type
V1(1), // n_sect
V2(0), // n_desc
VW(0) // n_value
},
{
V4(1 + startNameLength), // n_un
V1(N_SECT | N_EXT), // n_type
V1(1), // n_sect
V2(0), // n_desc
VW(size) // n_value
} }
};
fwrite(&header, 1, sizeof(header), out); virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
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);
}
} // 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_type_t cpuType;
cpu_subtype_t cpuSubType; cpu_subtype_t cpuSubType;
if (strcmp(architecture, "x86_64") == 0) { switch(info.arch) {
case 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) { break;
case 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) { break;
case 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) { break;
case PlatformInfo::Arm:
cpuType = CPU_TYPE_ARM; cpuType = CPU_TYPE_ARM;
cpuSubType = CPU_SUBTYPE_ARM_V7; cpuSubType = CPU_SUBTYPE_ARM_V7;
} else { break;
fprintf(stderr, "unsupported architecture: %s\n", architecture); default:
// should never happen (see MachOPlatform declarations at bottom)
fprintf(stderr, "unsupported architecture: %d\n", info.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 {
@ -342,20 +181,116 @@ MAKE_NAME(writeMachO, BITS_PER_WORD, Object)
sectionName = "__text"; sectionName = "__text";
} }
unsigned startNameLength = strlen(startName); FileHeader header = {
char myStartName[startNameLength + 2]; V4(Magic), // magic
myStartName[0] = '_'; V4(cpuType),
memcpy(myStartName + 1, startName, startNameLength + 1); V4(cpuSubType),
V4(MH_OBJECT), // filetype,
V4(2), // ncmds
V4(sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(SymtabCommand)), // sizeofcmds
V4(0) // flags
};
unsigned endNameLength = strlen(endName); AddrTy finalSize = pad(data.count);
char myEndName[endNameLength + 2];
myEndName[0] = '_';
memcpy(myEndName + 1, endName, endNameLength + 1);
writeObject(data, size, out, myStartName, myEndName, segmentName, SegmentCommand segment = {
sectionName, alignment, cpuType, cpuSubType); V4(Segment), // cmd
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
"", // segname
VANY(static_cast<AddrTy>(0)), // vmaddr
VANY(static_cast<AddrTy>(finalSize)), // vmsize
VANY(static_cast<AddrTy>(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(SymtabCommand))), // fileoff
VANY(static_cast<AddrTy>(finalSize)), // filesize
V4(7), // maxprot
V4(7), // initprot
V4(1), // nsects
V4(0) // flags
};
return true; strncpy(segment.segname, segmentName, sizeof(segment.segname));
}
} // namespace binaryToObject Section sect = {
"", // sectname
"", // segname
VANY(static_cast<AddrTy>(0)), // addr
VANY(static_cast<AddrTy>(finalSize)), // size
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(SymtabCommand)), // offset
V4(log(alignment)), // align
V4(0), // reloff
V4(0), // nreloc
V4(S_REGULAR), // flags
V4(0), // reserved1
V4(0), // reserved2
};
strncpy(sect.segname, segmentName, sizeof(sect.segname));
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
StringTable strings;
strings.add("");
Buffer symbolList;
for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) {
unsigned offset = strings.length;
strings.write("_", 1);
strings.add(sym->name);
NList symbol = {
V4(offset), // n_un
V1(N_SECT | N_EXT), // n_type
V1(1), // n_sect
V2(0), // n_desc
VANY(static_cast<AddrTy>(sym->addr)) // n_value
};
symbolList.write(&symbol, sizeof(NList));
}
SymtabCommand symbolTable = {
V4(LC_SYMTAB), // cmd
V4(sizeof(SymtabCommand)), // cmdsize
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(SymtabCommand)
+ finalSize), // symoff
V4(symbols.count), // nsyms
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(SymtabCommand)
+ finalSize
+ (sizeof(NList) * symbols.count)), // stroff
V4(strings.length), // strsize
};
out->writeChunk(&header, sizeof(header));
out->writeChunk(&segment, sizeof(segment));
out->writeChunk(&sect, sizeof(sect));
out->writeChunk(&symbolTable, sizeof(symbolTable));
out->writeChunk(data.items, data.count);
out->writeRepeat(0, finalSize - data.count);
out->writeChunk(symbolList.data, symbolList.length);
out->writeChunk(strings.data, strings.length);
}
MachOPlatform(PlatformInfo::Architecture arch):
Platform(PlatformInfo(PlatformInfo::Darwin, 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,111 +8,60 @@
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) { abort(); }
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
namespace { namespace {
using namespace avian::tools;
bool bool
writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName, writeObject(uint8_t* data, size_t size, OutputStream* 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;
} }
return success; SymbolInfo symbols[2];
symbols[0].name = startName;
symbols[0].addr = 0;
symbols[1].name = endName;
symbols[1].addr = size;
unsigned accessFlags = (writable ? Platform::Writable : 0) | (executable ? Platform::Executable : 0);
return platform->writeObject(out, Slice<SymbolInfo>(symbols, 2), Slice<const uint8_t>(data, size), accessFlags, alignment);
} }
void void
@ -191,13 +140,11 @@ main(int argc, const char** argv)
bool success = false; bool success = false;
if (data) { if (data) {
FILE* out = fopen(argv[2], "wb"); FileOutputStream out(argv[2]);
if (out) { if (out.isValid()) {
success = writeObject success = writeObject
(data, size, out, argv[3], argv[4], argv[5], argv[6], alignment, (data, size, &out, argv[3], argv[4], argv[5], argv[6], alignment,
writable, executable); writable, executable);
fclose(out);
} else { } else {
fprintf(stderr, "unable to open %s\n", argv[2]); fprintf(stderr, "unable to open %s\n", argv[2]);
} }

View File

@ -8,9 +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 <stdlib.h>
#include "tools.h"
namespace {
#define IMAGE_SIZEOF_SHORT_NAME 8 #define IMAGE_SIZEOF_SHORT_NAME 8
@ -29,8 +34,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;
@ -77,111 +80,137 @@ pad(unsigned n)
return (n + (4 - 1)) & ~(4 - 1); return (n + (4 - 1)) & ~(4 - 1);
} }
void using namespace avian::tools;
writeObject(const uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* sectionName, int machine, int machineMask,
int sectionMask)
{
const unsigned sectionCount = 1;
const unsigned symbolCount = 2;
const unsigned sectionNumber = 1; template<unsigned BytesPerWord>
class WindowsPlatform : public Platform {
public:
const unsigned startNameLength = strlen(startName) + 1;
const unsigned endNameLength = strlen(endName) + 1;
const unsigned startNameOffset = 4; class FileWriter {
const unsigned endNameOffset = startNameOffset + startNameLength; public:
unsigned sectionCount;
unsigned symbolCount;
unsigned dataStart;
unsigned dataOffset;
IMAGE_FILE_HEADER fileHeader = { IMAGE_FILE_HEADER header;
machine, // Machine
sectionCount, // NumberOfSections StringTable strings;
0, // TimeDateStamp Buffer symbols;
sizeof(IMAGE_FILE_HEADER)
+ sizeof(IMAGE_SECTION_HEADER) FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount):
+ pad(size), // PointerToSymbolTable sectionCount(0),
symbolCount, // NumberOfSymbols symbolCount(symbolCount),
0, // SizeOfOptionalHeader dataStart(sizeof(IMAGE_FILE_HEADER)),
IMAGE_FILE_RELOCS_STRIPPED dataOffset(0)
{
header.Machine = machine;
// header.NumberOfSections = sectionCount;
header.TimeDateStamp = 0;
// header.PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER)
// + sizeof(IMAGE_SECTION_HEADER)
// + pad(size);
// header.NumberOfSymbols = symbolCount;
header.SizeOfOptionalHeader = 0;
header.Characteristics = IMAGE_FILE_RELOCS_STRIPPED
| IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED
| machineMask // Characteristics | machineMask;
}; }
IMAGE_SECTION_HEADER sectionHeader = { void writeHeader(OutputStream* out) {
"", // Name header.NumberOfSections = sectionCount;
0, // PhysicalAddress header.PointerToSymbolTable = dataStart + dataOffset;
0, // VirtualAddress printf("symbol table start: 0x%x\n", header.PointerToSymbolTable);
pad(size), // SizeOfRawData dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL));
sizeof(IMAGE_FILE_HEADER) printf("string table start: 0x%x\n", dataStart + dataOffset);
+ sizeof(IMAGE_SECTION_HEADER), // PointerToRawData header.NumberOfSymbols = symbolCount;
0, // PointerToRelocations out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER));
0, // PointerToLinenumbers }
0, // NumberOfRelocations
0, // NumberOfLinenumbers
sectionMask // Characteristics
};
strncpy(reinterpret_cast<char*>(sectionHeader.Name), sectionName, void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) {
sizeof(sectionHeader.Name)); unsigned nameOffset = strings.add(name);
IMAGE_SYMBOL symbol = {
IMAGE_SYMBOL startSymbol = {
{ 0 }, // Name { 0 }, // Name
0, // Value addr, // Value
sectionNumber, // SectionNumber sectionNumber, // SectionNumber
0, // Type type, // Type
2, // StorageClass storageClass, // StorageClass
0, // NumberOfAuxSymbols 0, // NumberOfAuxSymbols
}; };
startSymbol.N.Name.Long = startNameOffset; symbol.N.Name.Long = nameOffset+4;
symbols.write(&symbol, sizeof(IMAGE_SYMBOL));
}
IMAGE_SYMBOL endSymbol = { void writeData(OutputStream* out) {
{ 0 }, // Name out->writeChunk(symbols.data, symbols.length);
size, // Value uint32_t size = strings.length + 4;
sectionNumber, // SectionNumber out->writeChunk(&size, 4);
0, // Type out->writeChunk(strings.data, strings.length);
2, // StorageClass }
0, // NumberOfAuxSymbols
}; };
endSymbol.N.Name.Long = endNameOffset;
fwrite(&fileHeader, 1, sizeof(fileHeader), out); class SectionWriter {
fwrite(&sectionHeader, 1, sizeof(sectionHeader), out); public:
FileWriter& file;
IMAGE_SECTION_HEADER header;
size_t dataSize;
size_t finalSize;
const uint8_t* data;
unsigned dataOffset;
fwrite(data, 1, size, out); SectionWriter(
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); FileWriter& file,
const char* name,
unsigned sectionMask,
const uint8_t* data,
size_t dataSize):
fwrite(&startSymbol, 1, sizeof(startSymbol), out); file(file),
fwrite(&endSymbol, 1, sizeof(endSymbol), out); data(data),
dataSize(dataSize),
finalSize(pad(dataSize))
{
file.sectionCount++;
file.dataStart += sizeof(IMAGE_SECTION_HEADER);
strcpy(reinterpret_cast<char*>(header.Name), name);
header.Misc.VirtualSize = 0;
header.SizeOfRawData = finalSize;
// header.PointerToRawData = file.dataOffset;
dataOffset = file.dataOffset;
file.dataOffset += finalSize;
header.PointerToRelocations = 0;
header.PointerToLinenumbers = 0;
header.NumberOfRelocations = 0;
header.NumberOfLinenumbers = 0;
header.Characteristics = sectionMask;
}
uint32_t symbolTableSize = endNameOffset + endNameLength; void writeHeader(OutputStream* out) {
fwrite(&symbolTableSize, 1, 4, out); header.PointerToRawData = dataOffset + file.dataStart;
printf("section %s: data at 0x%x, ending at 0x%x\n", header.Name, header.PointerToRawData, header.PointerToRawData + header.SizeOfRawData);
out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER));
}
fwrite(startName, 1, startNameLength, out); void writeData(OutputStream* out) {
fwrite(endName, 1, endNameLength, out); out->writeChunk(data, dataSize);
} out->writeRepeat(0, finalSize - dataSize);
}
} // namespace
namespace binaryToObject { };
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
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 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 +236,8 @@ writePEObject
sectionMask |= IMAGE_SCN_MEM_READ; sectionMask |= IMAGE_SCN_MEM_READ;
const char* sectionName; const char* sectionName;
if (writable) { if (accessFlags & Platform::Writable) {
if (executable) { if (accessFlags & Platform::Executable) {
sectionName = ".rwx"; sectionName = ".rwx";
sectionMask |= IMAGE_SCN_MEM_WRITE sectionMask |= IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_EXECUTE
@ -222,10 +251,31 @@ writePEObject
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
} }
writeObject(data, size, out, startName, endName, sectionName, machine, FileWriter file(machine, machineMask, symbols.count);
machineMask, sectionMask);
SectionWriter section(file, sectionName, sectionMask, data.items, data.count);
file.writeHeader(out);
for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) {
file.addSymbol(sym->name, sym->addr, 1, 0, 2);
}
section.writeHeader(out);
section.writeData(out);
file.writeData(out);
return true; return true;
}
} // namespace binaryToObject }
WindowsPlatform():
Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {}
};
WindowsPlatform<4> windows32Platform;
WindowsPlatform<8> windows64Platform;
} // namespace

View File

@ -0,0 +1,125 @@
/* 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 {
String::String(const char* text):
text(text),
length(strlen(text)) {}
Buffer::Buffer():
capacity(100),
length(0),
data((uint8_t*)malloc(capacity)) {}
Buffer::~Buffer() {
free(data);
}
void Buffer::ensure(size_t more) {
if(length + more > capacity) {
capacity = capacity * 2 + more;
data = (uint8_t*)realloc(data, capacity);
}
}
void Buffer::write(const void* d, size_t size) {
ensure(size);
memcpy(data + length, d, size);
length += size;
}
unsigned StringTable::add(String str) {
unsigned offset = Buffer::length;
Buffer::write(str.text, str.length + 1);
return offset;
}
void OutputStream::write(uint8_t byte) {
writeChunk(&byte, 1);
}
void OutputStream::writeRepeat(uint8_t byte, size_t size) {
for(size_t i = 0; i < size; i++) {
write(byte);
}
}
FileOutputStream::FileOutputStream(const char* name):
file(fopen(name, "wb")) {}
FileOutputStream::~FileOutputStream() {
if(file) {
fclose(file);
}
}
bool FileOutputStream::isValid() {
return file;
}
void FileOutputStream::writeChunk(const void* data, size_t size) {
fwrite(data, size, 1, file);
}
void FileOutputStream::write(uint8_t byte) {
fputc(byte, file);
}
Platform* Platform::first = 0;
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

157
src/binaryToObject/tools.h Normal file
View File

@ -0,0 +1,157 @@
/* 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 OutputStream {
public:
virtual void writeChunk(const void* data, size_t size) = 0;
virtual void write(uint8_t byte);
virtual void writeRepeat(uint8_t byte, size_t size);
};
class FileOutputStream : public OutputStream {
private:
FILE* file;
public:
FileOutputStream(const char* name);
~FileOutputStream();
bool isValid();
virtual void writeChunk(const void* data, size_t size);
virtual void write(uint8_t byte);
};
class String {
public:
const char* text;
size_t length;
String(const char* text);
};
class SymbolInfo {
public:
unsigned addr;
String name;
inline SymbolInfo(uint64_t addr, const char* name):
addr(addr),
name(name) {}
inline SymbolInfo():
name("") {}
};
class Buffer {
public:
size_t capacity;
size_t length;
uint8_t* data;
Buffer();
~Buffer();
void ensure(size_t more);
void write(const void* d, size_t size);
};
class StringTable : public Buffer {
public:
unsigned add(String str);
};
template<class T>
class Slice {
public:
T* items;
size_t count;
inline Slice(T* items, size_t count):
items(items),
count(count) {}
inline T* begin() {
return items;
}
inline T* end() {
return items + count;
}
};
class PlatformInfo {
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;
}
enum AccessFlags {
Writable = 1 << 0,
Executable = 1 << 1
};
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) = 0;
static Platform* getPlatform(PlatformInfo info);
};
} // namespace tools
} // namespace avian
#endif