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

View File

@ -8,12 +8,15 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "endianness.h"
#include "tools.h"
#define EI_NIDENT 16
#define EI_MAG0 0
@ -62,344 +65,316 @@
#define STV_DEFAULT 0
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
#define ELF32_ST_INFO(bind, type) ELF64_ST_INFO((bind), (type))
#if (BITS_PER_WORD == 64)
# define FileHeader Elf64_Ehdr
# define SectionHeader Elf64_Shdr
# define Symbol Elf64_Sym
# define Class ELFCLASS64
# define SYMBOL_INFO ELF64_ST_INFO
#elif (BITS_PER_WORD == 32)
# define FileHeader Elf32_Ehdr
# define SectionHeader Elf32_Shdr
# define Symbol Elf32_Sym
# define Class ELFCLASS32
# define SYMBOL_INFO ELF32_ST_INFO
#else
# error
#endif
#define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
#define OSABI ELFOSABI_SYSV
namespace {
typedef uint16_t Elf64_Half;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Xword;
typedef uint16_t Elf64_Section;
typedef uint64_t Elf64_Off;
using namespace avian::tools;
struct Elf64_Ehdr {
unsigned char e_ident[EI_NIDENT];
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
template<class AddrTy>
struct ElfTypes {
typedef uint16_t Half;
typedef uint32_t Word;
typedef AddrTy Addr;
typedef uint64_t Xword;
typedef uint16_t Section;
typedef AddrTy Off;
typedef AddrTy XFlags;
static const unsigned BytesPerWord = sizeof(AddrTy);
};
struct Elf64_Shdr {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
};
template<class AddrTy>
struct Symbol_Ty;
struct Elf64_Sym {
Elf64_Word st_name;
template<>
struct Symbol_Ty<uint64_t> {
typedef ElfTypes<uint64_t> Elf;
Elf::Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Section st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
Elf::Section st_shndx;
Elf::Addr st_value;
Elf::Xword st_size;
};
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Word;
typedef uint32_t Elf32_Addr;
typedef uint64_t Elf32_Xword;
typedef uint16_t Elf32_Section;
typedef uint32_t Elf32_Off;
template<>
struct Symbol_Ty<uint32_t> {
typedef ElfTypes<uint32_t> Elf;
struct Elf32_Ehdr {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
};
struct Elf32_Shdr {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
};
struct Elf32_Sym {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
Elf::Word st_name;
Elf::Addr st_value;
Elf::Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Section st_shndx;
Elf::Section st_shndx;
};
void
writeObject(const uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* sectionName, unsigned sectionFlags,
unsigned alignment, int machine, int encoding)
{
const unsigned sectionCount = 5;
const unsigned symbolCount = 2;
using avian::endian::Endianness;
const unsigned sectionNameLength = strlen(sectionName) + 1;
const unsigned startNameLength = strlen(startName) + 1;
const unsigned endNameLength = strlen(endName) + 1;
#define V1 Endianness<TargetLittleEndian>::v1
#define V2 Endianness<TargetLittleEndian>::v2
#define V3 Endianness<TargetLittleEndian>::v3
#define V4 Endianness<TargetLittleEndian>::v4
#define VANY Endianness<TargetLittleEndian>::vAny
const char* const sectionStringTableName = ".shstrtab";
const char* const stringTableName = ".strtab";
const char* const symbolTableName = ".symtab";
const unsigned sectionStringTableNameLength
= strlen(sectionStringTableName) + 1;
const unsigned stringTableNameLength = strlen(stringTableName) + 1;
const unsigned symbolTableNameLength = strlen(symbolTableName) + 1;
const unsigned nullStringOffset = 0;
const unsigned sectionStringTableNameOffset = nullStringOffset + 1;
const unsigned stringTableNameOffset
= sectionStringTableNameOffset + sectionStringTableNameLength;
const unsigned symbolTableNameOffset
= stringTableNameOffset + stringTableNameLength;
const unsigned sectionNameOffset
= symbolTableNameOffset + symbolTableNameLength;
const unsigned sectionStringTableLength
= sectionNameOffset + sectionNameLength;
const unsigned startNameOffset = nullStringOffset + 1;
const unsigned endNameOffset = startNameOffset + startNameLength;
const unsigned stringTableLength = endNameOffset + endNameLength;
const unsigned bodySectionNumber = 1;
const unsigned sectionStringTableSectionNumber = 2;
const unsigned stringTableSectionNumber = 3;
FileHeader fileHeader;
memset(&fileHeader, 0, sizeof(FileHeader));
fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0);
fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1);
fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2);
fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3);
fileHeader.e_ident[EI_CLASS] = V1(Class);
fileHeader.e_ident[EI_DATA] = V1(encoding);
fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT);
fileHeader.e_ident[EI_OSABI] = V1(OSABI);
fileHeader.e_ident[EI_ABIVERSION] = V1(0);
fileHeader.e_type = V2(ET_REL);
fileHeader.e_machine = V2(machine);
fileHeader.e_version = V4(EV_CURRENT);
fileHeader.e_entry = 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);
unsigned getElfPlatform(PlatformInfo::Architecture arch) {
switch(arch) {
case PlatformInfo::x86_64:
return EM_X86_64;
case PlatformInfo::x86:
return EM_386;
case PlatformInfo::Arm:
return EM_ARM;
case PlatformInfo::PowerPC:
return EM_PPC;
}
return ~0;
}
const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) {
sectionFlags = SHF_ALLOC;
if (accessFlags & Platform::Writable) {
if (accessFlags & Platform::Executable) {
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
return ".rwx";
} else {
sectionFlags |= SHF_WRITE;
return ".data";
}
} else if (accessFlags & Platform::Executable) {
sectionFlags |= SHF_EXECINSTR;
return ".text";
} else {
return ".rodata";
}
}
template<class 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));
}
void writeHeader(OutputStream* out) {
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;
}
};
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
#define MACRO_MAKE_NAME(a, b, c) a##b##c
#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c)
namespace binaryToObject {
bool
MAKE_NAME(writeElf, BITS_PER_WORD, Object)
(uint8_t* data, unsigned size, FILE* out, const char* startName,
const char* endName, const char* architecture, unsigned alignment,
bool writable, bool executable)
{
int machine;
int encoding;
if (strcmp(architecture, "x86_64") == 0) {
machine = EM_X86_64;
encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "i386") == 0) {
machine = EM_386;
encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "arm") == 0) {
machine = EM_ARM;
encoding = ELFDATA2LSB;
} else if (strcmp(architecture, "powerpc") == 0) {
machine = EM_PPC;
encoding = ELFDATA2MSB;
} else {
fprintf(stderr, "unsupported architecture: %s\n", architecture);
return false;
}
const char* sectionName;
unsigned sectionFlags = SHF_ALLOC;
if (writable) {
if (executable) {
sectionName = ".rwx";
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
} else {
sectionName = ".data";
sectionFlags |= SHF_WRITE;
}
} else if (executable) {
sectionName = ".text";
sectionFlags |= SHF_EXECINSTR;
} else {
sectionName = ".rodata";
}
writeObject(data, size, out, startName, endName, sectionName, sectionFlags,
alignment, machine, encoding);
return true;
}
} // namespace binaryToObject

