mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
refactor binaryToObject to allow more flexibilty (in particular, allowing arbitrary symbols per object)
This commit is contained in:
parent
ca9b5b2f59
commit
661f6c28a8
19
makefile
19
makefile
@ -236,7 +236,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
|
||||||
@ -342,10 +341,6 @@ ifeq ($(platform),darwin)
|
|||||||
lflags += $(flags)
|
lflags += $(flags)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(build-arch),powerpc)
|
|
||||||
converter-cflags += -DBIG_ENDIAN
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(arch),powerpc)
|
ifeq ($(arch),powerpc)
|
||||||
openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||||
cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||||
@ -428,6 +423,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)
|
||||||
@ -606,9 +602,6 @@ driver-object = $(build)/main.o
|
|||||||
driver-dynamic-objects = \
|
driver-dynamic-objects = \
|
||||||
$(build)/main-dynamic.o
|
$(build)/main-dynamic.o
|
||||||
|
|
||||||
gdb-plugin-object = $(build)/gdb-plugin.o
|
|
||||||
gdb-plugin-source = $(src)/gdb-plugin.cpp
|
|
||||||
|
|
||||||
boot-source = $(src)/boot.cpp
|
boot-source = $(src)/boot.cpp
|
||||||
boot-object = $(build)/boot.o
|
boot-object = $(build)/boot.o
|
||||||
|
|
||||||
@ -623,7 +616,10 @@ 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-depends = $(src)/binaryToObject/tools.h
|
converter-depends = \
|
||||||
|
$(src)/binaryToObject/tools.h \
|
||||||
|
$(src)/binaryToObject/endianness.h
|
||||||
|
|
||||||
|
|
||||||
converter-sources = \
|
converter-sources = \
|
||||||
$(src)/binaryToObject/main.cpp \
|
$(src)/binaryToObject/main.cpp \
|
||||||
@ -826,9 +822,6 @@ $(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends)
|
|||||||
$(driver-object): $(driver-source)
|
$(driver-object): $(driver-source)
|
||||||
$(compile-object)
|
$(compile-object)
|
||||||
|
|
||||||
$(gdb-plugin-object): $(gdb-plugin-source)
|
|
||||||
$(compile-object)
|
|
||||||
|
|
||||||
$(build)/main-dynamic.o: $(driver-source)
|
$(build)/main-dynamic.o: $(driver-source)
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
@ -846,7 +839,7 @@ $(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $
|
|||||||
$(build-cxx) $(converter-cflags) -c $(<) -o $(@)
|
$(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 $(@)"
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#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"
|
||||||
|
|
||||||
@ -119,6 +120,39 @@ using avian::endian::Endianness;
|
|||||||
#define V4 Endianness<TargetLittleEndian>::v4
|
#define V4 Endianness<TargetLittleEndian>::v4
|
||||||
#define VANY Endianness<TargetLittleEndian>::vAny
|
#define VANY Endianness<TargetLittleEndian>::vAny
|
||||||
|
|
||||||
|
|
||||||
|
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>
|
template<class AddrTy, bool TargetLittleEndian = true>
|
||||||
class ElfPlatform : public Platform {
|
class ElfPlatform : public Platform {
|
||||||
public:
|
public:
|
||||||
@ -158,240 +192,182 @@ public:
|
|||||||
|
|
||||||
typedef Symbol_Ty<AddrTy> Symbol;
|
typedef Symbol_Ty<AddrTy> Symbol;
|
||||||
|
|
||||||
class ElfObjectWriter : public ObjectWriter {
|
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:
|
public:
|
||||||
|
unsigned sectionCount;
|
||||||
|
unsigned sectionStringTableSectionNumber;
|
||||||
|
|
||||||
PlatformInfo::Architecture arch;
|
AddrTy dataOffset;
|
||||||
OutputStream* out;
|
|
||||||
|
|
||||||
ElfObjectWriter(PlatformInfo::Architecture arch, OutputStream* out):
|
FileHeader header;
|
||||||
arch(arch),
|
StringTable strings;
|
||||||
out(out) {}
|
|
||||||
|
|
||||||
void writeObject(const uint8_t* data, unsigned size,
|
FileWriter(unsigned machine):
|
||||||
const char* startName, const char* endName,
|
sectionCount(0),
|
||||||
const char* sectionName, unsigned sectionFlags,
|
dataOffset(sizeof(FileHeader))
|
||||||
unsigned alignment, int machine, int encoding)
|
|
||||||
{
|
{
|
||||||
const unsigned sectionCount = 5;
|
memset(&header, 0, sizeof(FileHeader));
|
||||||
const unsigned symbolCount = 2;
|
header.e_ident[EI_MAG0] = V1(ELFMAG0);
|
||||||
|
header.e_ident[EI_MAG1] = V1(ELFMAG1);
|
||||||
const unsigned sectionNameLength = strlen(sectionName) + 1;
|
header.e_ident[EI_MAG2] = V1(ELFMAG2);
|
||||||
const unsigned startNameLength = strlen(startName) + 1;
|
header.e_ident[EI_MAG3] = V1(ELFMAG3);
|
||||||
const unsigned endNameLength = strlen(endName) + 1;
|
header.e_ident[EI_CLASS] = V1(Class);
|
||||||
|
header.e_ident[EI_DATA] = V1(Encoding);
|
||||||
const char* const sectionStringTableName = ".shstrtab";
|
header.e_ident[EI_VERSION] = V1(EV_CURRENT);
|
||||||
const char* const stringTableName = ".strtab";
|
header.e_ident[EI_OSABI] = V1(OSABI);
|
||||||
const char* const symbolTableName = ".symtab";
|
header.e_ident[EI_ABIVERSION] = V1(0);
|
||||||
|
header.e_type = V2(ET_REL);
|
||||||
const unsigned sectionStringTableNameLength
|
header.e_machine = V2(machine);
|
||||||
= strlen(sectionStringTableName) + 1;
|
header.e_version = V4(EV_CURRENT);
|
||||||
const unsigned stringTableNameLength = strlen(stringTableName) + 1;
|
header.e_entry = VANY(static_cast<AddrTy>(0));
|
||||||
const unsigned symbolTableNameLength = strlen(symbolTableName) + 1;
|
header.e_phoff = VANY(static_cast<AddrTy>(0));
|
||||||
|
header.e_shoff = VANY(static_cast<AddrTy>(sizeof(FileHeader)));
|
||||||
const unsigned nullStringOffset = 0;
|
header.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
|
||||||
|
header.e_ehsize = V2(sizeof(FileHeader));
|
||||||
const unsigned sectionStringTableNameOffset = nullStringOffset + 1;
|
header.e_phentsize = V2(0);
|
||||||
const unsigned stringTableNameOffset
|
header.e_phnum = V2(0);
|
||||||
= sectionStringTableNameOffset + sectionStringTableNameLength;
|
header.e_shentsize = V2(sizeof(SectionHeader));
|
||||||
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 = VANY(static_cast<AddrTy>(0));
|
|
||||||
fileHeader.e_phoff = VANY(static_cast<AddrTy>(0));
|
|
||||||
fileHeader.e_shoff = VANY(static_cast<AddrTy>(sizeof(FileHeader)));
|
|
||||||
fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
|
|
||||||
fileHeader.e_ehsize = V2(sizeof(FileHeader));
|
|
||||||
fileHeader.e_phentsize = V2(0);
|
|
||||||
fileHeader.e_phnum = V2(0);
|
|
||||||
fileHeader.e_shentsize = V2(sizeof(SectionHeader));
|
|
||||||
fileHeader.e_shnum = V2(sectionCount);
|
|
||||||
fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber);
|
|
||||||
|
|
||||||
SectionHeader nullSection;
|
|
||||||
memset(&nullSection, 0, sizeof(SectionHeader));
|
|
||||||
|
|
||||||
SectionHeader bodySection;
|
|
||||||
bodySection.sh_name = V4(sectionNameOffset);
|
|
||||||
bodySection.sh_type = V4(SHT_PROGBITS);
|
|
||||||
bodySection.sh_flags = VANY(static_cast<AddrTy>(sectionFlags));
|
|
||||||
bodySection.sh_addr = VANY(static_cast<AddrTy>(0));
|
|
||||||
unsigned bodySectionOffset
|
|
||||||
= sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount);
|
|
||||||
bodySection.sh_offset = VANY(static_cast<AddrTy>(bodySectionOffset));
|
|
||||||
unsigned bodySectionSize = size;
|
|
||||||
bodySection.sh_size = VANY(static_cast<AddrTy>(bodySectionSize));
|
|
||||||
bodySection.sh_link = V4(0);
|
|
||||||
bodySection.sh_info = V4(0);
|
|
||||||
bodySection.sh_addralign = VANY(static_cast<AddrTy>(alignment));
|
|
||||||
bodySection.sh_entsize = VANY(static_cast<AddrTy>(0));
|
|
||||||
|
|
||||||
SectionHeader sectionStringTableSection;
|
|
||||||
sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset);
|
|
||||||
sectionStringTableSection.sh_type = V4(SHT_STRTAB);
|
|
||||||
sectionStringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
|
|
||||||
sectionStringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
|
|
||||||
unsigned sectionStringTableSectionOffset
|
|
||||||
= bodySectionOffset + bodySectionSize;
|
|
||||||
sectionStringTableSection.sh_offset = VANY(static_cast<AddrTy>(sectionStringTableSectionOffset));
|
|
||||||
unsigned sectionStringTableSectionSize = sectionStringTableLength;
|
|
||||||
sectionStringTableSection.sh_size = VANY(static_cast<AddrTy>(sectionStringTableSectionSize));
|
|
||||||
sectionStringTableSection.sh_link = V4(0);
|
|
||||||
sectionStringTableSection.sh_info = V4(0);
|
|
||||||
sectionStringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
|
|
||||||
sectionStringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
|
|
||||||
|
|
||||||
SectionHeader stringTableSection;
|
|
||||||
stringTableSection.sh_name = V4(stringTableNameOffset);
|
|
||||||
stringTableSection.sh_type = V4(SHT_STRTAB);
|
|
||||||
stringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
|
|
||||||
stringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
|
|
||||||
unsigned stringTableSectionOffset
|
|
||||||
= sectionStringTableSectionOffset + sectionStringTableSectionSize;
|
|
||||||
stringTableSection.sh_offset = VANY(static_cast<AddrTy>(stringTableSectionOffset));
|
|
||||||
unsigned stringTableSectionSize = stringTableLength;
|
|
||||||
stringTableSection.sh_size = VANY(static_cast<AddrTy>(stringTableSectionSize));
|
|
||||||
stringTableSection.sh_link = V4(0);
|
|
||||||
stringTableSection.sh_info = V4(0);
|
|
||||||
stringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
|
|
||||||
stringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
|
|
||||||
|
|
||||||
SectionHeader symbolTableSection;
|
|
||||||
symbolTableSection.sh_name = V4(symbolTableNameOffset);
|
|
||||||
symbolTableSection.sh_type = V4(SHT_SYMTAB);
|
|
||||||
symbolTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
|
|
||||||
symbolTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
|
|
||||||
unsigned symbolTableSectionOffset
|
|
||||||
= stringTableSectionOffset + stringTableSectionSize;
|
|
||||||
symbolTableSection.sh_offset = VANY(static_cast<AddrTy>(symbolTableSectionOffset));
|
|
||||||
unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount;
|
|
||||||
symbolTableSection.sh_size = VANY(static_cast<AddrTy>(symbolTableSectionSize));
|
|
||||||
symbolTableSection.sh_link = V4(stringTableSectionNumber);
|
|
||||||
symbolTableSection.sh_info = V4(0);
|
|
||||||
symbolTableSection.sh_addralign = VANY(static_cast<AddrTy>(Elf::BytesPerWord));
|
|
||||||
symbolTableSection.sh_entsize = VANY(static_cast<AddrTy>(sizeof(Symbol)));
|
|
||||||
|
|
||||||
Symbol startSymbol;
|
|
||||||
startSymbol.st_name = V4(startNameOffset);
|
|
||||||
startSymbol.st_value = VANY(static_cast<AddrTy>(0));
|
|
||||||
startSymbol.st_size = VANY(static_cast<AddrTy>(0));
|
|
||||||
startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
|
||||||
startSymbol.st_other = V1(STV_DEFAULT);
|
|
||||||
startSymbol.st_shndx = V2(bodySectionNumber);
|
|
||||||
|
|
||||||
Symbol endSymbol;
|
|
||||||
endSymbol.st_name = V4(endNameOffset);
|
|
||||||
endSymbol.st_value = VANY(static_cast<AddrTy>(size));
|
|
||||||
endSymbol.st_size = VANY(static_cast<AddrTy>(0));
|
|
||||||
endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
|
||||||
endSymbol.st_other = V1(STV_DEFAULT);
|
|
||||||
endSymbol.st_shndx = V2(bodySectionNumber);
|
|
||||||
|
|
||||||
out->writeChunk(&fileHeader, sizeof(fileHeader));
|
|
||||||
out->writeChunk(&nullSection, sizeof(nullSection));
|
|
||||||
out->writeChunk(&bodySection, sizeof(bodySection));
|
|
||||||
out->writeChunk(§ionStringTableSection, sizeof(sectionStringTableSection));
|
|
||||||
out->writeChunk(&stringTableSection, sizeof(stringTableSection));
|
|
||||||
out->writeChunk(&symbolTableSection, sizeof(symbolTableSection));
|
|
||||||
|
|
||||||
out->writeChunk(data, size);
|
|
||||||
|
|
||||||
out->write(0);
|
|
||||||
out->writeChunk(sectionStringTableName, sectionStringTableNameLength);
|
|
||||||
out->writeChunk(stringTableName, stringTableNameLength);
|
|
||||||
out->writeChunk(symbolTableName, symbolTableNameLength);
|
|
||||||
out->writeChunk(sectionName, sectionNameLength);
|
|
||||||
|
|
||||||
out->write(0);
|
|
||||||
out->writeChunk(startName, startNameLength);
|
|
||||||
out->writeChunk(endName, endNameLength);
|
|
||||||
|
|
||||||
out->writeChunk(&startSymbol, sizeof(startSymbol));
|
|
||||||
out->writeChunk(&endSymbol, sizeof(endSymbol));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool write(uint8_t* data, size_t size,
|
void writeHeader(OutputStream* out) {
|
||||||
const char* startName, const char* endName,
|
header.e_shnum = V2(sectionCount);
|
||||||
unsigned alignment, unsigned accessFlags)
|
header.e_shstrndx = V2(sectionStringTableSectionNumber);
|
||||||
{
|
out->writeChunk(&header, sizeof(FileHeader));
|
||||||
int machine;
|
|
||||||
int encoding;
|
|
||||||
if (arch == PlatformInfo::x86_64) {
|
|
||||||
machine = EM_X86_64;
|
|
||||||
encoding = ELFDATA2LSB;
|
|
||||||
} else if (arch == PlatformInfo::x86) {
|
|
||||||
machine = EM_386;
|
|
||||||
encoding = ELFDATA2LSB;
|
|
||||||
} else if (arch == PlatformInfo::Arm) {
|
|
||||||
machine = EM_ARM;
|
|
||||||
encoding = ELFDATA2LSB;
|
|
||||||
} else if (arch == PlatformInfo::PowerPC) {
|
|
||||||
machine = EM_PPC;
|
|
||||||
encoding = ELFDATA2MSB;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "unsupported architecture: %s\n", arch);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* sectionName;
|
|
||||||
unsigned sectionFlags = SHF_ALLOC;
|
|
||||||
if (accessFlags & Writable) {
|
|
||||||
if (accessFlags & Executable) {
|
|
||||||
sectionName = ".rwx";
|
|
||||||
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
|
|
||||||
} else {
|
|
||||||
sectionName = ".data";
|
|
||||||
sectionFlags |= SHF_WRITE;
|
|
||||||
}
|
|
||||||
} else if (accessFlags & Executable) {
|
|
||||||
sectionName = ".text";
|
|
||||||
sectionFlags |= SHF_EXECINSTR;
|
|
||||||
} else {
|
|
||||||
sectionName = ".rodata";
|
|
||||||
}
|
|
||||||
|
|
||||||
writeObject(data, size, startName, endName, sectionName, sectionFlags,
|
|
||||||
alignment, machine, encoding);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dispose() {
|
|
||||||
delete this;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ElfPlatform(PlatformInfo::Architecture arch):
|
class SectionWriter {
|
||||||
Platform(PlatformInfo(PlatformInfo::Linux, arch)) {}
|
public:
|
||||||
|
FileWriter& file;
|
||||||
|
String name;
|
||||||
|
SectionHeader header;
|
||||||
|
const size_t* dataSize;
|
||||||
|
const uint8_t* const* data;
|
||||||
|
|
||||||
virtual ObjectWriter* makeObjectWriter(OutputStream* out) {
|
SectionWriter(FileWriter& file):
|
||||||
return new ElfObjectWriter(info.arch, out);
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,11 +15,12 @@ namespace avian {
|
|||||||
|
|
||||||
namespace endian {
|
namespace endian {
|
||||||
|
|
||||||
#ifndef BIG_ENDIAN
|
static union {
|
||||||
const bool LittleEndian = true;
|
uint32_t i;
|
||||||
#else
|
char c[4];
|
||||||
const bool LittleEndian = false;
|
} _DetectEndianness = {1};
|
||||||
#endif
|
|
||||||
|
const bool LittleEndian = _DetectEndianness.c[0] == 1;
|
||||||
|
|
||||||
template<bool TargetLittleEndian>
|
template<bool TargetLittleEndian>
|
||||||
class Endianness {
|
class Endianness {
|
||||||
@ -57,13 +58,13 @@ public:
|
|||||||
return v;
|
return v;
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
|
((static_cast<uint64_t>(v) >> 56) & (static_cast<uint64_t>(0xff) << 0)) |
|
||||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
|
((static_cast<uint64_t>(v) >> 40) & (static_cast<uint64_t>(0xff) << 8)) |
|
||||||
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) |
|
((static_cast<uint64_t>(v) >> 24) & (static_cast<uint64_t>(0xff) << 16)) |
|
||||||
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) |
|
((static_cast<uint64_t>(v) >> 8) & (static_cast<uint64_t>(0xff) << 24)) |
|
||||||
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) |
|
((static_cast<uint64_t>(v) << 8) & (static_cast<uint64_t>(0xff) << 32)) |
|
||||||
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) |
|
((static_cast<uint64_t>(v) << 24) & (static_cast<uint64_t>(0xff) << 40)) |
|
||||||
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) |
|
((static_cast<uint64_t>(v) << 40) & (static_cast<uint64_t>(0xff) << 48)) |
|
||||||
((static_cast<uint64_t>(v) << 56));
|
((static_cast<uint64_t>(v) << 56));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,14 @@ using avian::endian::Endianness;
|
|||||||
#define V4 Endianness<TargetLittleEndian>::v4
|
#define V4 Endianness<TargetLittleEndian>::v4
|
||||||
#define VANY Endianness<TargetLittleEndian>::vAny
|
#define VANY Endianness<TargetLittleEndian>::vAny
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
log(unsigned n)
|
||||||
|
{
|
||||||
|
unsigned r = 0;
|
||||||
|
for (unsigned i = 1; i < n; ++r) i <<= 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
template<class AddrTy, bool TargetLittleEndian = true>
|
template<class AddrTy, bool TargetLittleEndian = true>
|
||||||
class MachOPlatform : public Platform {
|
class MachOPlatform : public Platform {
|
||||||
public:
|
public:
|
||||||
@ -132,155 +140,28 @@ public:
|
|||||||
return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
|
return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned
|
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
|
||||||
log(unsigned n)
|
|
||||||
{
|
|
||||||
unsigned r = 0;
|
|
||||||
for (unsigned i = 1; i < n; ++r) i <<= 1;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MachOObjectWriter : public ObjectWriter {
|
|
||||||
public:
|
|
||||||
|
|
||||||
PlatformInfo::Architecture arch;
|
|
||||||
OutputStream* out;
|
|
||||||
|
|
||||||
MachOObjectWriter(PlatformInfo::Architecture arch, OutputStream* out):
|
|
||||||
arch(arch),
|
|
||||||
out(out) {}
|
|
||||||
|
|
||||||
void writeObject(const uint8_t* data, unsigned size,
|
|
||||||
const char* startName, const char* endName,
|
|
||||||
const char* segmentName, const char* sectionName,
|
|
||||||
unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType)
|
|
||||||
{
|
|
||||||
unsigned startNameLength = strlen(startName) + 1;
|
|
||||||
unsigned endNameLength = strlen(endName) + 1;
|
|
||||||
|
|
||||||
FileHeader header = {
|
|
||||||
V4(Magic), // magic
|
|
||||||
V4(cpuType),
|
|
||||||
V4(cpuSubType),
|
|
||||||
V4(MH_OBJECT), // filetype,
|
|
||||||
V4(2), // ncmds
|
|
||||||
V4(sizeof(SegmentCommand)
|
|
||||||
+ sizeof(Section)
|
|
||||||
+ sizeof(SymtabCommand)), // sizeofcmds
|
|
||||||
V4(0) // flags
|
|
||||||
};
|
|
||||||
|
|
||||||
SegmentCommand segment = {
|
|
||||||
V4(Segment), // cmd
|
|
||||||
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
|
|
||||||
"", // segname
|
|
||||||
VANY(static_cast<AddrTy>(0)), // vmaddr
|
|
||||||
VANY(static_cast<AddrTy>(pad(size))), // vmsize
|
|
||||||
VANY(static_cast<AddrTy>(sizeof(FileHeader)
|
|
||||||
+ sizeof(SegmentCommand)
|
|
||||||
+ sizeof(Section)
|
|
||||||
+ sizeof(SymtabCommand))), // fileoff
|
|
||||||
VANY(static_cast<AddrTy>(pad(size))), // filesize
|
|
||||||
V4(7), // maxprot
|
|
||||||
V4(7), // initprot
|
|
||||||
V4(1), // nsects
|
|
||||||
V4(0) // flags
|
|
||||||
};
|
|
||||||
|
|
||||||
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
|
||||||
|
|
||||||
Section sect = {
|
|
||||||
"", // sectname
|
|
||||||
"", // segname
|
|
||||||
VANY(static_cast<AddrTy>(0)), // addr
|
|
||||||
VANY(static_cast<AddrTy>(pad(size))), // size
|
|
||||||
V4(sizeof(FileHeader)
|
|
||||||
+ sizeof(SegmentCommand)
|
|
||||||
+ sizeof(Section)
|
|
||||||
+ sizeof(SymtabCommand)), // offset
|
|
||||||
V4(log(alignment)), // align
|
|
||||||
V4(0), // reloff
|
|
||||||
V4(0), // nreloc
|
|
||||||
V4(S_REGULAR), // flags
|
|
||||||
V4(0), // reserved1
|
|
||||||
V4(0), // reserved2
|
|
||||||
};
|
|
||||||
|
|
||||||
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
|
||||||
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
|
||||||
|
|
||||||
SymtabCommand symbolTable = {
|
|
||||||
V4(LC_SYMTAB), // cmd
|
|
||||||
V4(sizeof(SymtabCommand)), // cmdsize
|
|
||||||
V4(sizeof(FileHeader)
|
|
||||||
+ sizeof(SegmentCommand)
|
|
||||||
+ sizeof(Section)
|
|
||||||
+ sizeof(SymtabCommand)
|
|
||||||
+ pad(size)), // symoff
|
|
||||||
V4(2), // nsyms
|
|
||||||
V4(sizeof(FileHeader)
|
|
||||||
+ sizeof(SegmentCommand)
|
|
||||||
+ sizeof(Section)
|
|
||||||
+ sizeof(SymtabCommand)
|
|
||||||
+ pad(size)
|
|
||||||
+ (sizeof(NList) * 2)), // stroff
|
|
||||||
V4(1 + startNameLength + endNameLength), // strsize
|
|
||||||
};
|
|
||||||
|
|
||||||
NList symbolList[] = {
|
|
||||||
{
|
|
||||||
V4(1), // n_un
|
|
||||||
V1(N_SECT | N_EXT), // n_type
|
|
||||||
V1(1), // n_sect
|
|
||||||
V2(0), // n_desc
|
|
||||||
VANY(static_cast<AddrTy>(0)) // n_value
|
|
||||||
},
|
|
||||||
{
|
|
||||||
V4(1 + startNameLength), // n_un
|
|
||||||
V1(N_SECT | N_EXT), // n_type
|
|
||||||
V1(1), // n_sect
|
|
||||||
V2(0), // n_desc
|
|
||||||
VANY(static_cast<AddrTy>(size)) // n_value
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
out->writeChunk(&header, sizeof(header));
|
|
||||||
out->writeChunk(&segment, sizeof(segment));
|
|
||||||
out->writeChunk(§, sizeof(sect));
|
|
||||||
out->writeChunk(&symbolTable, sizeof(symbolTable));
|
|
||||||
|
|
||||||
out->writeChunk(data, size);
|
|
||||||
out->writeRepeat(0, pad(size) - size);
|
|
||||||
|
|
||||||
out->writeChunk(&symbolList, sizeof(symbolList));
|
|
||||||
|
|
||||||
out->write(0);
|
|
||||||
|
|
||||||
out->writeChunk(startName, startNameLength);
|
|
||||||
out->writeChunk(endName, endNameLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool write(uint8_t* data, size_t size,
|
|
||||||
const char* startName, const char* endName,
|
|
||||||
unsigned alignment, unsigned accessFlags)
|
|
||||||
{
|
|
||||||
|
|
||||||
cpu_type_t cpuType;
|
cpu_type_t cpuType;
|
||||||
cpu_subtype_t cpuSubType;
|
cpu_subtype_t cpuSubType;
|
||||||
if (arch == PlatformInfo::x86_64) {
|
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 (arch == PlatformInfo::x86) {
|
break;
|
||||||
|
case PlatformInfo::x86:
|
||||||
cpuType = CPU_TYPE_I386;
|
cpuType = CPU_TYPE_I386;
|
||||||
cpuSubType = CPU_SUBTYPE_I386_ALL;
|
cpuSubType = CPU_SUBTYPE_I386_ALL;
|
||||||
} else if (arch == PlatformInfo::PowerPC) {
|
break;
|
||||||
|
case PlatformInfo::PowerPC:
|
||||||
cpuType = CPU_TYPE_POWERPC;
|
cpuType = CPU_TYPE_POWERPC;
|
||||||
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
|
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
|
||||||
} else if (arch == PlatformInfo::Arm) {
|
break;
|
||||||
|
case PlatformInfo::Arm:
|
||||||
cpuType = CPU_TYPE_ARM;
|
cpuType = CPU_TYPE_ARM;
|
||||||
cpuSubType = CPU_SUBTYPE_ARM_V7;
|
cpuSubType = CPU_SUBTYPE_ARM_V7;
|
||||||
} else {
|
default:
|
||||||
fprintf(stderr, "unsupported architecture: %d\n", arch);
|
// should never happen (see MachOPlatform declarations at bottom)
|
||||||
|
fprintf(stderr, "unsupported architecture: %d\n", info.arch);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,33 +180,111 @@ public:
|
|||||||
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,
|
||||||
unsigned endNameLength = strlen(endName);
|
V4(2), // ncmds
|
||||||
char myEndName[endNameLength + 2];
|
V4(sizeof(SegmentCommand)
|
||||||
myEndName[0] = '_';
|
+ sizeof(Section)
|
||||||
memcpy(myEndName + 1, endName, endNameLength + 1);
|
+ sizeof(SymtabCommand)), // sizeofcmds
|
||||||
|
V4(0) // flags
|
||||||
writeObject(data, size, myStartName, myEndName, segmentName,
|
|
||||||
sectionName, alignment, cpuType, cpuSubType);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dispose() {
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddrTy finalSize = pad(data.count);
|
||||||
|
|
||||||
|
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(§, 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):
|
MachOPlatform(PlatformInfo::Architecture arch):
|
||||||
Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {}
|
Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {}
|
||||||
|
|
||||||
virtual ObjectWriter* makeObjectWriter(OutputStream* out) {
|
|
||||||
return new MachOObjectWriter(info.arch, out);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MachOPlatform<uint32_t> darwinx86Platform(PlatformInfo::x86);
|
MachOPlatform<uint32_t> darwinx86Platform(PlatformInfo::x86);
|
||||||
|
@ -33,18 +33,14 @@ void* operator new(size_t size) {
|
|||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* mem) {
|
void operator delete(void* mem) { abort(); }
|
||||||
if(mem) {
|
|
||||||
free(mem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace avian::tools;
|
using namespace avian::tools;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startName,
|
writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName,
|
||||||
const char* endName, const char* os,
|
const char* endName, const char* os,
|
||||||
const char* architecture, unsigned alignment, bool writable,
|
const char* architecture, unsigned alignment, bool writable,
|
||||||
bool executable)
|
bool executable)
|
||||||
@ -56,14 +52,16 @@ writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startNa
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectWriter* writer = platform->makeObjectWriter(out);
|
SymbolInfo symbols[2];
|
||||||
|
symbols[0].name = startName;
|
||||||
|
symbols[0].addr = 0;
|
||||||
|
symbols[1].name = endName;
|
||||||
|
symbols[1].addr = size;
|
||||||
|
|
||||||
bool success = writer->write(data, size, startName, endName, alignment,
|
unsigned accessFlags = (writable ? Platform::Writable : 0) | (executable ? Platform::Executable : 0);
|
||||||
ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0));
|
|
||||||
|
|
||||||
writer->dispose();
|
return platform->writeObject(out, Slice<SymbolInfo>(symbols, 2), Slice<const uint8_t>(data, size), accessFlags, alignment);
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
@ -81,106 +82,126 @@ pad(unsigned n)
|
|||||||
|
|
||||||
using namespace avian::tools;
|
using namespace avian::tools;
|
||||||
|
|
||||||
void
|
|
||||||
writeObject(const uint8_t* data, unsigned size, OutputStream* 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;
|
|
||||||
|
|
||||||
const unsigned startNameLength = strlen(startName) + 1;
|
|
||||||
const unsigned endNameLength = strlen(endName) + 1;
|
|
||||||
|
|
||||||
const unsigned startNameOffset = 4;
|
|
||||||
const unsigned endNameOffset = startNameOffset + startNameLength;
|
|
||||||
|
|
||||||
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_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
|
|
||||||
};
|
|
||||||
|
|
||||||
strncpy(reinterpret_cast<char*>(sectionHeader.Name), sectionName,
|
|
||||||
sizeof(sectionHeader.Name));
|
|
||||||
|
|
||||||
IMAGE_SYMBOL startSymbol = {
|
|
||||||
{ 0 }, // Name
|
|
||||||
0, // Value
|
|
||||||
sectionNumber, // SectionNumber
|
|
||||||
0, // Type
|
|
||||||
2, // StorageClass
|
|
||||||
0, // NumberOfAuxSymbols
|
|
||||||
};
|
|
||||||
startSymbol.N.Name.Long = startNameOffset;
|
|
||||||
|
|
||||||
IMAGE_SYMBOL endSymbol = {
|
|
||||||
{ 0 }, // Name
|
|
||||||
size, // Value
|
|
||||||
sectionNumber, // SectionNumber
|
|
||||||
0, // Type
|
|
||||||
2, // StorageClass
|
|
||||||
0, // NumberOfAuxSymbols
|
|
||||||
};
|
|
||||||
endSymbol.N.Name.Long = endNameOffset;
|
|
||||||
|
|
||||||
out->writeChunk(&fileHeader, sizeof(fileHeader));
|
|
||||||
out->writeChunk(§ionHeader, sizeof(sectionHeader));
|
|
||||||
|
|
||||||
out->writeChunk(data, size);
|
|
||||||
out->writeRepeat(0, pad(size) - size);
|
|
||||||
|
|
||||||
out->writeChunk(&startSymbol, sizeof(startSymbol));
|
|
||||||
out->writeChunk(&endSymbol, sizeof(endSymbol));
|
|
||||||
|
|
||||||
uint32_t symbolTableSize = endNameOffset + endNameLength;
|
|
||||||
out->writeChunk(&symbolTableSize, 4);
|
|
||||||
|
|
||||||
out->writeChunk(startName, startNameLength);
|
|
||||||
out->writeChunk(endName, endNameLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<unsigned BytesPerWord>
|
template<unsigned BytesPerWord>
|
||||||
class WindowsPlatform : public Platform {
|
class WindowsPlatform : public Platform {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class PEObjectWriter : public ObjectWriter {
|
|
||||||
|
class FileWriter {
|
||||||
public:
|
public:
|
||||||
|
unsigned sectionCount;
|
||||||
|
unsigned symbolCount;
|
||||||
|
unsigned dataStart;
|
||||||
|
unsigned dataOffset;
|
||||||
|
|
||||||
OutputStream* out;
|
IMAGE_FILE_HEADER header;
|
||||||
|
|
||||||
PEObjectWriter(OutputStream* out):
|
StringTable strings;
|
||||||
out(out) {}
|
Buffer symbols;
|
||||||
|
|
||||||
virtual bool write(uint8_t* data, size_t size,
|
FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount):
|
||||||
const char* startName, const char* endName,
|
sectionCount(0),
|
||||||
unsigned alignment, unsigned accessFlags)
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
|
||||||
|
|
||||||
int machine;
|
int machine;
|
||||||
int machineMask;
|
int machineMask;
|
||||||
|
|
||||||
@ -215,8 +236,8 @@ public:
|
|||||||
sectionMask |= IMAGE_SCN_MEM_READ;
|
sectionMask |= IMAGE_SCN_MEM_READ;
|
||||||
|
|
||||||
const char* sectionName;
|
const char* sectionName;
|
||||||
if (accessFlags & ObjectWriter::Writable) {
|
if (accessFlags & Platform::Writable) {
|
||||||
if (accessFlags & ObjectWriter::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
|
||||||
@ -230,20 +251,24 @@ public:
|
|||||||
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;
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dispose() {
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ObjectWriter* makeObjectWriter(OutputStream* out) {
|
|
||||||
return new PEObjectWriter(out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowsPlatform():
|
WindowsPlatform():
|
||||||
@ -253,4 +278,4 @@ public:
|
|||||||
WindowsPlatform<4> windows32Platform;
|
WindowsPlatform<4> windows32Platform;
|
||||||
WindowsPlatform<8> windows64Platform;
|
WindowsPlatform<8> windows64Platform;
|
||||||
|
|
||||||
}
|
} // namespace
|
||||||
|
@ -19,6 +19,38 @@ namespace avian {
|
|||||||
|
|
||||||
namespace tools {
|
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) {
|
void OutputStream::write(uint8_t byte) {
|
||||||
writeChunk(&byte, 1);
|
writeChunk(&byte, 1);
|
||||||
}
|
}
|
||||||
|
@ -35,20 +35,62 @@ public:
|
|||||||
virtual void write(uint8_t byte);
|
virtual void write(uint8_t byte);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ObjectWriter {
|
class String {
|
||||||
public:
|
public:
|
||||||
|
const char* text;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
enum AccessFlags {
|
String(const char* text);
|
||||||
Readable = 1 << 0,
|
};
|
||||||
Writable = 1 << 1,
|
|
||||||
Executable = 1 << 2
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual bool write(uint8_t* data, size_t size,
|
class SymbolInfo {
|
||||||
const char* startName, const char* endName,
|
public:
|
||||||
unsigned alignment, unsigned accessFlags) = 0;
|
unsigned addr;
|
||||||
|
String name;
|
||||||
|
|
||||||
virtual void dispose() = 0;
|
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 {
|
class PlatformInfo {
|
||||||
@ -98,7 +140,12 @@ public:
|
|||||||
first = this;
|
first = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ObjectWriter* makeObjectWriter(OutputStream* out) = 0;
|
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);
|
static Platform* getPlatform(PlatformInfo info);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user