mirror of
https://github.com/corda/corda.git
synced 2025-01-04 04:04:27 +00:00
refactor binaryToObject, to better support (eventually) putting symbols for compiled code in objects
This commit is contained in:
parent
ba1f8aa68e
commit
9c308f751c
34
makefile
34
makefile
@ -334,9 +334,6 @@ ifeq ($(platform),darwin)
|
||||
x := $(error "couldn't find SDK for iOS version")
|
||||
endif
|
||||
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
flags = -arch armv7 -isysroot \
|
||||
$(sdk-dir)/iPhoneOS$(ios-version).sdk/
|
||||
openjdk-extra-cflags += $(flags)
|
||||
@ -345,10 +342,11 @@ ifeq ($(platform),darwin)
|
||||
lflags += $(flags)
|
||||
endif
|
||||
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags += -DBIG_ENDIAN
|
||||
endif
|
||||
|
||||
ifeq ($(arch),powerpc)
|
||||
ifneq (,$(filter i386 x86_64 arm,$(build-arch)))
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
@ -356,9 +354,6 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(arch),i386)
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
@ -366,9 +361,6 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(arch),x86_64)
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch x86_64
|
||||
cflags += -arch x86_64
|
||||
asmflags += -arch x86_64
|
||||
@ -614,6 +606,9 @@ driver-object = $(build)/main.o
|
||||
driver-dynamic-objects = \
|
||||
$(build)/main-dynamic.o
|
||||
|
||||
gdb-plugin-object = $(build)/gdb-plugin.o
|
||||
gdb-plugin-source = $(src)/gdb-plugin.cpp
|
||||
|
||||
boot-source = $(src)/boot.cpp
|
||||
boot-object = $(build)/boot.o
|
||||
|
||||
@ -630,8 +625,8 @@ generator = $(build)/generator
|
||||
|
||||
converter-objects = \
|
||||
$(build)/binaryToObject-main.o \
|
||||
$(build)/binaryToObject-elf64.o \
|
||||
$(build)/binaryToObject-elf32.o \
|
||||
$(build)/binaryToObject-tools.o \
|
||||
$(build)/binaryToObject-elf.o \
|
||||
$(build)/binaryToObject-mach-o64.o \
|
||||
$(build)/binaryToObject-mach-o32.o \
|
||||
$(build)/binaryToObject-pe.o
|
||||
@ -828,6 +823,9 @@ $(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends)
|
||||
$(driver-object): $(driver-source)
|
||||
$(compile-object)
|
||||
|
||||
$(gdb-plugin-object): $(gdb-plugin-source)
|
||||
$(compile-object)
|
||||
|
||||
$(build)/main-dynamic.o: $(driver-source)
|
||||
@echo "compiling $(@)"
|
||||
@mkdir -p $(dir $(@))
|
||||
@ -843,11 +841,11 @@ $(boot-javahome-object): $(src)/boot-javahome.cpp
|
||||
$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
|
||||
$(build-cxx) $(converter-cflags) -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
||||
$(build)/binaryToObject-tools.o: $(src)/binaryToObject/tools.cpp
|
||||
$(build-cxx) $(converter-cflags) -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@)
|
||||
$(build)/binaryToObject-elf.o: $(src)/binaryToObject/elf.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
||||
|
@ -8,12 +8,14 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "endianness.h"
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
#define EI_MAG0 0
|
||||
@ -62,344 +64,340 @@
|
||||
|
||||
#define STV_DEFAULT 0
|
||||
|
||||
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
#define ELF32_ST_INFO(bind, type) ELF64_ST_INFO((bind), (type))
|
||||
|
||||
#if (BITS_PER_WORD == 64)
|
||||
# define FileHeader Elf64_Ehdr
|
||||
# define SectionHeader Elf64_Shdr
|
||||
# define Symbol Elf64_Sym
|
||||
# define Class ELFCLASS64
|
||||
# define SYMBOL_INFO ELF64_ST_INFO
|
||||
#elif (BITS_PER_WORD == 32)
|
||||
# define FileHeader Elf32_Ehdr
|
||||
# define SectionHeader Elf32_Shdr
|
||||
# define Symbol Elf32_Sym
|
||||
# define Class ELFCLASS32
|
||||
# define SYMBOL_INFO ELF32_ST_INFO
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
#define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
|
||||
#define OSABI ELFOSABI_SYSV
|
||||
|
||||
namespace {
|
||||
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef uint16_t Elf64_Section;
|
||||
typedef uint64_t Elf64_Off;
|
||||
using namespace avian::tools;
|
||||
|
||||
struct Elf64_Ehdr {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
template<class AddrTy>
|
||||
struct ElfTypes {
|
||||
typedef uint16_t Half;
|
||||
typedef uint32_t Word;
|
||||
typedef AddrTy Addr;
|
||||
typedef uint64_t Xword;
|
||||
typedef uint16_t Section;
|
||||
typedef AddrTy Off;
|
||||
typedef AddrTy XFlags;
|
||||
static const unsigned BytesPerWord = sizeof(AddrTy);
|
||||
};
|
||||
|
||||
struct Elf64_Shdr {
|
||||
Elf64_Word sh_name;
|
||||
Elf64_Word sh_type;
|
||||
Elf64_Xword sh_flags;
|
||||
Elf64_Addr sh_addr;
|
||||
Elf64_Off sh_offset;
|
||||
Elf64_Xword sh_size;
|
||||
Elf64_Word sh_link;
|
||||
Elf64_Word sh_info;
|
||||
Elf64_Xword sh_addralign;
|
||||
Elf64_Xword sh_entsize;
|
||||
};
|
||||
template<class AddrTy>
|
||||
struct Symbol_Ty;
|
||||
|
||||
struct Elf64_Sym {
|
||||
Elf64_Word st_name;
|
||||
template<>
|
||||
struct Symbol_Ty<uint64_t> {
|
||||
typedef ElfTypes<uint64_t> Elf;
|
||||
|
||||
Elf::Word st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf64_Section st_shndx;
|
||||
Elf64_Addr st_value;
|
||||
Elf64_Xword st_size;
|
||||
Elf::Section st_shndx;
|
||||
Elf::Addr st_value;
|
||||
Elf::Xword st_size;
|
||||
};
|
||||
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Word;
|
||||
typedef uint32_t Elf32_Addr;
|
||||
typedef uint64_t Elf32_Xword;
|
||||
typedef uint16_t Elf32_Section;
|
||||
typedef uint32_t Elf32_Off;
|
||||
template<>
|
||||
struct Symbol_Ty<uint32_t> {
|
||||
typedef ElfTypes<uint32_t> Elf;
|
||||
|
||||
struct Elf32_Ehdr {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf32_Half e_type;
|
||||
Elf32_Half e_machine;
|
||||
Elf32_Word e_version;
|
||||
Elf32_Addr e_entry;
|
||||
Elf32_Off e_phoff;
|
||||
Elf32_Off e_shoff;
|
||||
Elf32_Word e_flags;
|
||||
Elf32_Half e_ehsize;
|
||||
Elf32_Half e_phentsize;
|
||||
Elf32_Half e_phnum;
|
||||
Elf32_Half e_shentsize;
|
||||
Elf32_Half e_shnum;
|
||||
Elf32_Half e_shstrndx;
|
||||
};
|
||||
|
||||
struct Elf32_Shdr {
|
||||
Elf32_Word sh_name;
|
||||
Elf32_Word sh_type;
|
||||
Elf32_Word sh_flags;
|
||||
Elf32_Addr sh_addr;
|
||||
Elf32_Off sh_offset;
|
||||
Elf32_Word sh_size;
|
||||
Elf32_Word sh_link;
|
||||
Elf32_Word sh_info;
|
||||
Elf32_Word sh_addralign;
|
||||
Elf32_Word sh_entsize;
|
||||
};
|
||||
|
||||
struct Elf32_Sym {
|
||||
Elf32_Word st_name;
|
||||
Elf32_Addr st_value;
|
||||
Elf32_Word st_size;
|
||||
Elf::Word st_name;
|
||||
Elf::Addr st_value;
|
||||
Elf::Word st_size;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf32_Section st_shndx;
|
||||
Elf::Section st_shndx;
|
||||
};
|
||||
|
||||
void
|
||||
writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* sectionName, unsigned sectionFlags,
|
||||
unsigned alignment, int machine, int encoding)
|
||||
{
|
||||
const unsigned sectionCount = 5;
|
||||
const unsigned symbolCount = 2;
|
||||
using avian::endian::Endianness;
|
||||
|
||||
const unsigned sectionNameLength = strlen(sectionName) + 1;
|
||||
const unsigned startNameLength = strlen(startName) + 1;
|
||||
const unsigned endNameLength = strlen(endName) + 1;
|
||||
#define V1 Endianness<TargetLittleEndian>::v1
|
||||
#define V2 Endianness<TargetLittleEndian>::v2
|
||||
#define V3 Endianness<TargetLittleEndian>::v3
|
||||
#define V4 Endianness<TargetLittleEndian>::v4
|
||||
#define VANY Endianness<TargetLittleEndian>::vAny
|
||||
|
||||
const char* const sectionStringTableName = ".shstrtab";
|
||||
const char* const stringTableName = ".strtab";
|
||||
const char* const symbolTableName = ".symtab";
|
||||
template<class AddrTy, bool TargetLittleEndian = true>
|
||||
class ElfPlatform : public Platform {
|
||||
public:
|
||||
|
||||
const unsigned sectionStringTableNameLength
|
||||
= strlen(sectionStringTableName) + 1;
|
||||
const unsigned stringTableNameLength = strlen(stringTableName) + 1;
|
||||
const unsigned symbolTableNameLength = strlen(symbolTableName) + 1;
|
||||
typedef ElfTypes<AddrTy> Elf;
|
||||
static const unsigned Class = Elf::BytesPerWord / 4;
|
||||
|
||||
const unsigned nullStringOffset = 0;
|
||||
struct FileHeader {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
typename Elf::Half e_type;
|
||||
typename Elf::Half e_machine;
|
||||
typename Elf::Word e_version;
|
||||
typename Elf::Addr e_entry;
|
||||
typename Elf::Off e_phoff;
|
||||
typename Elf::Off e_shoff;
|
||||
typename Elf::Word e_flags;
|
||||
typename Elf::Half e_ehsize;
|
||||
typename Elf::Half e_phentsize;
|
||||
typename Elf::Half e_phnum;
|
||||
typename Elf::Half e_shentsize;
|
||||
typename Elf::Half e_shnum;
|
||||
typename Elf::Half e_shstrndx;
|
||||
};
|
||||
|
||||
const unsigned sectionStringTableNameOffset = nullStringOffset + 1;
|
||||
const unsigned stringTableNameOffset
|
||||
= sectionStringTableNameOffset + sectionStringTableNameLength;
|
||||
const unsigned symbolTableNameOffset
|
||||
= stringTableNameOffset + stringTableNameLength;
|
||||
const unsigned sectionNameOffset
|
||||
= symbolTableNameOffset + symbolTableNameLength;
|
||||
const unsigned sectionStringTableLength
|
||||
= sectionNameOffset + sectionNameLength;
|
||||
struct SectionHeader {
|
||||
typename Elf::Word sh_name;
|
||||
typename Elf::Word sh_type;
|
||||
typename Elf::XFlags sh_flags;
|
||||
typename Elf::Addr sh_addr;
|
||||
typename Elf::Off sh_offset;
|
||||
typename Elf::Off sh_size;
|
||||
typename Elf::Word sh_link;
|
||||
typename Elf::Word sh_info;
|
||||
typename Elf::Addr sh_addralign;
|
||||
typename Elf::Off sh_entsize;
|
||||
};
|
||||
|
||||
const unsigned startNameOffset = nullStringOffset + 1;
|
||||
const unsigned endNameOffset = startNameOffset + startNameLength;
|
||||
const unsigned stringTableLength = endNameOffset + endNameLength;
|
||||
typedef Symbol_Ty<AddrTy> Symbol;
|
||||
|
||||
const unsigned bodySectionNumber = 1;
|
||||
const unsigned sectionStringTableSectionNumber = 2;
|
||||
const unsigned stringTableSectionNumber = 3;
|
||||
class ElfObjectWriter : public ObjectWriter {
|
||||
public:
|
||||
|
||||
FileHeader fileHeader;
|
||||
memset(&fileHeader, 0, sizeof(FileHeader));
|
||||
fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0);
|
||||
fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1);
|
||||
fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2);
|
||||
fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3);
|
||||
fileHeader.e_ident[EI_CLASS] = V1(Class);
|
||||
fileHeader.e_ident[EI_DATA] = V1(encoding);
|
||||
fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT);
|
||||
fileHeader.e_ident[EI_OSABI] = V1(OSABI);
|
||||
fileHeader.e_ident[EI_ABIVERSION] = V1(0);
|
||||
fileHeader.e_type = V2(ET_REL);
|
||||
fileHeader.e_machine = V2(machine);
|
||||
fileHeader.e_version = V4(EV_CURRENT);
|
||||
fileHeader.e_entry = VW(0);
|
||||
fileHeader.e_phoff = VW(0);
|
||||
fileHeader.e_shoff = VW(sizeof(FileHeader));
|
||||
fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
|
||||
fileHeader.e_ehsize = V2(sizeof(FileHeader));
|
||||
fileHeader.e_phentsize = V2(0);
|
||||
fileHeader.e_phnum = V2(0);
|
||||
fileHeader.e_shentsize = V2(sizeof(SectionHeader));
|
||||
fileHeader.e_shnum = V2(sectionCount);
|
||||
fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber);
|
||||
PlatformInfo::Architecture arch;
|
||||
|
||||
SectionHeader nullSection;
|
||||
memset(&nullSection, 0, sizeof(SectionHeader));
|
||||
ElfObjectWriter(PlatformInfo::Architecture arch):
|
||||
arch(arch) {}
|
||||
|
||||
SectionHeader bodySection;
|
||||
bodySection.sh_name = V4(sectionNameOffset);
|
||||
bodySection.sh_type = V4(SHT_PROGBITS);
|
||||
bodySection.sh_flags = VW(sectionFlags);
|
||||
bodySection.sh_addr = VW(0);
|
||||
unsigned bodySectionOffset
|
||||
= sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount);
|
||||
bodySection.sh_offset = VW(bodySectionOffset);
|
||||
unsigned bodySectionSize = size;
|
||||
bodySection.sh_size = VW(bodySectionSize);
|
||||
bodySection.sh_link = V4(0);
|
||||
bodySection.sh_info = V4(0);
|
||||
bodySection.sh_addralign = VW(alignment);
|
||||
bodySection.sh_entsize = VW(0);
|
||||
void writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* sectionName, unsigned sectionFlags,
|
||||
unsigned alignment, int machine, int encoding)
|
||||
{
|
||||
const unsigned sectionCount = 5;
|
||||
const unsigned symbolCount = 2;
|
||||
|
||||
SectionHeader sectionStringTableSection;
|
||||
sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset);
|
||||
sectionStringTableSection.sh_type = V4(SHT_STRTAB);
|
||||
sectionStringTableSection.sh_flags = VW(0);
|
||||
sectionStringTableSection.sh_addr = VW(0);
|
||||
unsigned sectionStringTableSectionOffset
|
||||
= bodySectionOffset + bodySectionSize;
|
||||
sectionStringTableSection.sh_offset = VW(sectionStringTableSectionOffset);
|
||||
unsigned sectionStringTableSectionSize = sectionStringTableLength;
|
||||
sectionStringTableSection.sh_size = VW(sectionStringTableSectionSize);
|
||||
sectionStringTableSection.sh_link = V4(0);
|
||||
sectionStringTableSection.sh_info = V4(0);
|
||||
sectionStringTableSection.sh_addralign = VW(1);
|
||||
sectionStringTableSection.sh_entsize = VW(0);
|
||||
const unsigned sectionNameLength = strlen(sectionName) + 1;
|
||||
const unsigned startNameLength = strlen(startName) + 1;
|
||||
const unsigned endNameLength = strlen(endName) + 1;
|
||||
|
||||
SectionHeader stringTableSection;
|
||||
stringTableSection.sh_name = V4(stringTableNameOffset);
|
||||
stringTableSection.sh_type = V4(SHT_STRTAB);
|
||||
stringTableSection.sh_flags = VW(0);
|
||||
stringTableSection.sh_addr = VW(0);
|
||||
unsigned stringTableSectionOffset
|
||||
= sectionStringTableSectionOffset + sectionStringTableSectionSize;
|
||||
stringTableSection.sh_offset = VW(stringTableSectionOffset);
|
||||
unsigned stringTableSectionSize = stringTableLength;
|
||||
stringTableSection.sh_size = VW(stringTableSectionSize);
|
||||
stringTableSection.sh_link = V4(0);
|
||||
stringTableSection.sh_info = V4(0);
|
||||
stringTableSection.sh_addralign = VW(1);
|
||||
stringTableSection.sh_entsize = VW(0);
|
||||
const char* const sectionStringTableName = ".shstrtab";
|
||||
const char* const stringTableName = ".strtab";
|
||||
const char* const symbolTableName = ".symtab";
|
||||
|
||||
SectionHeader symbolTableSection;
|
||||
symbolTableSection.sh_name = V4(symbolTableNameOffset);
|
||||
symbolTableSection.sh_type = V4(SHT_SYMTAB);
|
||||
symbolTableSection.sh_flags = VW(0);
|
||||
symbolTableSection.sh_addr = VW(0);
|
||||
unsigned symbolTableSectionOffset
|
||||
= stringTableSectionOffset + stringTableSectionSize;
|
||||
symbolTableSection.sh_offset = VW(symbolTableSectionOffset);
|
||||
unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount;
|
||||
symbolTableSection.sh_size = VW(symbolTableSectionSize);
|
||||
symbolTableSection.sh_link = V4(stringTableSectionNumber);
|
||||
symbolTableSection.sh_info = V4(0);
|
||||
symbolTableSection.sh_addralign = VW(BITS_PER_WORD / 8);
|
||||
symbolTableSection.sh_entsize = VW(sizeof(Symbol));
|
||||
const unsigned sectionStringTableNameLength
|
||||
= strlen(sectionStringTableName) + 1;
|
||||
const unsigned stringTableNameLength = strlen(stringTableName) + 1;
|
||||
const unsigned symbolTableNameLength = strlen(symbolTableName) + 1;
|
||||
|
||||
Symbol startSymbol;
|
||||
startSymbol.st_name = V4(startNameOffset);
|
||||
startSymbol.st_value = VW(0);
|
||||
startSymbol.st_size = VW(0);
|
||||
startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
||||
startSymbol.st_other = V1(STV_DEFAULT);
|
||||
startSymbol.st_shndx = V2(bodySectionNumber);
|
||||
const unsigned nullStringOffset = 0;
|
||||
|
||||
Symbol endSymbol;
|
||||
endSymbol.st_name = V4(endNameOffset);
|
||||
endSymbol.st_value = VW(size);
|
||||
endSymbol.st_size = VW(0);
|
||||
endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
||||
endSymbol.st_other = V1(STV_DEFAULT);
|
||||
endSymbol.st_shndx = V2(bodySectionNumber);
|
||||
const unsigned sectionStringTableNameOffset = nullStringOffset + 1;
|
||||
const unsigned stringTableNameOffset
|
||||
= sectionStringTableNameOffset + sectionStringTableNameLength;
|
||||
const unsigned symbolTableNameOffset
|
||||
= stringTableNameOffset + stringTableNameLength;
|
||||
const unsigned sectionNameOffset
|
||||
= symbolTableNameOffset + symbolTableNameLength;
|
||||
const unsigned sectionStringTableLength
|
||||
= sectionNameOffset + sectionNameLength;
|
||||
|
||||
fwrite(&fileHeader, 1, sizeof(fileHeader), out);
|
||||
fwrite(&nullSection, 1, sizeof(nullSection), out);
|
||||
fwrite(&bodySection, 1, sizeof(bodySection), out);
|
||||
fwrite(§ionStringTableSection, 1, sizeof(sectionStringTableSection),
|
||||
out);
|
||||
fwrite(&stringTableSection, 1, sizeof(stringTableSection), out);
|
||||
fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out);
|
||||
const unsigned startNameOffset = nullStringOffset + 1;
|
||||
const unsigned endNameOffset = startNameOffset + startNameLength;
|
||||
const unsigned stringTableLength = endNameOffset + endNameLength;
|
||||
|
||||
fwrite(data, 1, size, out);
|
||||
const unsigned bodySectionNumber = 1;
|
||||
const unsigned sectionStringTableSectionNumber = 2;
|
||||
const unsigned stringTableSectionNumber = 3;
|
||||
|
||||
fputc(0, out);
|
||||
fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out);
|
||||
fwrite(stringTableName, 1, stringTableNameLength, out);
|
||||
fwrite(symbolTableName, 1, symbolTableNameLength, out);
|
||||
fwrite(sectionName, 1, sectionNameLength, out);
|
||||
FileHeader fileHeader;
|
||||
memset(&fileHeader, 0, sizeof(FileHeader));
|
||||
fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0);
|
||||
fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1);
|
||||
fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2);
|
||||
fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3);
|
||||
fileHeader.e_ident[EI_CLASS] = V1(Class);
|
||||
fileHeader.e_ident[EI_DATA] = V1(encoding);
|
||||
fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT);
|
||||
fileHeader.e_ident[EI_OSABI] = V1(OSABI);
|
||||
fileHeader.e_ident[EI_ABIVERSION] = V1(0);
|
||||
fileHeader.e_type = V2(ET_REL);
|
||||
fileHeader.e_machine = V2(machine);
|
||||
fileHeader.e_version = V4(EV_CURRENT);
|
||||
fileHeader.e_entry = VANY(static_cast<AddrTy>(0));
|
||||
fileHeader.e_phoff = VANY(static_cast<AddrTy>(0));
|
||||
fileHeader.e_shoff = VANY(static_cast<AddrTy>(sizeof(FileHeader)));
|
||||
fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
|
||||
fileHeader.e_ehsize = V2(sizeof(FileHeader));
|
||||
fileHeader.e_phentsize = V2(0);
|
||||
fileHeader.e_phnum = V2(0);
|
||||
fileHeader.e_shentsize = V2(sizeof(SectionHeader));
|
||||
fileHeader.e_shnum = V2(sectionCount);
|
||||
fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber);
|
||||
|
||||
fputc(0, out);
|
||||
fwrite(startName, 1, startNameLength, out);
|
||||
fwrite(endName, 1, endNameLength, out);
|
||||
SectionHeader nullSection;
|
||||
memset(&nullSection, 0, sizeof(SectionHeader));
|
||||
|
||||
SectionHeader bodySection;
|
||||
bodySection.sh_name = V4(sectionNameOffset);
|
||||
bodySection.sh_type = V4(SHT_PROGBITS);
|
||||
bodySection.sh_flags = VANY(static_cast<AddrTy>(sectionFlags));
|
||||
bodySection.sh_addr = VANY(static_cast<AddrTy>(0));
|
||||
unsigned bodySectionOffset
|
||||
= sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount);
|
||||
bodySection.sh_offset = VANY(static_cast<AddrTy>(bodySectionOffset));
|
||||
unsigned bodySectionSize = size;
|
||||
bodySection.sh_size = VANY(static_cast<AddrTy>(bodySectionSize));
|
||||
bodySection.sh_link = V4(0);
|
||||
bodySection.sh_info = V4(0);
|
||||
bodySection.sh_addralign = VANY(static_cast<AddrTy>(alignment));
|
||||
bodySection.sh_entsize = VANY(static_cast<AddrTy>(0));
|
||||
|
||||
SectionHeader sectionStringTableSection;
|
||||
sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset);
|
||||
sectionStringTableSection.sh_type = V4(SHT_STRTAB);
|
||||
sectionStringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
|
||||
sectionStringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
|
||||
unsigned sectionStringTableSectionOffset
|
||||
= bodySectionOffset + bodySectionSize;
|
||||
sectionStringTableSection.sh_offset = VANY(static_cast<AddrTy>(sectionStringTableSectionOffset));
|
||||
unsigned sectionStringTableSectionSize = sectionStringTableLength;
|
||||
sectionStringTableSection.sh_size = VANY(static_cast<AddrTy>(sectionStringTableSectionSize));
|
||||
sectionStringTableSection.sh_link = V4(0);
|
||||
sectionStringTableSection.sh_info = V4(0);
|
||||
sectionStringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
|
||||
sectionStringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
|
||||
|
||||
SectionHeader stringTableSection;
|
||||
stringTableSection.sh_name = V4(stringTableNameOffset);
|
||||
stringTableSection.sh_type = V4(SHT_STRTAB);
|
||||
stringTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
|
||||
stringTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
|
||||
unsigned stringTableSectionOffset
|
||||
= sectionStringTableSectionOffset + sectionStringTableSectionSize;
|
||||
stringTableSection.sh_offset = VANY(static_cast<AddrTy>(stringTableSectionOffset));
|
||||
unsigned stringTableSectionSize = stringTableLength;
|
||||
stringTableSection.sh_size = VANY(static_cast<AddrTy>(stringTableSectionSize));
|
||||
stringTableSection.sh_link = V4(0);
|
||||
stringTableSection.sh_info = V4(0);
|
||||
stringTableSection.sh_addralign = VANY(static_cast<AddrTy>(1));
|
||||
stringTableSection.sh_entsize = VANY(static_cast<AddrTy>(0));
|
||||
|
||||
SectionHeader symbolTableSection;
|
||||
symbolTableSection.sh_name = V4(symbolTableNameOffset);
|
||||
symbolTableSection.sh_type = V4(SHT_SYMTAB);
|
||||
symbolTableSection.sh_flags = VANY(static_cast<AddrTy>(0));
|
||||
symbolTableSection.sh_addr = VANY(static_cast<AddrTy>(0));
|
||||
unsigned symbolTableSectionOffset
|
||||
= stringTableSectionOffset + stringTableSectionSize;
|
||||
symbolTableSection.sh_offset = VANY(static_cast<AddrTy>(symbolTableSectionOffset));
|
||||
unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount;
|
||||
symbolTableSection.sh_size = VANY(static_cast<AddrTy>(symbolTableSectionSize));
|
||||
symbolTableSection.sh_link = V4(stringTableSectionNumber);
|
||||
symbolTableSection.sh_info = V4(0);
|
||||
symbolTableSection.sh_addralign = VANY(static_cast<AddrTy>(Elf::BytesPerWord));
|
||||
symbolTableSection.sh_entsize = VANY(static_cast<AddrTy>(sizeof(Symbol)));
|
||||
|
||||
Symbol startSymbol;
|
||||
startSymbol.st_name = V4(startNameOffset);
|
||||
startSymbol.st_value = VANY(static_cast<AddrTy>(0));
|
||||
startSymbol.st_size = VANY(static_cast<AddrTy>(0));
|
||||
startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
||||
startSymbol.st_other = V1(STV_DEFAULT);
|
||||
startSymbol.st_shndx = V2(bodySectionNumber);
|
||||
|
||||
Symbol endSymbol;
|
||||
endSymbol.st_name = V4(endNameOffset);
|
||||
endSymbol.st_value = VANY(static_cast<AddrTy>(size));
|
||||
endSymbol.st_size = VANY(static_cast<AddrTy>(0));
|
||||
endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
||||
endSymbol.st_other = V1(STV_DEFAULT);
|
||||
endSymbol.st_shndx = V2(bodySectionNumber);
|
||||
|
||||
fwrite(&fileHeader, 1, sizeof(fileHeader), out);
|
||||
fwrite(&nullSection, 1, sizeof(nullSection), out);
|
||||
fwrite(&bodySection, 1, sizeof(bodySection), out);
|
||||
fwrite(§ionStringTableSection, 1, sizeof(sectionStringTableSection),
|
||||
out);
|
||||
fwrite(&stringTableSection, 1, sizeof(stringTableSection), out);
|
||||
fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out);
|
||||
|
||||
fwrite(data, 1, size, out);
|
||||
|
||||
fputc(0, out);
|
||||
fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out);
|
||||
fwrite(stringTableName, 1, stringTableNameLength, out);
|
||||
fwrite(symbolTableName, 1, symbolTableNameLength, out);
|
||||
fwrite(sectionName, 1, sectionNameLength, out);
|
||||
|
||||
fputc(0, out);
|
||||
fwrite(startName, 1, startNameLength, out);
|
||||
fwrite(endName, 1, endNameLength, out);
|
||||
|
||||
fwrite(&startSymbol, 1, sizeof(startSymbol), out);
|
||||
fwrite(&endSymbol, 1, sizeof(endSymbol), out);
|
||||
}
|
||||
|
||||
virtual bool write(uint8_t* data, size_t size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
unsigned alignment, unsigned accessFlags)
|
||||
{
|
||||
int machine;
|
||||
int encoding;
|
||||
if (arch == PlatformInfo::x86_64) {
|
||||
machine = EM_X86_64;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (arch == PlatformInfo::x86) {
|
||||
machine = EM_386;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (arch == PlatformInfo::Arm) {
|
||||
machine = EM_ARM;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (arch == PlatformInfo::PowerPC) {
|
||||
machine = EM_PPC;
|
||||
encoding = ELFDATA2MSB;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %s\n", arch);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* sectionName;
|
||||
unsigned sectionFlags = SHF_ALLOC;
|
||||
if (accessFlags & Writable) {
|
||||
if (accessFlags & Executable) {
|
||||
sectionName = ".rwx";
|
||||
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
|
||||
} else {
|
||||
sectionName = ".data";
|
||||
sectionFlags |= SHF_WRITE;
|
||||
}
|
||||
} else if (accessFlags & Executable) {
|
||||
sectionName = ".text";
|
||||
sectionFlags |= SHF_EXECINSTR;
|
||||
} else {
|
||||
sectionName = ".rodata";
|
||||
}
|
||||
|
||||
writeObject(data, size, out, startName, endName, sectionName, sectionFlags,
|
||||
alignment, machine, encoding);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
ElfPlatform(PlatformInfo::Architecture arch):
|
||||
Platform(PlatformInfo(PlatformInfo::Linux, arch)) {}
|
||||
|
||||
virtual ObjectWriter* makeObjectWriter() {
|
||||
return new ElfObjectWriter(info.arch);
|
||||
}
|
||||
};
|
||||
|
||||
ElfPlatform<uint32_t> elfx86Platform(PlatformInfo::x86);
|
||||
ElfPlatform<uint32_t> elfArmPlatform(PlatformInfo::Arm);
|
||||
ElfPlatform<uint32_t, false> elfPowerPCPlatform(PlatformInfo::PowerPC);
|
||||
ElfPlatform<uint64_t> elfx86_64Platform(PlatformInfo::x86_64);
|
||||
|
||||
fwrite(&startSymbol, 1, sizeof(startSymbol), out);
|
||||
fwrite(&endSymbol, 1, sizeof(endSymbol), out);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#define MACRO_MAKE_NAME(a, b, c) a##b##c
|
||||
#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c)
|
||||
|
||||
namespace binaryToObject {
|
||||
|
||||
bool
|
||||
MAKE_NAME(writeElf, BITS_PER_WORD, Object)
|
||||
(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture, unsigned alignment,
|
||||
bool writable, bool executable)
|
||||
{
|
||||
int machine;
|
||||
int encoding;
|
||||
if (strcmp(architecture, "x86_64") == 0) {
|
||||
machine = EM_X86_64;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (strcmp(architecture, "i386") == 0) {
|
||||
machine = EM_386;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (strcmp(architecture, "arm") == 0) {
|
||||
machine = EM_ARM;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (strcmp(architecture, "powerpc") == 0) {
|
||||
machine = EM_PPC;
|
||||
encoding = ELFDATA2MSB;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %s\n", architecture);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* sectionName;
|
||||
unsigned sectionFlags = SHF_ALLOC;
|
||||
if (writable) {
|
||||
if (executable) {
|
||||
sectionName = ".rwx";
|
||||
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
|
||||
} else {
|
||||
sectionName = ".data";
|
||||
sectionFlags |= SHF_WRITE;
|
||||
}
|
||||
} else if (executable) {
|
||||
sectionName = ".text";
|
||||
sectionFlags |= SHF_EXECINSTR;
|
||||
} else {
|
||||
sectionName = ".rodata";
|
||||
}
|
||||
|
||||
writeObject(data, size, out, startName, endName, sectionName, sectionFlags,
|
||||
alignment, machine, encoding);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace binaryToObject
|
||||
|
@ -1,38 +1,80 @@
|
||||
#ifndef ENDIANNESS_H
|
||||
#define ENDIANNESS_H
|
||||
/* Copyright (c) 2008-2011, Avian Contributors
|
||||
|
||||
#define V1(v) (v)
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
#ifdef OPPOSITE_ENDIAN
|
||||
# define V2(v) \
|
||||
((((v) >> 8) & 0xFF) | \
|
||||
(((v) << 8)))
|
||||
# define V4(v) \
|
||||
((((v) >> 24) & 0x000000FF) | \
|
||||
(((v) >> 8) & 0x0000FF00) | \
|
||||
(((v) << 8) & 0x00FF0000) | \
|
||||
(((v) << 24)))
|
||||
# define V8(v) \
|
||||
(((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) | \
|
||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) | \
|
||||
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \
|
||||
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) | \
|
||||
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) | \
|
||||
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) | \
|
||||
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) | \
|
||||
((static_cast<uint64_t>(v) << 56)))
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#ifndef AVIAN_ENDIANNESS_H
|
||||
#define AVIAN_ENDIANNESS_H
|
||||
|
||||
namespace avian {
|
||||
|
||||
namespace endian {
|
||||
|
||||
#ifndef BIG_ENDIAN
|
||||
const bool LittleEndian = true;
|
||||
#else
|
||||
# define V2(v) (v)
|
||||
# define V4(v) (v)
|
||||
# define V8(v) (v)
|
||||
const bool LittleEndian = false;
|
||||
#endif
|
||||
|
||||
#if (BITS_PER_WORD == 64)
|
||||
# define VW(v) V8(v)
|
||||
#elif (BITS_PER_WORD == 32)
|
||||
# define VW(v) V4(v)
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
template<bool TargetLittleEndian>
|
||||
class Endianness {
|
||||
public:
|
||||
static inline uint8_t v1(uint8_t v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif//ENDIANNESS_H
|
||||
static inline uint16_t v2(uint16_t v) {
|
||||
if(LittleEndian == TargetLittleEndian) {
|
||||
return v;
|
||||
} else {
|
||||
return ((v >> 8) & 0xFF) | (v << 8);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t v4(uint32_t v) {
|
||||
if(LittleEndian == TargetLittleEndian) {
|
||||
return v;
|
||||
} else {
|
||||
return
|
||||
((v >> 24) & 0x000000FF) |
|
||||
((v >> 8) & 0x0000FF00) |
|
||||
((v << 8) & 0x00FF0000) |
|
||||
((v << 24));
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t vAny(uint32_t v) {
|
||||
return v4(v);
|
||||
}
|
||||
|
||||
static inline uint64_t v8(uint64_t v) {
|
||||
if(LittleEndian == TargetLittleEndian) {
|
||||
return v;
|
||||
} else {
|
||||
return
|
||||
((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) |
|
||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) |
|
||||
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) |
|
||||
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) |
|
||||
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) |
|
||||
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) |
|
||||
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) |
|
||||
((static_cast<uint64_t>(v) << 56));
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t vAny(uint64_t v) {
|
||||
return v8(v);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace endian
|
||||
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_ENDIANNESS_H
|
||||
|
@ -8,19 +8,19 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "endianness.h"
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
#define MH_MAGIC_64 0xfeedfacf
|
||||
#define MH_MAGIC 0xfeedface
|
||||
|
||||
#define MH_OBJECT 1
|
||||
|
||||
#define LC_SEGMENT_64 0x19
|
||||
#define LC_SEGMENT 1
|
||||
#define LC_SYMTAB 2
|
||||
|
||||
#define S_REGULAR 0
|
||||
@ -40,322 +40,294 @@
|
||||
#define CPU_SUBTYPE_POWERPC_ALL 0
|
||||
#define CPU_SUBTYPE_ARM_V7 9
|
||||
|
||||
#if (BITS_PER_WORD == 64)
|
||||
# define Magic MH_MAGIC_64
|
||||
# define Segment LC_SEGMENT_64
|
||||
# define FileHeader mach_header_64
|
||||
# define SegmentCommand segment_command_64
|
||||
# define Section section_64
|
||||
# define NList struct nlist_64
|
||||
#elif (BITS_PER_WORD == 32)
|
||||
# define Magic MH_MAGIC
|
||||
# define Segment LC_SEGMENT
|
||||
# define FileHeader mach_header
|
||||
# define SegmentCommand segment_command
|
||||
# define Section section
|
||||
# define NList struct nlist
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace avian::tools;
|
||||
|
||||
typedef int cpu_type_t;
|
||||
typedef int cpu_subtype_t;
|
||||
typedef int vm_prot_t;
|
||||
|
||||
struct mach_header_64 {
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
uint32_t flags;
|
||||
uint32_t reserved;
|
||||
};
|
||||
using avian::endian::Endianness;
|
||||
|
||||
struct segment_command_64 {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
char segname[16];
|
||||
uint64_t vmaddr;
|
||||
uint64_t vmsize;
|
||||
uint64_t fileoff;
|
||||
uint64_t filesize;
|
||||
vm_prot_t maxprot;
|
||||
vm_prot_t initprot;
|
||||
uint32_t nsects;
|
||||
uint32_t flags;
|
||||
};
|
||||
#define V1 Endianness<TargetLittleEndian>::v1
|
||||
#define V2 Endianness<TargetLittleEndian>::v2
|
||||
#define V3 Endianness<TargetLittleEndian>::v3
|
||||
#define V4 Endianness<TargetLittleEndian>::v4
|
||||
#define VANY Endianness<TargetLittleEndian>::vAny
|
||||
|
||||
struct section_64 {
|
||||
char sectname[16];
|
||||
char segname[16];
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
uint32_t offset;
|
||||
uint32_t align;
|
||||
uint32_t reloff;
|
||||
uint32_t nreloc;
|
||||
uint32_t flags;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
uint32_t reserved3;
|
||||
};
|
||||
template<class AddrTy, bool TargetLittleEndian = true>
|
||||
class MachOPlatform : public Platform {
|
||||
public:
|
||||
|
||||
struct nlist_64 {
|
||||
union {
|
||||
uint32_t n_strx;
|
||||
} n_un;
|
||||
uint8_t n_type;
|
||||
uint8_t n_sect;
|
||||
uint16_t n_desc;
|
||||
uint64_t n_value;
|
||||
};
|
||||
struct FileHeader {
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
|
||||
struct mach_header {
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct segment_command {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
char segname[16];
|
||||
uint32_t vmaddr;
|
||||
uint32_t vmsize;
|
||||
uint32_t fileoff;
|
||||
uint32_t filesize;
|
||||
vm_prot_t maxprot;
|
||||
vm_prot_t initprot;
|
||||
uint32_t nsects;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct section {
|
||||
char sectname[16];
|
||||
char segname[16];
|
||||
uint32_t addr;
|
||||
uint32_t size;
|
||||
uint32_t offset;
|
||||
uint32_t align;
|
||||
uint32_t reloff;
|
||||
uint32_t nreloc;
|
||||
uint32_t flags;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
};
|
||||
|
||||
struct symtab_command {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
uint32_t symoff;
|
||||
uint32_t nsyms;
|
||||
uint32_t stroff;
|
||||
uint32_t strsize;
|
||||
};
|
||||
|
||||
struct nlist {
|
||||
union {
|
||||
int32_t n_strx;
|
||||
} n_un;
|
||||
uint8_t n_type;
|
||||
uint8_t n_sect;
|
||||
int16_t n_desc;
|
||||
uint32_t n_value;
|
||||
};
|
||||
|
||||
inline unsigned
|
||||
pad(unsigned n)
|
||||
{
|
||||
return (n + ((BITS_PER_WORD / 8) - 1)) & ~((BITS_PER_WORD / 8) - 1);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
log(unsigned n)
|
||||
{
|
||||
unsigned r = 0;
|
||||
for (unsigned i = 1; i < n; ++r) i <<= 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* segmentName, const char* sectionName,
|
||||
unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType)
|
||||
{
|
||||
unsigned startNameLength = strlen(startName) + 1;
|
||||
unsigned endNameLength = strlen(endName) + 1;
|
||||
|
||||
FileHeader header = {
|
||||
V4(Magic), // magic
|
||||
V4(cpuType),
|
||||
V4(cpuSubType),
|
||||
V4(MH_OBJECT), // filetype,
|
||||
V4(2), // ncmds
|
||||
V4(sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // sizeofcmds
|
||||
V4(0) // flags
|
||||
union {
|
||||
uint32_t flags;
|
||||
AddrTy flagsAndMaybeReserved;
|
||||
};
|
||||
};
|
||||
|
||||
SegmentCommand segment = {
|
||||
V4(Segment), // cmd
|
||||
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
|
||||
"", // segname
|
||||
VW(0), // vmaddr
|
||||
VW(pad(size)), // vmsize
|
||||
VW(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // fileoff
|
||||
VW(pad(size)), // filesize
|
||||
V4(7), // maxprot
|
||||
V4(7), // initprot
|
||||
V4(1), // nsects
|
||||
V4(0) // flags
|
||||
|
||||
struct SegmentCommand {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
char segname[16];
|
||||
AddrTy vmaddr;
|
||||
AddrTy vmsize;
|
||||
AddrTy fileoff;
|
||||
AddrTy filesize;
|
||||
vm_prot_t maxprot;
|
||||
vm_prot_t initprot;
|
||||
uint32_t nsects;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
||||
|
||||
Section sect = {
|
||||
"", // sectname
|
||||
"", // segname
|
||||
VW(0), // addr
|
||||
VW(pad(size)), // size
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // offset
|
||||
V4(log(alignment)), // align
|
||||
V4(0), // reloff
|
||||
V4(0), // nreloc
|
||||
V4(S_REGULAR), // flags
|
||||
V4(0), // reserved1
|
||||
V4(0), // reserved2
|
||||
struct Section {
|
||||
char sectname[16];
|
||||
char segname[16];
|
||||
AddrTy addr;
|
||||
AddrTy size;
|
||||
uint32_t offset;
|
||||
uint32_t align;
|
||||
uint32_t reloff;
|
||||
uint32_t nreloc;
|
||||
uint32_t flags;
|
||||
uint32_t reserved1;
|
||||
AddrTy reserved2AndMaybe3;
|
||||
};
|
||||
|
||||
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
||||
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
||||
|
||||
symtab_command symbolTable = {
|
||||
V4(LC_SYMTAB), // cmd
|
||||
V4(sizeof(symtab_command)), // cmdsize
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size)), // symoff
|
||||
V4(2), // nsyms
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size)
|
||||
+ (sizeof(NList) * 2)), // stroff
|
||||
V4(1 + startNameLength + endNameLength), // strsize
|
||||
struct NList {
|
||||
union {
|
||||
uint32_t n_strx;
|
||||
} n_un;
|
||||
uint8_t n_type;
|
||||
uint8_t n_sect;
|
||||
uint16_t n_desc;
|
||||
AddrTy n_value;
|
||||
};
|
||||
|
||||
NList symbolList[] = {
|
||||
struct SymtabCommand {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
uint32_t symoff;
|
||||
uint32_t nsyms;
|
||||
uint32_t stroff;
|
||||
uint32_t strsize;
|
||||
};
|
||||
|
||||
static const unsigned BytesPerWord = sizeof(AddrTy);
|
||||
static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1;
|
||||
static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface;
|
||||
|
||||
static inline unsigned
|
||||
pad(unsigned n)
|
||||
{
|
||||
return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
log(unsigned n)
|
||||
{
|
||||
unsigned r = 0;
|
||||
for (unsigned i = 1; i < n; ++r) i <<= 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
class MachOObjectWriter : public ObjectWriter {
|
||||
public:
|
||||
|
||||
PlatformInfo::Architecture arch;
|
||||
|
||||
MachOObjectWriter(PlatformInfo::Architecture arch):
|
||||
arch(arch) {}
|
||||
|
||||
void writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* segmentName, const char* sectionName,
|
||||
unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType)
|
||||
{
|
||||
V4(1), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VW(0) // n_value
|
||||
},
|
||||
unsigned startNameLength = strlen(startName) + 1;
|
||||
unsigned endNameLength = strlen(endName) + 1;
|
||||
|
||||
FileHeader header = {
|
||||
V4(Magic), // magic
|
||||
V4(cpuType),
|
||||
V4(cpuSubType),
|
||||
V4(MH_OBJECT), // filetype,
|
||||
V4(2), // ncmds
|
||||
V4(sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)), // sizeofcmds
|
||||
V4(0) // flags
|
||||
};
|
||||
|
||||
SegmentCommand segment = {
|
||||
V4(Segment), // cmd
|
||||
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
|
||||
"", // segname
|
||||
VANY(static_cast<AddrTy>(0)), // vmaddr
|
||||
VANY(static_cast<AddrTy>(pad(size))), // vmsize
|
||||
VANY(static_cast<AddrTy>(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand))), // fileoff
|
||||
VANY(static_cast<AddrTy>(pad(size))), // filesize
|
||||
V4(7), // maxprot
|
||||
V4(7), // initprot
|
||||
V4(1), // nsects
|
||||
V4(0) // flags
|
||||
};
|
||||
|
||||
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
||||
|
||||
Section sect = {
|
||||
"", // sectname
|
||||
"", // segname
|
||||
VANY(static_cast<AddrTy>(0)), // addr
|
||||
VANY(static_cast<AddrTy>(pad(size))), // size
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)), // offset
|
||||
V4(log(alignment)), // align
|
||||
V4(0), // reloff
|
||||
V4(0), // nreloc
|
||||
V4(S_REGULAR), // flags
|
||||
V4(0), // reserved1
|
||||
V4(0), // reserved2
|
||||
};
|
||||
|
||||
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
||||
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
||||
|
||||
SymtabCommand symbolTable = {
|
||||
V4(LC_SYMTAB), // cmd
|
||||
V4(sizeof(SymtabCommand)), // cmdsize
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)
|
||||
+ pad(size)), // symoff
|
||||
V4(2), // nsyms
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)
|
||||
+ pad(size)
|
||||
+ (sizeof(NList) * 2)), // stroff
|
||||
V4(1 + startNameLength + endNameLength), // strsize
|
||||
};
|
||||
|
||||
NList symbolList[] = {
|
||||
{
|
||||
V4(1), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VANY(static_cast<AddrTy>(0)) // n_value
|
||||
},
|
||||
{
|
||||
V4(1 + startNameLength), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VANY(static_cast<AddrTy>(size)) // n_value
|
||||
}
|
||||
};
|
||||
|
||||
fwrite(&header, 1, sizeof(header), out);
|
||||
fwrite(&segment, 1, sizeof(segment), out);
|
||||
fwrite(§, 1, sizeof(sect), out);
|
||||
fwrite(&symbolTable, 1, sizeof(symbolTable), out);
|
||||
|
||||
fwrite(data, 1, size, out);
|
||||
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out);
|
||||
|
||||
fwrite(&symbolList, 1, sizeof(symbolList), out);
|
||||
|
||||
fputc(0, out);
|
||||
fwrite(startName, 1, startNameLength, out);
|
||||
fwrite(endName, 1, endNameLength, out);
|
||||
}
|
||||
|
||||
virtual bool write(uint8_t* data, size_t size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
unsigned alignment, unsigned accessFlags)
|
||||
{
|
||||
V4(1 + startNameLength), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VW(size) // n_value
|
||||
|
||||
cpu_type_t cpuType;
|
||||
cpu_subtype_t cpuSubType;
|
||||
if (arch == PlatformInfo::x86_64) {
|
||||
cpuType = CPU_TYPE_X86_64;
|
||||
cpuSubType = CPU_SUBTYPE_X86_64_ALL;
|
||||
} else if (arch == PlatformInfo::x86) {
|
||||
cpuType = CPU_TYPE_I386;
|
||||
cpuSubType = CPU_SUBTYPE_I386_ALL;
|
||||
} else if (arch == PlatformInfo::PowerPC) {
|
||||
cpuType = CPU_TYPE_POWERPC;
|
||||
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
|
||||
} else if (arch == PlatformInfo::Arm) {
|
||||
cpuType = CPU_TYPE_ARM;
|
||||
cpuSubType = CPU_SUBTYPE_ARM_V7;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %d\n", arch);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* segmentName;
|
||||
const char* sectionName;
|
||||
if (accessFlags & Writable) {
|
||||
if (accessFlags & Executable) {
|
||||
segmentName = "__RWX";
|
||||
sectionName = "__rwx";
|
||||
} else {
|
||||
segmentName = "__DATA";
|
||||
sectionName = "__data";
|
||||
}
|
||||
} else {
|
||||
segmentName = "__TEXT";
|
||||
sectionName = "__text";
|
||||
}
|
||||
|
||||
unsigned startNameLength = strlen(startName);
|
||||
char myStartName[startNameLength + 2];
|
||||
myStartName[0] = '_';
|
||||
memcpy(myStartName + 1, startName, startNameLength + 1);
|
||||
|
||||
unsigned endNameLength = strlen(endName);
|
||||
char myEndName[endNameLength + 2];
|
||||
myEndName[0] = '_';
|
||||
memcpy(myEndName + 1, endName, endNameLength + 1);
|
||||
|
||||
writeObject(data, size, out, myStartName, myEndName, segmentName,
|
||||
sectionName, alignment, cpuType, cpuSubType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
MachOPlatform(PlatformInfo::Architecture arch):
|
||||
Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {}
|
||||
|
||||
fwrite(&header, 1, sizeof(header), out);
|
||||
fwrite(&segment, 1, sizeof(segment), out);
|
||||
fwrite(§, 1, sizeof(sect), out);
|
||||
fwrite(&symbolTable, 1, sizeof(symbolTable), out);
|
||||
virtual ObjectWriter* makeObjectWriter() {
|
||||
return new MachOObjectWriter(info.arch);
|
||||
}
|
||||
};
|
||||
|
||||
fwrite(data, 1, size, out);
|
||||
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out);
|
||||
|
||||
fwrite(&symbolList, 1, sizeof(symbolList), out);
|
||||
|
||||
fputc(0, out);
|
||||
fwrite(startName, 1, startNameLength, out);
|
||||
fwrite(endName, 1, endNameLength, out);
|
||||
}
|
||||
MachOPlatform<uint32_t> darwinx86Platform(PlatformInfo::x86);
|
||||
MachOPlatform<uint32_t> darwinArmPlatform(PlatformInfo::Arm);
|
||||
MachOPlatform<uint32_t, false> darwinPowerPCPlatform(PlatformInfo::PowerPC);
|
||||
MachOPlatform<uint64_t> darwinx86_64Platform(PlatformInfo::x86_64);
|
||||
|
||||
} // namespace
|
||||
|
||||
#define MACRO_MAKE_NAME(a, b, c) a##b##c
|
||||
#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c)
|
||||
|
||||
namespace binaryToObject {
|
||||
|
||||
bool
|
||||
MAKE_NAME(writeMachO, BITS_PER_WORD, Object)
|
||||
(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture, unsigned alignment,
|
||||
bool writable, bool executable)
|
||||
{
|
||||
cpu_type_t cpuType;
|
||||
cpu_subtype_t cpuSubType;
|
||||
if (strcmp(architecture, "x86_64") == 0) {
|
||||
cpuType = CPU_TYPE_X86_64;
|
||||
cpuSubType = CPU_SUBTYPE_X86_64_ALL;
|
||||
} else if (strcmp(architecture, "i386") == 0) {
|
||||
cpuType = CPU_TYPE_I386;
|
||||
cpuSubType = CPU_SUBTYPE_I386_ALL;
|
||||
} else if (strcmp(architecture, "powerpc") == 0) {
|
||||
cpuType = CPU_TYPE_POWERPC;
|
||||
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
|
||||
} else if (strcmp(architecture, "arm") == 0) {
|
||||
cpuType = CPU_TYPE_ARM;
|
||||
cpuSubType = CPU_SUBTYPE_ARM_V7;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %s\n", architecture);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* segmentName;
|
||||
const char* sectionName;
|
||||
if (writable) {
|
||||
if (executable) {
|
||||
segmentName = "__RWX";
|
||||
sectionName = "__rwx";
|
||||
} else {
|
||||
segmentName = "__DATA";
|
||||
sectionName = "__data";
|
||||
}
|
||||
} else {
|
||||
segmentName = "__TEXT";
|
||||
sectionName = "__text";
|
||||
}
|
||||
|
||||
unsigned startNameLength = strlen(startName);
|
||||
char myStartName[startNameLength + 2];
|
||||
myStartName[0] = '_';
|
||||
memcpy(myStartName + 1, startName, startNameLength + 1);
|
||||
|
||||
unsigned endNameLength = strlen(endName);
|
||||
char myEndName[endNameLength + 2];
|
||||
myEndName[0] = '_';
|
||||
memcpy(myEndName + 1, endName, endNameLength + 1);
|
||||
|
||||
writeObject(data, size, out, myStartName, myEndName, segmentName,
|
||||
sectionName, alignment, cpuType, cpuSubType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace binaryToObject
|
||||
|
@ -8,110 +8,61 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sys/stat.h"
|
||||
#include <sys/stat.h>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include "sys/mman.h"
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include "fcntl.h"
|
||||
#include "unistd.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace binaryToObject {
|
||||
#include "tools.h"
|
||||
|
||||
bool
|
||||
writeElf64Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
extern "C"
|
||||
void __cxa_pure_virtual() {
|
||||
abort();
|
||||
}
|
||||
|
||||
bool
|
||||
writeElf32Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
void* operator new(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
bool
|
||||
writeMachO64Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
|
||||
bool
|
||||
writeMachO32Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
|
||||
bool
|
||||
writePEObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture,
|
||||
unsigned alignment, bool writable, bool executable);
|
||||
|
||||
} // namespace binaryToObject
|
||||
void operator delete(void* mem) {
|
||||
if(mem) {
|
||||
free(mem);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace avian::tools;
|
||||
|
||||
bool
|
||||
writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* platform,
|
||||
const char* endName, const char* os,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable)
|
||||
{
|
||||
using namespace binaryToObject;
|
||||
Platform* platform = Platform::getPlatform(PlatformInfo(os, architecture));
|
||||
|
||||
bool found = false;
|
||||
bool success = false;
|
||||
if (strcmp("linux", platform) == 0) {
|
||||
if (strcmp("x86_64", architecture) == 0) {
|
||||
found = true;
|
||||
success = writeElf64Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
} else if (strcmp("i386", architecture) == 0
|
||||
or strcmp("arm", architecture) == 0
|
||||
or strcmp("powerpc", architecture) == 0)
|
||||
{
|
||||
found = true;
|
||||
success = writeElf32Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
}
|
||||
} else if (strcmp("darwin", platform) == 0) {
|
||||
if (strcmp("x86_64", architecture) == 0) {
|
||||
found = true;
|
||||
success = writeMachO64Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
} else if (strcmp("i386", architecture) == 0
|
||||
or strcmp("powerpc", architecture) == 0
|
||||
or strcmp("arm", architecture) == 0)
|
||||
{
|
||||
found = true;
|
||||
success = writeMachO32Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
}
|
||||
} else if (strcmp("windows", platform) == 0
|
||||
and ((strcmp("x86_64", architecture) == 0
|
||||
or strcmp("i386", architecture) == 0)))
|
||||
{
|
||||
found = true;
|
||||
success = writePEObject
|
||||
(data, size, out, startName, endName, architecture, alignment, writable,
|
||||
executable);
|
||||
}
|
||||
|
||||
if (not found) {
|
||||
fprintf(stderr, "unsupported platform: %s/%s\n", platform, architecture);
|
||||
if(!platform) {
|
||||
fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture);
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectWriter* writer = platform->makeObjectWriter();
|
||||
|
||||
bool success = writer->write(data, size, out, startName, endName, alignment,
|
||||
ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0));
|
||||
|
||||
writer->dispose();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -8,16 +8,20 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
|
||||
#define IMAGE_FILE_RELOCS_STRIPPED 1
|
||||
#define IMAGE_FILE_LINE_NUMS_STRIPPED 4
|
||||
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_32BIT_MACHINE 256
|
||||
|
||||
#define IMAGE_SCN_ALIGN_1BYTES 0x100000
|
||||
@ -29,8 +33,6 @@
|
||||
#define IMAGE_SCN_MEM_WRITE 0x80000000
|
||||
#define IMAGE_SCN_CNT_CODE 32
|
||||
|
||||
namespace {
|
||||
|
||||
struct IMAGE_FILE_HEADER {
|
||||
uint16_t Machine;
|
||||
uint16_t NumberOfSections;
|
||||
@ -161,71 +163,89 @@ writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
fwrite(endName, 1, endNameLength, out);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
using namespace avian::tools;
|
||||
|
||||
namespace binaryToObject {
|
||||
template<unsigned BytesPerWord>
|
||||
class WindowsPlatform : public Platform {
|
||||
public:
|
||||
|
||||
bool
|
||||
writePEObject
|
||||
(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture, unsigned alignment,
|
||||
bool writable, bool executable)
|
||||
{
|
||||
int machine;
|
||||
int machineMask;
|
||||
if (strcmp(architecture, "x86_64") == 0) {
|
||||
machine = IMAGE_FILE_MACHINE_AMD64;
|
||||
machineMask = 0;
|
||||
} else if (strcmp(architecture, "i386") == 0) {
|
||||
machine = IMAGE_FILE_MACHINE_I386;
|
||||
machineMask = IMAGE_FILE_32BIT_MACHINE;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %s\n", architecture);
|
||||
return false;
|
||||
}
|
||||
class PEObjectWriter : public ObjectWriter {
|
||||
public:
|
||||
|
||||
int sectionMask;
|
||||
switch (alignment) {
|
||||
case 0:
|
||||
case 1:
|
||||
sectionMask = IMAGE_SCN_ALIGN_1BYTES;
|
||||
break;
|
||||
case 2:
|
||||
sectionMask = IMAGE_SCN_ALIGN_2BYTES;
|
||||
break;
|
||||
case 4:
|
||||
sectionMask = IMAGE_SCN_ALIGN_4BYTES;
|
||||
break;
|
||||
case 8:
|
||||
sectionMask = IMAGE_SCN_ALIGN_8BYTES;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unsupported alignment: %d\n", alignment);
|
||||
return false;
|
||||
}
|
||||
virtual bool write(uint8_t* data, size_t size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
unsigned alignment, unsigned accessFlags)
|
||||
{
|
||||
int machine;
|
||||
int machineMask;
|
||||
|
||||
sectionMask |= IMAGE_SCN_MEM_READ;
|
||||
if (BytesPerWord == 8) {
|
||||
machine = IMAGE_FILE_MACHINE_AMD64;
|
||||
machineMask = 0;
|
||||
} else { // if (BytesPerWord == 8)
|
||||
machine = IMAGE_FILE_MACHINE_I386;
|
||||
machineMask = IMAGE_FILE_32BIT_MACHINE;
|
||||
}
|
||||
|
||||
const char* sectionName;
|
||||
if (writable) {
|
||||
if (executable) {
|
||||
sectionName = ".rwx";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE
|
||||
| IMAGE_SCN_MEM_EXECUTE
|
||||
| IMAGE_SCN_CNT_CODE;
|
||||
} else {
|
||||
sectionName = ".data";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE;
|
||||
int sectionMask;
|
||||
switch (alignment) {
|
||||
case 0:
|
||||
case 1:
|
||||
sectionMask = IMAGE_SCN_ALIGN_1BYTES;
|
||||
break;
|
||||
case 2:
|
||||
sectionMask = IMAGE_SCN_ALIGN_2BYTES;
|
||||
break;
|
||||
case 4:
|
||||
sectionMask = IMAGE_SCN_ALIGN_4BYTES;
|
||||
break;
|
||||
case 8:
|
||||
sectionMask = IMAGE_SCN_ALIGN_8BYTES;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unsupported alignment: %d\n", alignment);
|
||||
return false;
|
||||
}
|
||||
|
||||
sectionMask |= IMAGE_SCN_MEM_READ;
|
||||
|
||||
const char* sectionName;
|
||||
if (accessFlags & ObjectWriter::Writable) {
|
||||
if (accessFlags & ObjectWriter::Executable) {
|
||||
sectionName = ".rwx";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE
|
||||
| IMAGE_SCN_MEM_EXECUTE
|
||||
| IMAGE_SCN_CNT_CODE;
|
||||
} else {
|
||||
sectionName = ".data";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE;
|
||||
}
|
||||
} else {
|
||||
sectionName = ".text";
|
||||
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
|
||||
}
|
||||
|
||||
writeObject(data, size, out, startName, endName, sectionName, machine,
|
||||
machineMask, sectionMask);
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
sectionName = ".text";
|
||||
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
|
||||
|
||||
virtual void dispose() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
virtual ObjectWriter* makeObjectWriter() {
|
||||
return new PEObjectWriter();
|
||||
}
|
||||
|
||||
writeObject(data, size, out, startName, endName, sectionName, machine,
|
||||
machineMask, sectionMask);
|
||||
WindowsPlatform():
|
||||
Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {}
|
||||
};
|
||||
|
||||
WindowsPlatform<4> windows32Platform;
|
||||
WindowsPlatform<8> windows64Platform;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace binaryToObject
|
||||
|
62
src/binaryToObject/tools.cpp
Normal file
62
src/binaryToObject/tools.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/* Copyright (c) 2009, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
namespace avian {
|
||||
|
||||
namespace tools {
|
||||
|
||||
|
||||
Platform* Platform::first = 0;
|
||||
|
||||
PlatformInfo::OperatingSystem PlatformInfo::osFromString(const char* os) {
|
||||
if(strcmp(os, "linux") == 0) {
|
||||
return Linux;
|
||||
} else if(strcmp(os, "windows") == 0) {
|
||||
return Windows;
|
||||
} else if(strcmp(os, "darwin") == 0) {
|
||||
return Darwin;
|
||||
} else {
|
||||
return UnknownOS;
|
||||
}
|
||||
}
|
||||
|
||||
PlatformInfo::Architecture PlatformInfo::archFromString(const char* arch) {
|
||||
if(strcmp(arch, "i386") == 0) {
|
||||
return x86;
|
||||
} else if(strcmp(arch, "x86_64") == 0) {
|
||||
return x86_64;
|
||||
} else if(strcmp(arch, "powerpc") == 0) {
|
||||
return PowerPC;
|
||||
} else if(strcmp(arch, "arm") == 0) {
|
||||
return Arm;
|
||||
} else {
|
||||
return UnknownArch;
|
||||
}
|
||||
}
|
||||
|
||||
Platform* Platform::getPlatform(PlatformInfo info) {
|
||||
for(Platform* p = first; p; p = p->next) {
|
||||
if(p->info == info) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace tools
|
||||
|
||||
} // namespace avian
|
90
src/binaryToObject/tools.h
Normal file
90
src/binaryToObject/tools.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright (c) 2009, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#ifndef AVIAN_TOOLS_H_
|
||||
#define AVIAN_TOOLS_H_
|
||||
|
||||
namespace avian {
|
||||
|
||||
namespace tools {
|
||||
|
||||
class ObjectWriter {
|
||||
public:
|
||||
|
||||
enum AccessFlags {
|
||||
Readable = 1 << 0,
|
||||
Writable = 1 << 1,
|
||||
Executable = 1 << 2
|
||||
};
|
||||
|
||||
virtual bool write(uint8_t* data, size_t size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
unsigned alignment, unsigned accessFlags) = 0;
|
||||
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
class PlatformInfo {
|
||||
public:
|
||||
enum OperatingSystem {
|
||||
Linux, Windows, Darwin, UnknownOS
|
||||
};
|
||||
|
||||
enum Architecture {
|
||||
x86, x86_64, PowerPC, Arm, UnknownArch
|
||||
};
|
||||
|
||||
const OperatingSystem os;
|
||||
const Architecture arch;
|
||||
|
||||
static OperatingSystem osFromString(const char* os);
|
||||
static Architecture archFromString(const char* arch);
|
||||
|
||||
inline PlatformInfo(OperatingSystem os, Architecture arch):
|
||||
os(os),
|
||||
arch(arch) {}
|
||||
|
||||
inline PlatformInfo(const char* os, const char* arch):
|
||||
os(osFromString(os)),
|
||||
arch(archFromString(arch)) {}
|
||||
|
||||
inline bool operator == (const PlatformInfo& other) {
|
||||
return os == other.os && arch == other.arch;
|
||||
}
|
||||
|
||||
inline bool isLittleEndian() {
|
||||
return arch != PowerPC;
|
||||
}
|
||||
};
|
||||
|
||||
class Platform {
|
||||
private:
|
||||
Platform* next;
|
||||
static Platform* first;
|
||||
public:
|
||||
PlatformInfo info;
|
||||
|
||||
inline Platform(PlatformInfo info):
|
||||
next(first),
|
||||
info(info)
|
||||
{
|
||||
first = this;
|
||||
}
|
||||
|
||||
virtual ObjectWriter* makeObjectWriter() = 0;
|
||||
|
||||
static Platform* getPlatform(PlatformInfo info);
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
|
||||
} // namespace avian
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user