View File

@ -1,38 +1,81 @@
#ifndef ENDIANNESS_H
#define ENDIANNESS_H
/* Copyright (c) 2008-2011, Avian Contributors
#define V1(v) (v)
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
#ifdef OPPOSITE_ENDIAN
# define V2(v) \
((((v) >> 8) & 0xFF) | \
(((v) << 8)))
# define V4(v) \
((((v) >> 24) & 0x000000FF) | \
(((v) >> 8) & 0x0000FF00) | \
(((v) << 8) & 0x00FF0000) | \
(((v) << 24)))
# define V8(v) \
(((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) | \
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) | \
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) | \
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) | \
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) | \
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) | \
((static_cast<uint64_t>(v) << 56)))
#else
# define V2(v) (v)
# define V4(v) (v)
# define V8(v) (v)
#endif
There is NO WARRANTY for this software. See license.txt for
details. */
#if (BITS_PER_WORD == 64)
# define VW(v) V8(v)
#elif (BITS_PER_WORD == 32)
# define VW(v) V4(v)
#else
# error
#endif
#ifndef AVIAN_ENDIANNESS_H
#define AVIAN_ENDIANNESS_H
#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
details. */
#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "endianness.h"
#include "tools.h"
#define MH_MAGIC_64 0xfeedfacf
#define MH_MAGIC 0xfeedface
#define MH_OBJECT 1
#define LC_SEGMENT_64 0x19
#define LC_SEGMENT 1
#define LC_SYMTAB 2
#define S_REGULAR 0
@ -40,142 +40,21 @@
#define CPU_SUBTYPE_POWERPC_ALL 0
#define CPU_SUBTYPE_ARM_V7 9
#if (BITS_PER_WORD == 64)
# define Magic MH_MAGIC_64
# define Segment LC_SEGMENT_64
# define FileHeader mach_header_64
# define SegmentCommand segment_command_64
# define Section section_64
# define NList struct nlist_64
#elif (BITS_PER_WORD == 32)
# define Magic MH_MAGIC
# define Segment LC_SEGMENT
# define FileHeader mach_header
# define SegmentCommand segment_command
# define Section section
# define NList struct nlist
#else
# error
#endif
namespace {
using namespace avian::tools;
typedef int cpu_type_t;
typedef int cpu_subtype_t;
typedef int vm_prot_t;
struct mach_header_64 {
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
};
using avian::endian::Endianness;
struct segment_command_64 {
uint32_t cmd;
uint32_t cmdsize;
char segname[16];
uint64_t vmaddr;
uint64_t vmsize;
uint64_t fileoff;
uint64_t filesize;
vm_prot_t maxprot;
vm_prot_t initprot;
uint32_t nsects;
uint32_t flags;
};
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);
}
#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
inline unsigned
log(unsigned n)
@ -185,177 +64,233 @@ log(unsigned n)
return r;
}
void
writeObject(const uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* segmentName, const char* sectionName,
unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType)
{
unsigned startNameLength = strlen(startName) + 1;
unsigned endNameLength = strlen(endName) + 1;
template<class AddrTy, bool TargetLittleEndian = true>
class MachOPlatform : public Platform {
public:
FileHeader header = {
V4(Magic), // magic
V4(cpuType),
V4(cpuSubType),
V4(MH_OBJECT), // filetype,
V4(2), // ncmds
V4(sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)), // sizeofcmds
V4(0) // flags
struct FileHeader {
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
union {
uint32_t flags;
AddrTy flagsAndMaybeReserved;
};
};
SegmentCommand segment = {
V4(Segment), // cmd
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
"", // segname
VW(0), // vmaddr
VW(pad(size)), // vmsize
VW(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)), // fileoff
VW(pad(size)), // filesize
V4(7), // maxprot
V4(7), // initprot
V4(1), // nsects
V4(0) // flags
struct SegmentCommand {
uint32_t cmd;
uint32_t cmdsize;
char segname[16];
AddrTy vmaddr;
AddrTy vmsize;
AddrTy fileoff;
AddrTy filesize;
vm_prot_t maxprot;
vm_prot_t initprot;
uint32_t nsects;
uint32_t flags;
};
strncpy(segment.segname, segmentName, sizeof(segment.segname));
Section sect = {
"", // sectname
"", // segname
VW(0), // addr
VW(pad(size)), // size
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)), // offset
V4(log(alignment)), // align
V4(0), // reloff
V4(0), // nreloc
V4(S_REGULAR), // flags
V4(0), // reserved1
V4(0), // reserved2
struct Section {
char sectname[16];
char segname[16];
AddrTy addr;
AddrTy size;
uint32_t offset;
uint32_t align;
uint32_t reloff;
uint32_t nreloc;
uint32_t flags;
uint32_t reserved1;
AddrTy reserved2AndMaybe3;
};
strncpy(sect.segname, segmentName, sizeof(sect.segname));
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
symtab_command symbolTable = {
V4(LC_SYMTAB), // cmd
V4(sizeof(symtab_command)), // cmdsize
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)
+ pad(size)), // symoff
V4(2), // nsyms
V4(sizeof(FileHeader)
+ sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(symtab_command)
+ pad(size)
+ (sizeof(NList) * 2)), // stroff
V4(1 + startNameLength + endNameLength), // strsize
struct NList {
union {
uint32_t n_strx;
} n_un;
uint8_t n_type;
uint8_t n_sect;
uint16_t n_desc;
AddrTy n_value;
};
NList symbolList[] = {
{
V4(1), // n_un
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
struct SymtabCommand {
uint32_t cmd;
uint32_t cmdsize;
uint32_t symoff;
uint32_t nsyms;
uint32_t stroff;
uint32_t strsize;
};
static const unsigned BytesPerWord = sizeof(AddrTy);
static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1;
static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface;
static inline unsigned
pad(unsigned n)
{
return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
}
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
cpu_type_t cpuType;
cpu_subtype_t cpuSubType;
switch(info.arch) {
case PlatformInfo::x86_64:
cpuType = CPU_TYPE_X86_64;
cpuSubType = CPU_SUBTYPE_X86_64_ALL;
break;
case PlatformInfo::x86:
cpuType = CPU_TYPE_I386;
cpuSubType = CPU_SUBTYPE_I386_ALL;
break;
case PlatformInfo::PowerPC:
cpuType = CPU_TYPE_POWERPC;
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
break;
case PlatformInfo::Arm:
cpuType = CPU_TYPE_ARM;
cpuSubType = CPU_SUBTYPE_ARM_V7;
break;
default:
// should never happen (see MachOPlatform declarations at bottom)
fprintf(stderr, "unsupported architecture: %d\n", info.arch);
return false;
}
};
fwrite(&header, 1, sizeof(header), out);
fwrite(&segment, 1, sizeof(segment), out);
fwrite(&sect, 1, sizeof(sect), out);
fwrite(&symbolTable, 1, sizeof(symbolTable), out);
const char* segmentName;
const char* sectionName;
if (accessFlags & Writable) {
if (accessFlags & Executable) {
segmentName = "__RWX";
sectionName = "__rwx";
} else {
segmentName = "__DATA";
sectionName = "__data";
}
} else {
segmentName = "__TEXT";
sectionName = "__text";
}
fwrite(data, 1, size, out);
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out);
FileHeader header = {
V4(Magic), // magic
V4(cpuType),
V4(cpuSubType),
V4(MH_OBJECT), // filetype,
V4(2), // ncmds
V4(sizeof(SegmentCommand)
+ sizeof(Section)
+ sizeof(SymtabCommand)), // sizeofcmds
V4(0) // flags
};
fwrite(&symbolList, 1, sizeof(symbolList), out);
AddrTy finalSize = pad(data.count);
fputc(0, out);
fwrite(startName, 1, startNameLength, out);
fwrite(endName, 1, endNameLength, out);
}
SegmentCommand segment = {
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
};
strncpy(segment.segname, segmentName, sizeof(segment.segname));
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
#define MACRO_MAKE_NAME(a, b, c) a##b##c
#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c)
namespace binaryToObject {
bool
MAKE_NAME(writeMachO, BITS_PER_WORD, Object)
(uint8_t* data, unsigned size, FILE* out, const char* startName,
const char* endName, const char* architecture, unsigned alignment,
bool writable, bool executable)
{
cpu_type_t cpuType;
cpu_subtype_t cpuSubType;
if (strcmp(architecture, "x86_64") == 0) {
cpuType = CPU_TYPE_X86_64;
cpuSubType = CPU_SUBTYPE_X86_64_ALL;
} else if (strcmp(architecture, "i386") == 0) {
cpuType = CPU_TYPE_I386;
cpuSubType = CPU_SUBTYPE_I386_ALL;
} else if (strcmp(architecture, "powerpc") == 0) {
cpuType = CPU_TYPE_POWERPC;
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
} else if (strcmp(architecture, "arm") == 0) {
cpuType = CPU_TYPE_ARM;
cpuSubType = CPU_SUBTYPE_ARM_V7;
} else {
fprintf(stderr, "unsupported architecture: %s\n", architecture);
return false;
}
const char* segmentName;
const char* sectionName;
if (writable) {
if (executable) {
segmentName = "__RWX";
sectionName = "__rwx";
} else {
segmentName = "__DATA";
sectionName = "__data";
}
} else {
segmentName = "__TEXT";
sectionName = "__text";
}
unsigned startNameLength = strlen(startName);
char myStartName[startNameLength + 2];
myStartName[0] = '_';
memcpy(myStartName + 1, startName, startNameLength + 1);
unsigned endNameLength = strlen(endName);
char myEndName[endNameLength + 2];
myEndName[0] = '_';
memcpy(myEndName + 1, endName, endNameLength + 1);
writeObject(data, size, out, myStartName, myEndName, segmentName,
sectionName, alignment, cpuType, cpuSubType);
return true;
}
} // namespace binaryToObject

View File

@ -8,111 +8,60 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include "stdint.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sys/stat.h"
#include <sys/stat.h>
#ifdef WIN32
#include <windows.h>
#else
#include "sys/mman.h"
#include <sys/mman.h>
#endif
#include "fcntl.h"
#include "unistd.h"
#include <fcntl.h>
#include <unistd.h>
namespace binaryToObject {
#include "tools.h"
bool
writeElf64Object(uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* architecture, unsigned alignment, bool writable,
bool executable);
extern "C"
void __cxa_pure_virtual() {
abort();
}
bool
writeElf32Object(uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* architecture, unsigned alignment, bool writable,
bool executable);
void* operator new(size_t size) {
return malloc(size);
}
bool
writeMachO64Object(uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* architecture, unsigned alignment, bool writable,
bool executable);
bool
writeMachO32Object(uint8_t* data, unsigned size, FILE* out,
const char* startName, const char* endName,
const char* architecture, unsigned alignment, bool writable,
bool executable);
bool
writePEObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
const char* endName, const char* architecture,
unsigned alignment, bool writable, bool executable);
} // namespace binaryToObject
void operator delete(void* mem) { abort(); }
namespace {
using namespace avian::tools;
bool
writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
const char* endName, const char* platform,
writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName,
const char* endName, const char* os,
const char* architecture, unsigned alignment, bool writable,
bool executable)
{
using namespace binaryToObject;
Platform* platform = Platform::getPlatform(PlatformInfo(os, architecture));
bool found = false;
bool success = false;
if (strcmp("linux", platform) == 0) {
if (strcmp("x86_64", architecture) == 0) {
found = true;
success = writeElf64Object
(data, size, out, startName, endName, architecture, alignment,
writable, executable);
} else if (strcmp("i386", architecture) == 0
or strcmp("arm", architecture) == 0
or strcmp("powerpc", architecture) == 0)
{
found = true;
success = writeElf32Object
(data, size, out, startName, endName, architecture, alignment,
writable, executable);
}
} else if (strcmp("darwin", platform) == 0) {
if (strcmp("x86_64", architecture) == 0) {
found = true;
success = writeMachO64Object
(data, size, out, startName, endName, architecture, alignment,
writable, executable);
} else if (strcmp("i386", architecture) == 0
or strcmp("powerpc", architecture) == 0
or strcmp("arm", architecture) == 0)
{
found = true;
success = writeMachO32Object
(data, size, out, startName, endName, architecture, alignment,
writable, executable);
}
} else if (strcmp("windows", platform) == 0
and ((strcmp("x86_64", architecture) == 0
or strcmp("i386", architecture) == 0)))
{
found = true;
success = writePEObject
(data, size, out, startName, endName, architecture, alignment, writable,
executable);
}
if (not found) {
fprintf(stderr, "unsupported platform: %s/%s\n", platform, architecture);
if(!platform) {
fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture);
return false;
}
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
@ -191,13 +140,11 @@ main(int argc, const char** argv)
bool success = false;
if (data) {
FILE* out = fopen(argv[2], "wb");
if (out) {
FileOutputStream out(argv[2]);
if (out.isValid()) {
success = writeObject
(data, size, out, argv[3], argv[4], argv[5], argv[6], alignment,
(data, size, &out, argv[3], argv[4], argv[5], argv[6], alignment,
writable, executable);
fclose(out);
} else {
fprintf(stderr, "unable to open %s\n", argv[2]);
}

View File

@ -8,16 +8,21 @@
There is NO WARRANTY for this software. See license.txt for
details. */
#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tools.h"
namespace {
#define IMAGE_SIZEOF_SHORT_NAME 8
#define IMAGE_FILE_RELOCS_STRIPPED 1
#define IMAGE_FILE_LINE_NUMS_STRIPPED 4
#define IMAGE_FILE_MACHINE_AMD64 0x8664
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_32BIT_MACHINE 256
#define IMAGE_SCN_ALIGN_1BYTES 0x100000
@ -29,8 +34,6 @@
#define IMAGE_SCN_MEM_WRITE 0x80000000
#define IMAGE_SCN_CNT_CODE 32
namespace {
struct IMAGE_FILE_HEADER {
uint16_t Machine;
uint16_t NumberOfSections;
@ -77,155 +80,202 @@ pad(unsigned n)
return (n + (4 - 1)) & ~(4 - 1);
}
void
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;
using namespace avian::tools;
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;
const unsigned endNameOffset = startNameOffset + startNameLength;
class FileWriter {
public:
unsigned sectionCount;
unsigned symbolCount;
unsigned dataStart;
unsigned dataOffset;
IMAGE_FILE_HEADER fileHeader = {
machine, // Machine
sectionCount, // NumberOfSections
0, // TimeDateStamp
sizeof(IMAGE_FILE_HEADER)
+ sizeof(IMAGE_SECTION_HEADER)
+ pad(size), // PointerToSymbolTable
symbolCount, // NumberOfSymbols
0, // SizeOfOptionalHeader
IMAGE_FILE_RELOCS_STRIPPED
| IMAGE_FILE_LINE_NUMS_STRIPPED
| machineMask // Characteristics
IMAGE_FILE_HEADER header;
StringTable strings;
Buffer symbols;
FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount):
sectionCount(0),
symbolCount(symbolCount),
dataStart(sizeof(IMAGE_FILE_HEADER)),
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
| machineMask;
}
void writeHeader(OutputStream* out) {
header.NumberOfSections = sectionCount;
header.PointerToSymbolTable = dataStart + dataOffset;
printf("symbol table start: 0x%x\n", header.PointerToSymbolTable);
dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL));
printf("string table start: 0x%x\n", dataStart + dataOffset);
header.NumberOfSymbols = symbolCount;
out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER));
}
void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) {
unsigned nameOffset = strings.add(name);
IMAGE_SYMBOL symbol = {
{ 0 }, // Name
addr, // Value
sectionNumber, // SectionNumber
type, // Type
storageClass, // StorageClass
0, // NumberOfAuxSymbols
};
symbol.N.Name.Long = nameOffset+4;
symbols.write(&symbol, sizeof(IMAGE_SYMBOL));
}
void writeData(OutputStream* out) {
out->writeChunk(symbols.data, symbols.length);
uint32_t size = strings.length + 4;
out->writeChunk(&size, 4);
out->writeChunk(strings.data, strings.length);
}
};
IMAGE_SECTION_HEADER sectionHeader = {
"", // Name
0, // PhysicalAddress
0, // VirtualAddress
pad(size), // SizeOfRawData
sizeof(IMAGE_FILE_HEADER)
+ sizeof(IMAGE_SECTION_HEADER), // PointerToRawData
0, // PointerToRelocations
0, // PointerToLinenumbers
0, // NumberOfRelocations
0, // NumberOfLinenumbers
sectionMask // Characteristics
class SectionWriter {
public:
FileWriter& file;
IMAGE_SECTION_HEADER header;
size_t dataSize;
size_t finalSize;
const uint8_t* data;
unsigned dataOffset;
SectionWriter(
FileWriter& file,
const char* name,
unsigned sectionMask,
const uint8_t* data,
size_t dataSize):
file(file),
data(data),
dataSize(dataSize),
finalSize(pad(dataSize))
{
file.sectionCount++;
file.dataStart += sizeof(IMAGE_SECTION_HEADER);
strcpy(reinterpret_cast<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;
}
void writeHeader(OutputStream* out) {
header.PointerToRawData = dataOffset + file.dataStart;
printf("section %s: data at 0x%x, ending at 0x%x\n", header.Name, header.PointerToRawData, header.PointerToRawData + header.SizeOfRawData);
out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER));
}
void writeData(OutputStream* out) {
out->writeChunk(data, dataSize);
out->writeRepeat(0, finalSize - dataSize);
}
};
strncpy(reinterpret_cast<char*>(sectionHeader.Name), sectionName,
sizeof(sectionHeader.Name));
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
IMAGE_SYMBOL startSymbol = {
{ 0 }, // Name
0, // Value
sectionNumber, // SectionNumber
0, // Type
2, // StorageClass
0, // NumberOfAuxSymbols
};
startSymbol.N.Name.Long = startNameOffset;
int machine;
int machineMask;
IMAGE_SYMBOL endSymbol = {
{ 0 }, // Name
size, // Value
sectionNumber, // SectionNumber
0, // Type
2, // StorageClass
0, // NumberOfAuxSymbols
};
endSymbol.N.Name.Long = endNameOffset;
if (BytesPerWord == 8) {
machine = IMAGE_FILE_MACHINE_AMD64;
machineMask = 0;
} else { // if (BytesPerWord == 8)
machine = IMAGE_FILE_MACHINE_I386;
machineMask = IMAGE_FILE_32BIT_MACHINE;
}
fwrite(&fileHeader, 1, sizeof(fileHeader), out);
fwrite(&sectionHeader, 1, sizeof(sectionHeader), out);
int sectionMask;
switch (alignment) {
case 0:
case 1:
sectionMask = IMAGE_SCN_ALIGN_1BYTES;
break;
case 2:
sectionMask = IMAGE_SCN_ALIGN_2BYTES;
break;
case 4:
sectionMask = IMAGE_SCN_ALIGN_4BYTES;
break;
case 8:
sectionMask = IMAGE_SCN_ALIGN_8BYTES;
break;
default:
fprintf(stderr, "unsupported alignment: %d\n", alignment);
return false;
}
fwrite(data, 1, size, out);
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out);
sectionMask |= IMAGE_SCN_MEM_READ;
fwrite(&startSymbol, 1, sizeof(startSymbol), out);
fwrite(&endSymbol, 1, sizeof(endSymbol), out);
const char* sectionName;
if (accessFlags & Platform::Writable) {
if (accessFlags & Platform::Executable) {
sectionName = ".rwx";
sectionMask |= IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_CNT_CODE;
} else {
sectionName = ".data";
sectionMask |= IMAGE_SCN_MEM_WRITE;
}
} else {
sectionName = ".text";
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
}
uint32_t symbolTableSize = endNameOffset + endNameLength;
fwrite(&symbolTableSize, 1, 4, out);
FileWriter file(machine, machineMask, symbols.count);
fwrite(startName, 1, startNameLength, out);
fwrite(endName, 1, endNameLength, out);
}
SectionWriter section(file, sectionName, sectionMask, data.items, data.count);
file.writeHeader(out);
for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) {
file.addSymbol(sym->name, sym->addr, 1, 0, 2);
}
section.writeHeader(out);
section.writeData(out);
file.writeData(out);
return true;
}
WindowsPlatform():
Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {}
};
WindowsPlatform<4> windows32Platform;
WindowsPlatform<8> windows64Platform;
} // namespace
namespace binaryToObject {
bool
writePEObject
(uint8_t* data, unsigned size, FILE* out, const char* startName,
const char* endName, const char* architecture, unsigned alignment,
bool writable, bool executable)
{
int machine;
int machineMask;
if (strcmp(architecture, "x86_64") == 0) {
machine = IMAGE_FILE_MACHINE_AMD64;
machineMask = 0;
} else if (strcmp(architecture, "i386") == 0) {
machine = IMAGE_FILE_MACHINE_I386;
machineMask = IMAGE_FILE_32BIT_MACHINE;
} else {
fprintf(stderr, "unsupported architecture: %s\n", architecture);
return false;
}
int sectionMask;
switch (alignment) {
case 0:
case 1:
sectionMask = IMAGE_SCN_ALIGN_1BYTES;
break;
case 2:
sectionMask = IMAGE_SCN_ALIGN_2BYTES;
break;
case 4:
sectionMask = IMAGE_SCN_ALIGN_4BYTES;
break;
case 8:
sectionMask = IMAGE_SCN_ALIGN_8BYTES;
break;
default:
fprintf(stderr, "unsupported alignment: %d\n", alignment);
return false;
}
sectionMask |= IMAGE_SCN_MEM_READ;
const char* sectionName;
if (writable) {
if (executable) {
sectionName = ".rwx";
sectionMask |= IMAGE_SCN_MEM_WRITE
| IMAGE_SCN_MEM_EXECUTE
| IMAGE_SCN_CNT_CODE;
} else {
sectionName = ".data";
sectionMask |= IMAGE_SCN_MEM_WRITE;
}
} else {
sectionName = ".text";
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
}
writeObject(data, size, out, startName, endName, sectionName, machine,
machineMask, sectionMask);
return true;
}
} // namespace binaryToObject

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