mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +00:00
Merge remote-tracking branch 'origin/master' into jdk7
This commit is contained in:
commit
20a0823a74
58
makefile
58
makefile
@ -241,7 +241,6 @@ ifeq ($(arch),powerpc)
|
||||
|
||||
ifneq ($(platform),darwin)
|
||||
ifneq ($(arch),$(build-arch))
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
cxx = powerpc-linux-gnu-g++
|
||||
cc = powerpc-linux-gnu-gcc
|
||||
ar = powerpc-linux-gnu-ar
|
||||
@ -341,9 +340,6 @@ ifeq ($(platform),darwin)
|
||||
x := $(error "couldn't find SDK for iOS version")
|
||||
endif
|
||||
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
flags = -arch armv7 -isysroot \
|
||||
$(sdk-dir)/iPhoneOS$(ios-version).sdk/
|
||||
openjdk-extra-cflags += $(flags)
|
||||
@ -353,9 +349,6 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(arch),powerpc)
|
||||
ifneq (,$(filter i386 x86_64 arm,$(build-arch)))
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
@ -363,9 +356,6 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(arch),i386)
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION}
|
||||
@ -373,9 +363,6 @@ ifeq ($(platform),darwin)
|
||||
endif
|
||||
|
||||
ifeq ($(arch),x86_64)
|
||||
ifeq ($(build-arch),powerpc)
|
||||
converter-cflags += -DOPPOSITE_ENDIAN
|
||||
endif
|
||||
openjdk-extra-cflags += -arch x86_64
|
||||
cflags += -arch x86_64
|
||||
asmflags += -arch x86_64
|
||||
@ -444,6 +431,7 @@ endif
|
||||
|
||||
ifeq ($(mode),debug)
|
||||
optimization-cflags = -O0 -g3
|
||||
converter-cflags += -O0 -g3
|
||||
strip = :
|
||||
endif
|
||||
ifeq ($(mode),debug-fast)
|
||||
@ -636,14 +624,20 @@ generator-objects = \
|
||||
$(call generator-cpp-objects,$(generator-sources),$(src),$(build))
|
||||
generator = $(build)/generator
|
||||
|
||||
converter-objects = \
|
||||
$(build)/binaryToObject-main.o \
|
||||
$(build)/binaryToObject-elf64.o \
|
||||
$(build)/binaryToObject-elf32.o \
|
||||
$(build)/binaryToObject-mach-o64.o \
|
||||
$(build)/binaryToObject-mach-o32.o \
|
||||
$(build)/binaryToObject-pe.o
|
||||
converter = $(build)/binaryToObject
|
||||
converter-depends = \
|
||||
$(src)/binaryToObject/tools.h \
|
||||
$(src)/binaryToObject/endianness.h
|
||||
|
||||
|
||||
converter-sources = \
|
||||
$(src)/binaryToObject/main.cpp \
|
||||
$(src)/binaryToObject/tools.cpp \
|
||||
$(src)/binaryToObject/elf.cpp \
|
||||
$(src)/binaryToObject/mach-o.cpp \
|
||||
$(src)/binaryToObject/pe.cpp
|
||||
|
||||
converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build))
|
||||
converter = $(build)/binaryToObject/binaryToObject
|
||||
|
||||
static-library = $(build)/lib$(name).a
|
||||
executable = $(build)/$(name)${exe-suffix}
|
||||
@ -848,26 +842,12 @@ $(boot-object): $(boot-source)
|
||||
$(boot-javahome-object): $(src)/boot-javahome.cpp
|
||||
$(compile-object)
|
||||
|
||||
$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
|
||||
$(build-cxx) $(converter-cflags) -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-mach-o32.o: $(src)/binaryToObject/mach-o.cpp
|
||||
$(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@)
|
||||
|
||||
$(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp
|
||||
$(build-cxx) $(converter-cflags) -c $(^) -o $(@)
|
||||
$(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends)
|
||||
@mkdir -p $(dir $(@))
|
||||
$(build-cxx) $(converter-cflags) -c $(<) -o $(@)
|
||||
|
||||
$(converter): $(converter-objects)
|
||||
$(build-cc) $(^) -o $(@)
|
||||
$(build-cc) $(^) -g -o $(@)
|
||||
|
||||
$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep)
|
||||
@echo "creating $(@)"
|
||||
|
@ -8,12 +8,15 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "endianness.h"
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
#define EI_MAG0 0
|
||||
@ -62,344 +65,316 @@
|
||||
|
||||
#define STV_DEFAULT 0
|
||||
|
||||
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
#define ELF32_ST_INFO(bind, type) ELF64_ST_INFO((bind), (type))
|
||||
|
||||
#if (BITS_PER_WORD == 64)
|
||||
# define FileHeader Elf64_Ehdr
|
||||
# define SectionHeader Elf64_Shdr
|
||||
# define Symbol Elf64_Sym
|
||||
# define Class ELFCLASS64
|
||||
# define SYMBOL_INFO ELF64_ST_INFO
|
||||
#elif (BITS_PER_WORD == 32)
|
||||
# define FileHeader Elf32_Ehdr
|
||||
# define SectionHeader Elf32_Shdr
|
||||
# define Symbol Elf32_Sym
|
||||
# define Class ELFCLASS32
|
||||
# define SYMBOL_INFO ELF32_ST_INFO
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
#define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
|
||||
#define OSABI ELFOSABI_SYSV
|
||||
|
||||
namespace {
|
||||
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef uint16_t Elf64_Section;
|
||||
typedef uint64_t Elf64_Off;
|
||||
using namespace avian::tools;
|
||||
|
||||
struct Elf64_Ehdr {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
template<class AddrTy>
|
||||
struct ElfTypes {
|
||||
typedef uint16_t Half;
|
||||
typedef uint32_t Word;
|
||||
typedef AddrTy Addr;
|
||||
typedef uint64_t Xword;
|
||||
typedef uint16_t Section;
|
||||
typedef AddrTy Off;
|
||||
typedef AddrTy XFlags;
|
||||
static const unsigned BytesPerWord = sizeof(AddrTy);
|
||||
};
|
||||
|
||||
struct Elf64_Shdr {
|
||||
Elf64_Word sh_name;
|
||||
Elf64_Word sh_type;
|
||||
Elf64_Xword sh_flags;
|
||||
Elf64_Addr sh_addr;
|
||||
Elf64_Off sh_offset;
|
||||
Elf64_Xword sh_size;
|
||||
Elf64_Word sh_link;
|
||||
Elf64_Word sh_info;
|
||||
Elf64_Xword sh_addralign;
|
||||
Elf64_Xword sh_entsize;
|
||||
};
|
||||
template<class AddrTy>
|
||||
struct Symbol_Ty;
|
||||
|
||||
struct Elf64_Sym {
|
||||
Elf64_Word st_name;
|
||||
template<>
|
||||
struct Symbol_Ty<uint64_t> {
|
||||
typedef ElfTypes<uint64_t> Elf;
|
||||
|
||||
Elf::Word st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf64_Section st_shndx;
|
||||
Elf64_Addr st_value;
|
||||
Elf64_Xword st_size;
|
||||
Elf::Section st_shndx;
|
||||
Elf::Addr st_value;
|
||||
Elf::Xword st_size;
|
||||
};
|
||||
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Word;
|
||||
typedef uint32_t Elf32_Addr;
|
||||
typedef uint64_t Elf32_Xword;
|
||||
typedef uint16_t Elf32_Section;
|
||||
typedef uint32_t Elf32_Off;
|
||||
template<>
|
||||
struct Symbol_Ty<uint32_t> {
|
||||
typedef ElfTypes<uint32_t> Elf;
|
||||
|
||||
struct Elf32_Ehdr {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf32_Half e_type;
|
||||
Elf32_Half e_machine;
|
||||
Elf32_Word e_version;
|
||||
Elf32_Addr e_entry;
|
||||
Elf32_Off e_phoff;
|
||||
Elf32_Off e_shoff;
|
||||
Elf32_Word e_flags;
|
||||
Elf32_Half e_ehsize;
|
||||
Elf32_Half e_phentsize;
|
||||
Elf32_Half e_phnum;
|
||||
Elf32_Half e_shentsize;
|
||||
Elf32_Half e_shnum;
|
||||
Elf32_Half e_shstrndx;
|
||||
};
|
||||
|
||||
struct Elf32_Shdr {
|
||||
Elf32_Word sh_name;
|
||||
Elf32_Word sh_type;
|
||||
Elf32_Word sh_flags;
|
||||
Elf32_Addr sh_addr;
|
||||
Elf32_Off sh_offset;
|
||||
Elf32_Word sh_size;
|
||||
Elf32_Word sh_link;
|
||||
Elf32_Word sh_info;
|
||||
Elf32_Word sh_addralign;
|
||||
Elf32_Word sh_entsize;
|
||||
};
|
||||
|
||||
struct Elf32_Sym {
|
||||
Elf32_Word st_name;
|
||||
Elf32_Addr st_value;
|
||||
Elf32_Word st_size;
|
||||
Elf::Word st_name;
|
||||
Elf::Addr st_value;
|
||||
Elf::Word st_size;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf32_Section st_shndx;
|
||||
Elf::Section st_shndx;
|
||||
};
|
||||
|
||||
void
|
||||
writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* sectionName, unsigned sectionFlags,
|
||||
unsigned alignment, int machine, int encoding)
|
||||
{
|
||||
const unsigned sectionCount = 5;
|
||||
const unsigned symbolCount = 2;
|
||||
using avian::endian::Endianness;
|
||||
|
||||
const unsigned sectionNameLength = strlen(sectionName) + 1;
|
||||
const unsigned startNameLength = strlen(startName) + 1;
|
||||
const unsigned endNameLength = strlen(endName) + 1;
|
||||
#define V1 Endianness<TargetLittleEndian>::v1
|
||||
#define V2 Endianness<TargetLittleEndian>::v2
|
||||
#define V3 Endianness<TargetLittleEndian>::v3
|
||||
#define V4 Endianness<TargetLittleEndian>::v4
|
||||
#define VANY Endianness<TargetLittleEndian>::vAny
|
||||
|
||||
const char* const sectionStringTableName = ".shstrtab";
|
||||
const char* const stringTableName = ".strtab";
|
||||
const char* const symbolTableName = ".symtab";
|
||||
|
||||
const unsigned sectionStringTableNameLength
|
||||
= strlen(sectionStringTableName) + 1;
|
||||
const unsigned stringTableNameLength = strlen(stringTableName) + 1;
|
||||
const unsigned symbolTableNameLength = strlen(symbolTableName) + 1;
|
||||
|
||||
const unsigned nullStringOffset = 0;
|
||||
|
||||
const unsigned sectionStringTableNameOffset = nullStringOffset + 1;
|
||||
const unsigned stringTableNameOffset
|
||||
= sectionStringTableNameOffset + sectionStringTableNameLength;
|
||||
const unsigned symbolTableNameOffset
|
||||
= stringTableNameOffset + stringTableNameLength;
|
||||
const unsigned sectionNameOffset
|
||||
= symbolTableNameOffset + symbolTableNameLength;
|
||||
const unsigned sectionStringTableLength
|
||||
= sectionNameOffset + sectionNameLength;
|
||||
|
||||
const unsigned startNameOffset = nullStringOffset + 1;
|
||||
const unsigned endNameOffset = startNameOffset + startNameLength;
|
||||
const unsigned stringTableLength = endNameOffset + endNameLength;
|
||||
|
||||
const unsigned bodySectionNumber = 1;
|
||||
const unsigned sectionStringTableSectionNumber = 2;
|
||||
const unsigned stringTableSectionNumber = 3;
|
||||
|
||||
FileHeader fileHeader;
|
||||
memset(&fileHeader, 0, sizeof(FileHeader));
|
||||
fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0);
|
||||
fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1);
|
||||
fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2);
|
||||
fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3);
|
||||
fileHeader.e_ident[EI_CLASS] = V1(Class);
|
||||
fileHeader.e_ident[EI_DATA] = V1(encoding);
|
||||
fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT);
|
||||
fileHeader.e_ident[EI_OSABI] = V1(OSABI);
|
||||
fileHeader.e_ident[EI_ABIVERSION] = V1(0);
|
||||
fileHeader.e_type = V2(ET_REL);
|
||||
fileHeader.e_machine = V2(machine);
|
||||
fileHeader.e_version = V4(EV_CURRENT);
|
||||
fileHeader.e_entry = VW(0);
|
||||
fileHeader.e_phoff = VW(0);
|
||||
fileHeader.e_shoff = VW(sizeof(FileHeader));
|
||||
fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
|
||||
fileHeader.e_ehsize = V2(sizeof(FileHeader));
|
||||
fileHeader.e_phentsize = V2(0);
|
||||
fileHeader.e_phnum = V2(0);
|
||||
fileHeader.e_shentsize = V2(sizeof(SectionHeader));
|
||||
fileHeader.e_shnum = V2(sectionCount);
|
||||
fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber);
|
||||
|
||||
SectionHeader nullSection;
|
||||
memset(&nullSection, 0, sizeof(SectionHeader));
|
||||
|
||||
SectionHeader bodySection;
|
||||
bodySection.sh_name = V4(sectionNameOffset);
|
||||
bodySection.sh_type = V4(SHT_PROGBITS);
|
||||
bodySection.sh_flags = VW(sectionFlags);
|
||||
bodySection.sh_addr = VW(0);
|
||||
unsigned bodySectionOffset
|
||||
= sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount);
|
||||
bodySection.sh_offset = VW(bodySectionOffset);
|
||||
unsigned bodySectionSize = size;
|
||||
bodySection.sh_size = VW(bodySectionSize);
|
||||
bodySection.sh_link = V4(0);
|
||||
bodySection.sh_info = V4(0);
|
||||
bodySection.sh_addralign = VW(alignment);
|
||||
bodySection.sh_entsize = VW(0);
|
||||
|
||||
SectionHeader sectionStringTableSection;
|
||||
sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset);
|
||||
sectionStringTableSection.sh_type = V4(SHT_STRTAB);
|
||||
sectionStringTableSection.sh_flags = VW(0);
|
||||
sectionStringTableSection.sh_addr = VW(0);
|
||||
unsigned sectionStringTableSectionOffset
|
||||
= bodySectionOffset + bodySectionSize;
|
||||
sectionStringTableSection.sh_offset = VW(sectionStringTableSectionOffset);
|
||||
unsigned sectionStringTableSectionSize = sectionStringTableLength;
|
||||
sectionStringTableSection.sh_size = VW(sectionStringTableSectionSize);
|
||||
sectionStringTableSection.sh_link = V4(0);
|
||||
sectionStringTableSection.sh_info = V4(0);
|
||||
sectionStringTableSection.sh_addralign = VW(1);
|
||||
sectionStringTableSection.sh_entsize = VW(0);
|
||||
|
||||
SectionHeader stringTableSection;
|
||||
stringTableSection.sh_name = V4(stringTableNameOffset);
|
||||
stringTableSection.sh_type = V4(SHT_STRTAB);
|
||||
stringTableSection.sh_flags = VW(0);
|
||||
stringTableSection.sh_addr = VW(0);
|
||||
unsigned stringTableSectionOffset
|
||||
= sectionStringTableSectionOffset + sectionStringTableSectionSize;
|
||||
stringTableSection.sh_offset = VW(stringTableSectionOffset);
|
||||
unsigned stringTableSectionSize = stringTableLength;
|
||||
stringTableSection.sh_size = VW(stringTableSectionSize);
|
||||
stringTableSection.sh_link = V4(0);
|
||||
stringTableSection.sh_info = V4(0);
|
||||
stringTableSection.sh_addralign = VW(1);
|
||||
stringTableSection.sh_entsize = VW(0);
|
||||
|
||||
SectionHeader symbolTableSection;
|
||||
symbolTableSection.sh_name = V4(symbolTableNameOffset);
|
||||
symbolTableSection.sh_type = V4(SHT_SYMTAB);
|
||||
symbolTableSection.sh_flags = VW(0);
|
||||
symbolTableSection.sh_addr = VW(0);
|
||||
unsigned symbolTableSectionOffset
|
||||
= stringTableSectionOffset + stringTableSectionSize;
|
||||
symbolTableSection.sh_offset = VW(symbolTableSectionOffset);
|
||||
unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount;
|
||||
symbolTableSection.sh_size = VW(symbolTableSectionSize);
|
||||
symbolTableSection.sh_link = V4(stringTableSectionNumber);
|
||||
symbolTableSection.sh_info = V4(0);
|
||||
symbolTableSection.sh_addralign = VW(BITS_PER_WORD / 8);
|
||||
symbolTableSection.sh_entsize = VW(sizeof(Symbol));
|
||||
|
||||
Symbol startSymbol;
|
||||
startSymbol.st_name = V4(startNameOffset);
|
||||
startSymbol.st_value = VW(0);
|
||||
startSymbol.st_size = VW(0);
|
||||
startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
||||
startSymbol.st_other = V1(STV_DEFAULT);
|
||||
startSymbol.st_shndx = V2(bodySectionNumber);
|
||||
|
||||
Symbol endSymbol;
|
||||
endSymbol.st_name = V4(endNameOffset);
|
||||
endSymbol.st_value = VW(size);
|
||||
endSymbol.st_size = VW(0);
|
||||
endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
||||
endSymbol.st_other = V1(STV_DEFAULT);
|
||||
endSymbol.st_shndx = V2(bodySectionNumber);
|
||||
|
||||
fwrite(&fileHeader, 1, sizeof(fileHeader), out);
|
||||
fwrite(&nullSection, 1, sizeof(nullSection), out);
|
||||
fwrite(&bodySection, 1, sizeof(bodySection), out);
|
||||
fwrite(§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);
|
||||
unsigned getElfPlatform(PlatformInfo::Architecture arch) {
|
||||
switch(arch) {
|
||||
case PlatformInfo::x86_64:
|
||||
return EM_X86_64;
|
||||
case PlatformInfo::x86:
|
||||
return EM_386;
|
||||
case PlatformInfo::Arm:
|
||||
return EM_ARM;
|
||||
case PlatformInfo::PowerPC:
|
||||
return EM_PPC;
|
||||
}
|
||||
return ~0;
|
||||
}
|
||||
|
||||
const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) {
|
||||
sectionFlags = SHF_ALLOC;
|
||||
if (accessFlags & Platform::Writable) {
|
||||
if (accessFlags & Platform::Executable) {
|
||||
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
|
||||
return ".rwx";
|
||||
} else {
|
||||
sectionFlags |= SHF_WRITE;
|
||||
return ".data";
|
||||
}
|
||||
} else if (accessFlags & Platform::Executable) {
|
||||
sectionFlags |= SHF_EXECINSTR;
|
||||
return ".text";
|
||||
} else {
|
||||
return ".rodata";
|
||||
}
|
||||
}
|
||||
|
||||
template<class AddrTy, bool TargetLittleEndian = true>
|
||||
class ElfPlatform : public Platform {
|
||||
public:
|
||||
|
||||
typedef ElfTypes<AddrTy> Elf;
|
||||
static const unsigned Class = Elf::BytesPerWord / 4;
|
||||
|
||||
struct FileHeader {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
typename Elf::Half e_type;
|
||||
typename Elf::Half e_machine;
|
||||
typename Elf::Word e_version;
|
||||
typename Elf::Addr e_entry;
|
||||
typename Elf::Off e_phoff;
|
||||
typename Elf::Off e_shoff;
|
||||
typename Elf::Word e_flags;
|
||||
typename Elf::Half e_ehsize;
|
||||
typename Elf::Half e_phentsize;
|
||||
typename Elf::Half e_phnum;
|
||||
typename Elf::Half e_shentsize;
|
||||
typename Elf::Half e_shnum;
|
||||
typename Elf::Half e_shstrndx;
|
||||
};
|
||||
|
||||
struct SectionHeader {
|
||||
typename Elf::Word sh_name;
|
||||
typename Elf::Word sh_type;
|
||||
typename Elf::XFlags sh_flags;
|
||||
typename Elf::Addr sh_addr;
|
||||
typename Elf::Off sh_offset;
|
||||
typename Elf::Off sh_size;
|
||||
typename Elf::Word sh_link;
|
||||
typename Elf::Word sh_info;
|
||||
typename Elf::Addr sh_addralign;
|
||||
typename Elf::Off sh_entsize;
|
||||
};
|
||||
|
||||
typedef Symbol_Ty<AddrTy> Symbol;
|
||||
|
||||
static const unsigned Encoding = TargetLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
|
||||
|
||||
const unsigned machine;
|
||||
|
||||
ElfPlatform(PlatformInfo::Architecture arch):
|
||||
Platform(PlatformInfo(PlatformInfo::Linux, arch)),
|
||||
machine(getElfPlatform(arch)) {}
|
||||
|
||||
class FileWriter {
|
||||
public:
|
||||
unsigned sectionCount;
|
||||
unsigned sectionStringTableSectionNumber;
|
||||
|
||||
AddrTy dataOffset;
|
||||
|
||||
FileHeader header;
|
||||
StringTable strings;
|
||||
|
||||
FileWriter(unsigned machine):
|
||||
sectionCount(0),
|
||||
dataOffset(sizeof(FileHeader))
|
||||
{
|
||||
memset(&header, 0, sizeof(FileHeader));
|
||||
header.e_ident[EI_MAG0] = V1(ELFMAG0);
|
||||
header.e_ident[EI_MAG1] = V1(ELFMAG1);
|
||||
header.e_ident[EI_MAG2] = V1(ELFMAG2);
|
||||
header.e_ident[EI_MAG3] = V1(ELFMAG3);
|
||||
header.e_ident[EI_CLASS] = V1(Class);
|
||||
header.e_ident[EI_DATA] = V1(Encoding);
|
||||
header.e_ident[EI_VERSION] = V1(EV_CURRENT);
|
||||
header.e_ident[EI_OSABI] = V1(OSABI);
|
||||
header.e_ident[EI_ABIVERSION] = V1(0);
|
||||
header.e_type = V2(ET_REL);
|
||||
header.e_machine = V2(machine);
|
||||
header.e_version = V4(EV_CURRENT);
|
||||
header.e_entry = VANY(static_cast<AddrTy>(0));
|
||||
header.e_phoff = VANY(static_cast<AddrTy>(0));
|
||||
header.e_shoff = VANY(static_cast<AddrTy>(sizeof(FileHeader)));
|
||||
header.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0);
|
||||
header.e_ehsize = V2(sizeof(FileHeader));
|
||||
header.e_phentsize = V2(0);
|
||||
header.e_phnum = V2(0);
|
||||
header.e_shentsize = V2(sizeof(SectionHeader));
|
||||
}
|
||||
|
||||
void writeHeader(OutputStream* out) {
|
||||
header.e_shnum = V2(sectionCount);
|
||||
header.e_shstrndx = V2(sectionStringTableSectionNumber);
|
||||
out->writeChunk(&header, sizeof(FileHeader));
|
||||
}
|
||||
};
|
||||
|
||||
class SectionWriter {
|
||||
public:
|
||||
FileWriter& file;
|
||||
String name;
|
||||
SectionHeader header;
|
||||
const size_t* dataSize;
|
||||
const uint8_t* const* data;
|
||||
|
||||
SectionWriter(FileWriter& file):
|
||||
file(file),
|
||||
name(""),
|
||||
data(0),
|
||||
dataSize(0)
|
||||
{
|
||||
memset(&header, 0, sizeof(SectionHeader));
|
||||
file.sectionCount++;
|
||||
file.dataOffset += sizeof(SectionHeader);
|
||||
size_t nameOffset = file.strings.add(name);
|
||||
header.sh_name = V4(nameOffset);
|
||||
}
|
||||
|
||||
SectionWriter(
|
||||
FileWriter& file,
|
||||
const char* chname,
|
||||
unsigned type,
|
||||
AddrTy flags,
|
||||
unsigned alignment,
|
||||
AddrTy addr,
|
||||
const uint8_t* const* data,
|
||||
size_t* dataSize,
|
||||
size_t entsize = 0,
|
||||
unsigned link = 0):
|
||||
|
||||
file(file),
|
||||
name(chname),
|
||||
data(data),
|
||||
dataSize(dataSize)
|
||||
{
|
||||
if(strcmp(chname, ".shstrtab") == 0) {
|
||||
file.sectionStringTableSectionNumber = file.sectionCount;
|
||||
}
|
||||
file.sectionCount++;
|
||||
file.dataOffset += sizeof(SectionHeader);
|
||||
size_t nameOffset = file.strings.add(name);
|
||||
|
||||
header.sh_name = V4(nameOffset);
|
||||
header.sh_type = V4(type);
|
||||
header.sh_flags = VANY(flags);
|
||||
header.sh_addr = VANY(addr);
|
||||
// header.sh_offset = VANY(static_cast<AddrTy>(bodySectionOffset));
|
||||
// header.sh_size = VANY(static_cast<AddrTy>(*dataSize));
|
||||
header.sh_link = V4(link);
|
||||
header.sh_info = V4(0);
|
||||
header.sh_addralign = VANY(static_cast<AddrTy>(alignment));
|
||||
header.sh_entsize = VANY(static_cast<AddrTy>(entsize));
|
||||
}
|
||||
|
||||
void writeHeader(OutputStream* out) {
|
||||
if(dataSize) {
|
||||
header.sh_offset = VANY(file.dataOffset);
|
||||
header.sh_size = VANY(static_cast<AddrTy>(*dataSize));
|
||||
file.dataOffset += *dataSize;
|
||||
}
|
||||
|
||||
out->writeChunk(&header, sizeof(SectionHeader));
|
||||
}
|
||||
|
||||
void writeData(OutputStream* out) {
|
||||
if(data) {
|
||||
out->writeChunk(*data, *dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
|
||||
|
||||
unsigned sectionFlags;
|
||||
const char* sectionName = getSectionName(accessFlags, sectionFlags);
|
||||
|
||||
StringTable symbolStringTable;
|
||||
Buffer symbolTable;
|
||||
|
||||
FileWriter file(machine);
|
||||
|
||||
const int bodySectionNumber = 1;
|
||||
const int stringTableSectionNumber = 3;
|
||||
|
||||
SectionWriter sections[] = {
|
||||
SectionWriter(file), // null section
|
||||
SectionWriter(file, sectionName, SHT_PROGBITS, sectionFlags, alignment, 0, &data.items, &data.count), // body section
|
||||
SectionWriter(file, ".shstrtab", SHT_STRTAB, 0, 1, 0, &file.strings.data, &file.strings.length),
|
||||
SectionWriter(file, ".strtab", SHT_STRTAB, 0, 1, 0, &symbolStringTable.data, &symbolStringTable.length),
|
||||
SectionWriter(file, ".symtab", SHT_SYMTAB, 0, 8, 0, &symbolTable.data, &symbolTable.length, sizeof(Symbol), stringTableSectionNumber)
|
||||
};
|
||||
|
||||
// for some reason, string tables require a null first element...
|
||||
symbolStringTable.add("");
|
||||
|
||||
for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) {
|
||||
size_t nameOffset = symbolStringTable.add(sym->name);
|
||||
|
||||
Symbol symbolStruct;
|
||||
symbolStruct.st_name = V4(nameOffset);
|
||||
symbolStruct.st_value = VANY(static_cast<AddrTy>(sym->addr));
|
||||
symbolStruct.st_size = VANY(static_cast<AddrTy>(0));
|
||||
symbolStruct.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE));
|
||||
symbolStruct.st_other = V1(STV_DEFAULT);
|
||||
symbolStruct.st_shndx = V2(bodySectionNumber);
|
||||
symbolTable.write(&symbolStruct, sizeof(Symbol));
|
||||
}
|
||||
|
||||
file.writeHeader(out);
|
||||
|
||||
for(int i = 0; i < file.sectionCount; i++) {
|
||||
sections[i].writeHeader(out);
|
||||
}
|
||||
|
||||
for(int i = 0; i < file.sectionCount; i++) {
|
||||
sections[i].writeData(out);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
ElfPlatform<uint32_t> elfx86Platform(PlatformInfo::x86);
|
||||
ElfPlatform<uint32_t> elfArmPlatform(PlatformInfo::Arm);
|
||||
ElfPlatform<uint32_t, false> elfPowerPCPlatform(PlatformInfo::PowerPC);
|
||||
ElfPlatform<uint64_t> elfx86_64Platform(PlatformInfo::x86_64);
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#define MACRO_MAKE_NAME(a, b, c) a##b##c
|
||||
#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c)
|
||||
|
||||
namespace binaryToObject {
|
||||
|
||||
bool
|
||||
MAKE_NAME(writeElf, BITS_PER_WORD, Object)
|
||||
(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture, unsigned alignment,
|
||||
bool writable, bool executable)
|
||||
{
|
||||
int machine;
|
||||
int encoding;
|
||||
if (strcmp(architecture, "x86_64") == 0) {
|
||||
machine = EM_X86_64;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (strcmp(architecture, "i386") == 0) {
|
||||
machine = EM_386;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (strcmp(architecture, "arm") == 0) {
|
||||
machine = EM_ARM;
|
||||
encoding = ELFDATA2LSB;
|
||||
} else if (strcmp(architecture, "powerpc") == 0) {
|
||||
machine = EM_PPC;
|
||||
encoding = ELFDATA2MSB;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %s\n", architecture);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* sectionName;
|
||||
unsigned sectionFlags = SHF_ALLOC;
|
||||
if (writable) {
|
||||
if (executable) {
|
||||
sectionName = ".rwx";
|
||||
sectionFlags |= SHF_WRITE | SHF_EXECINSTR;
|
||||
} else {
|
||||
sectionName = ".data";
|
||||
sectionFlags |= SHF_WRITE;
|
||||
}
|
||||
} else if (executable) {
|
||||
sectionName = ".text";
|
||||
sectionFlags |= SHF_EXECINSTR;
|
||||
} else {
|
||||
sectionName = ".rodata";
|
||||
}
|
||||
|
||||
writeObject(data, size, out, startName, endName, sectionName, sectionFlags,
|
||||
alignment, machine, encoding);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace binaryToObject
|
||||
|
@ -1,38 +1,81 @@
|
||||
#ifndef ENDIANNESS_H
|
||||
#define ENDIANNESS_H
|
||||
/* Copyright (c) 2008-2011, Avian Contributors
|
||||
|
||||
#define V1(v) (v)
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
#ifdef OPPOSITE_ENDIAN
|
||||
# define V2(v) \
|
||||
((((v) >> 8) & 0xFF) | \
|
||||
(((v) << 8)))
|
||||
# define V4(v) \
|
||||
((((v) >> 24) & 0x000000FF) | \
|
||||
(((v) >> 8) & 0x0000FF00) | \
|
||||
(((v) << 8) & 0x00FF0000) | \
|
||||
(((v) << 24)))
|
||||
# define V8(v) \
|
||||
(((static_cast<uint64_t>(v) >> 56) & UINT64_C(0x00000000000000FF)) | \
|
||||
((static_cast<uint64_t>(v) >> 40) & UINT64_C(0x000000000000FF00)) | \
|
||||
((static_cast<uint64_t>(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \
|
||||
((static_cast<uint64_t>(v) >> 8) & UINT64_C(0x00000000FF000000)) | \
|
||||
((static_cast<uint64_t>(v) << 8) & UINT64_C(0x000000FF00000000)) | \
|
||||
((static_cast<uint64_t>(v) << 24) & UINT64_C(0x0000FF0000000000)) | \
|
||||
((static_cast<uint64_t>(v) << 40) & UINT64_C(0x00FF000000000000)) | \
|
||||
((static_cast<uint64_t>(v) << 56)))
|
||||
#else
|
||||
# define V2(v) (v)
|
||||
# define V4(v) (v)
|
||||
# define V8(v) (v)
|
||||
#endif
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#if (BITS_PER_WORD == 64)
|
||||
# define VW(v) V8(v)
|
||||
#elif (BITS_PER_WORD == 32)
|
||||
# define VW(v) V4(v)
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
#ifndef AVIAN_ENDIANNESS_H
|
||||
#define AVIAN_ENDIANNESS_H
|
||||
|
||||
#endif//ENDIANNESS_H
|
||||
namespace avian {
|
||||
|
||||
namespace endian {
|
||||
|
||||
static union {
|
||||
uint32_t i;
|
||||
char c[4];
|
||||
} _DetectEndianness = {1};
|
||||
|
||||
const bool LittleEndian = _DetectEndianness.c[0] == 1;
|
||||
|
||||
template<bool TargetLittleEndian>
|
||||
class Endianness {
|
||||
public:
|
||||
static inline uint8_t v1(uint8_t v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline uint16_t v2(uint16_t v) {
|
||||
if(LittleEndian == TargetLittleEndian) {
|
||||
return v;
|
||||
} else {
|
||||
return ((v >> 8) & 0xFF) | (v << 8);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t v4(uint32_t v) {
|
||||
if(LittleEndian == TargetLittleEndian) {
|
||||
return v;
|
||||
} else {
|
||||
return
|
||||
((v >> 24) & 0x000000FF) |
|
||||
((v >> 8) & 0x0000FF00) |
|
||||
((v << 8) & 0x00FF0000) |
|
||||
((v << 24));
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t vAny(uint32_t v) {
|
||||
return v4(v);
|
||||
}
|
||||
|
||||
static inline uint64_t v8(uint64_t v) {
|
||||
if(LittleEndian == TargetLittleEndian) {
|
||||
return v;
|
||||
} else {
|
||||
return
|
||||
((static_cast<uint64_t>(v) >> 56) & (static_cast<uint64_t>(0xff) << 0)) |
|
||||
((static_cast<uint64_t>(v) >> 40) & (static_cast<uint64_t>(0xff) << 8)) |
|
||||
((static_cast<uint64_t>(v) >> 24) & (static_cast<uint64_t>(0xff) << 16)) |
|
||||
((static_cast<uint64_t>(v) >> 8) & (static_cast<uint64_t>(0xff) << 24)) |
|
||||
((static_cast<uint64_t>(v) << 8) & (static_cast<uint64_t>(0xff) << 32)) |
|
||||
((static_cast<uint64_t>(v) << 24) & (static_cast<uint64_t>(0xff) << 40)) |
|
||||
((static_cast<uint64_t>(v) << 40) & (static_cast<uint64_t>(0xff) << 48)) |
|
||||
((static_cast<uint64_t>(v) << 56));
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t vAny(uint64_t v) {
|
||||
return v8(v);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace endian
|
||||
|
||||
} // namespace avian
|
||||
|
||||
#endif // AVIAN_ENDIANNESS_H
|
||||
|
@ -8,19 +8,19 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "endianness.h"
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
#define MH_MAGIC_64 0xfeedfacf
|
||||
#define MH_MAGIC 0xfeedface
|
||||
|
||||
#define MH_OBJECT 1
|
||||
|
||||
#define LC_SEGMENT_64 0x19
|
||||
#define LC_SEGMENT 1
|
||||
#define LC_SYMTAB 2
|
||||
|
||||
#define S_REGULAR 0
|
||||
@ -40,142 +40,21 @@
|
||||
#define CPU_SUBTYPE_POWERPC_ALL 0
|
||||
#define CPU_SUBTYPE_ARM_V7 9
|
||||
|
||||
#if (BITS_PER_WORD == 64)
|
||||
# define Magic MH_MAGIC_64
|
||||
# define Segment LC_SEGMENT_64
|
||||
# define FileHeader mach_header_64
|
||||
# define SegmentCommand segment_command_64
|
||||
# define Section section_64
|
||||
# define NList struct nlist_64
|
||||
#elif (BITS_PER_WORD == 32)
|
||||
# define Magic MH_MAGIC
|
||||
# define Segment LC_SEGMENT
|
||||
# define FileHeader mach_header
|
||||
# define SegmentCommand segment_command
|
||||
# define Section section
|
||||
# define NList struct nlist
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace avian::tools;
|
||||
|
||||
typedef int cpu_type_t;
|
||||
typedef int cpu_subtype_t;
|
||||
typedef int vm_prot_t;
|
||||
|
||||
struct mach_header_64 {
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
uint32_t flags;
|
||||
uint32_t reserved;
|
||||
};
|
||||
using avian::endian::Endianness;
|
||||
|
||||
struct segment_command_64 {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
char segname[16];
|
||||
uint64_t vmaddr;
|
||||
uint64_t vmsize;
|
||||
uint64_t fileoff;
|
||||
uint64_t filesize;
|
||||
vm_prot_t maxprot;
|
||||
vm_prot_t initprot;
|
||||
uint32_t nsects;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct section_64 {
|
||||
char sectname[16];
|
||||
char segname[16];
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
uint32_t offset;
|
||||
uint32_t align;
|
||||
uint32_t reloff;
|
||||
uint32_t nreloc;
|
||||
uint32_t flags;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
uint32_t reserved3;
|
||||
};
|
||||
|
||||
struct nlist_64 {
|
||||
union {
|
||||
uint32_t n_strx;
|
||||
} n_un;
|
||||
uint8_t n_type;
|
||||
uint8_t n_sect;
|
||||
uint16_t n_desc;
|
||||
uint64_t n_value;
|
||||
};
|
||||
|
||||
struct mach_header {
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct segment_command {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
char segname[16];
|
||||
uint32_t vmaddr;
|
||||
uint32_t vmsize;
|
||||
uint32_t fileoff;
|
||||
uint32_t filesize;
|
||||
vm_prot_t maxprot;
|
||||
vm_prot_t initprot;
|
||||
uint32_t nsects;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct section {
|
||||
char sectname[16];
|
||||
char segname[16];
|
||||
uint32_t addr;
|
||||
uint32_t size;
|
||||
uint32_t offset;
|
||||
uint32_t align;
|
||||
uint32_t reloff;
|
||||
uint32_t nreloc;
|
||||
uint32_t flags;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
};
|
||||
|
||||
struct symtab_command {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
uint32_t symoff;
|
||||
uint32_t nsyms;
|
||||
uint32_t stroff;
|
||||
uint32_t strsize;
|
||||
};
|
||||
|
||||
struct nlist {
|
||||
union {
|
||||
int32_t n_strx;
|
||||
} n_un;
|
||||
uint8_t n_type;
|
||||
uint8_t n_sect;
|
||||
int16_t n_desc;
|
||||
uint32_t n_value;
|
||||
};
|
||||
|
||||
inline unsigned
|
||||
pad(unsigned n)
|
||||
{
|
||||
return (n + ((BITS_PER_WORD / 8) - 1)) & ~((BITS_PER_WORD / 8) - 1);
|
||||
}
|
||||
#define V1 Endianness<TargetLittleEndian>::v1
|
||||
#define V2 Endianness<TargetLittleEndian>::v2
|
||||
#define V3 Endianness<TargetLittleEndian>::v3
|
||||
#define V4 Endianness<TargetLittleEndian>::v4
|
||||
#define VANY Endianness<TargetLittleEndian>::vAny
|
||||
|
||||
inline unsigned
|
||||
log(unsigned n)
|
||||
@ -185,177 +64,233 @@ log(unsigned n)
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* segmentName, const char* sectionName,
|
||||
unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType)
|
||||
{
|
||||
unsigned startNameLength = strlen(startName) + 1;
|
||||
unsigned endNameLength = strlen(endName) + 1;
|
||||
template<class AddrTy, bool TargetLittleEndian = true>
|
||||
class MachOPlatform : public Platform {
|
||||
public:
|
||||
|
||||
FileHeader header = {
|
||||
V4(Magic), // magic
|
||||
V4(cpuType),
|
||||
V4(cpuSubType),
|
||||
V4(MH_OBJECT), // filetype,
|
||||
V4(2), // ncmds
|
||||
V4(sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // sizeofcmds
|
||||
V4(0) // flags
|
||||
struct FileHeader {
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
|
||||
union {
|
||||
uint32_t flags;
|
||||
AddrTy flagsAndMaybeReserved;
|
||||
};
|
||||
};
|
||||
|
||||
SegmentCommand segment = {
|
||||
V4(Segment), // cmd
|
||||
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
|
||||
"", // segname
|
||||
VW(0), // vmaddr
|
||||
VW(pad(size)), // vmsize
|
||||
VW(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // fileoff
|
||||
VW(pad(size)), // filesize
|
||||
V4(7), // maxprot
|
||||
V4(7), // initprot
|
||||
V4(1), // nsects
|
||||
V4(0) // flags
|
||||
|
||||
struct SegmentCommand {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
char segname[16];
|
||||
AddrTy vmaddr;
|
||||
AddrTy vmsize;
|
||||
AddrTy fileoff;
|
||||
AddrTy filesize;
|
||||
vm_prot_t maxprot;
|
||||
vm_prot_t initprot;
|
||||
uint32_t nsects;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
||||
|
||||
Section sect = {
|
||||
"", // sectname
|
||||
"", // segname
|
||||
VW(0), // addr
|
||||
VW(pad(size)), // size
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)), // offset
|
||||
V4(log(alignment)), // align
|
||||
V4(0), // reloff
|
||||
V4(0), // nreloc
|
||||
V4(S_REGULAR), // flags
|
||||
V4(0), // reserved1
|
||||
V4(0), // reserved2
|
||||
struct Section {
|
||||
char sectname[16];
|
||||
char segname[16];
|
||||
AddrTy addr;
|
||||
AddrTy size;
|
||||
uint32_t offset;
|
||||
uint32_t align;
|
||||
uint32_t reloff;
|
||||
uint32_t nreloc;
|
||||
uint32_t flags;
|
||||
uint32_t reserved1;
|
||||
AddrTy reserved2AndMaybe3;
|
||||
};
|
||||
|
||||
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
||||
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
||||
|
||||
symtab_command symbolTable = {
|
||||
V4(LC_SYMTAB), // cmd
|
||||
V4(sizeof(symtab_command)), // cmdsize
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size)), // symoff
|
||||
V4(2), // nsyms
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(symtab_command)
|
||||
+ pad(size)
|
||||
+ (sizeof(NList) * 2)), // stroff
|
||||
V4(1 + startNameLength + endNameLength), // strsize
|
||||
struct NList {
|
||||
union {
|
||||
uint32_t n_strx;
|
||||
} n_un;
|
||||
uint8_t n_type;
|
||||
uint8_t n_sect;
|
||||
uint16_t n_desc;
|
||||
AddrTy n_value;
|
||||
};
|
||||
|
||||
NList symbolList[] = {
|
||||
{
|
||||
V4(1), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VW(0) // n_value
|
||||
},
|
||||
{
|
||||
V4(1 + startNameLength), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VW(size) // n_value
|
||||
struct SymtabCommand {
|
||||
uint32_t cmd;
|
||||
uint32_t cmdsize;
|
||||
uint32_t symoff;
|
||||
uint32_t nsyms;
|
||||
uint32_t stroff;
|
||||
uint32_t strsize;
|
||||
};
|
||||
|
||||
static const unsigned BytesPerWord = sizeof(AddrTy);
|
||||
static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1;
|
||||
static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface;
|
||||
|
||||
static inline unsigned
|
||||
pad(unsigned n)
|
||||
{
|
||||
return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1);
|
||||
}
|
||||
|
||||
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
|
||||
cpu_type_t cpuType;
|
||||
cpu_subtype_t cpuSubType;
|
||||
switch(info.arch) {
|
||||
case PlatformInfo::x86_64:
|
||||
cpuType = CPU_TYPE_X86_64;
|
||||
cpuSubType = CPU_SUBTYPE_X86_64_ALL;
|
||||
break;
|
||||
case PlatformInfo::x86:
|
||||
cpuType = CPU_TYPE_I386;
|
||||
cpuSubType = CPU_SUBTYPE_I386_ALL;
|
||||
break;
|
||||
case PlatformInfo::PowerPC:
|
||||
cpuType = CPU_TYPE_POWERPC;
|
||||
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
|
||||
break;
|
||||
case PlatformInfo::Arm:
|
||||
cpuType = CPU_TYPE_ARM;
|
||||
cpuSubType = CPU_SUBTYPE_ARM_V7;
|
||||
break;
|
||||
default:
|
||||
// should never happen (see MachOPlatform declarations at bottom)
|
||||
fprintf(stderr, "unsupported architecture: %d\n", info.arch);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
fwrite(&header, 1, sizeof(header), out);
|
||||
fwrite(&segment, 1, sizeof(segment), out);
|
||||
fwrite(§, 1, sizeof(sect), out);
|
||||
fwrite(&symbolTable, 1, sizeof(symbolTable), out);
|
||||
const char* segmentName;
|
||||
const char* sectionName;
|
||||
if (accessFlags & Writable) {
|
||||
if (accessFlags & Executable) {
|
||||
segmentName = "__RWX";
|
||||
sectionName = "__rwx";
|
||||
} else {
|
||||
segmentName = "__DATA";
|
||||
sectionName = "__data";
|
||||
}
|
||||
} else {
|
||||
segmentName = "__TEXT";
|
||||
sectionName = "__text";
|
||||
}
|
||||
|
||||
fwrite(data, 1, size, out);
|
||||
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out);
|
||||
FileHeader header = {
|
||||
V4(Magic), // magic
|
||||
V4(cpuType),
|
||||
V4(cpuSubType),
|
||||
V4(MH_OBJECT), // filetype,
|
||||
V4(2), // ncmds
|
||||
V4(sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)), // sizeofcmds
|
||||
V4(0) // flags
|
||||
};
|
||||
|
||||
fwrite(&symbolList, 1, sizeof(symbolList), out);
|
||||
AddrTy finalSize = pad(data.count);
|
||||
|
||||
fputc(0, out);
|
||||
fwrite(startName, 1, startNameLength, out);
|
||||
fwrite(endName, 1, endNameLength, out);
|
||||
}
|
||||
SegmentCommand segment = {
|
||||
V4(Segment), // cmd
|
||||
V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize
|
||||
"", // segname
|
||||
VANY(static_cast<AddrTy>(0)), // vmaddr
|
||||
VANY(static_cast<AddrTy>(finalSize)), // vmsize
|
||||
VANY(static_cast<AddrTy>(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand))), // fileoff
|
||||
VANY(static_cast<AddrTy>(finalSize)), // filesize
|
||||
V4(7), // maxprot
|
||||
V4(7), // initprot
|
||||
V4(1), // nsects
|
||||
V4(0) // flags
|
||||
};
|
||||
|
||||
strncpy(segment.segname, segmentName, sizeof(segment.segname));
|
||||
|
||||
Section sect = {
|
||||
"", // sectname
|
||||
"", // segname
|
||||
VANY(static_cast<AddrTy>(0)), // addr
|
||||
VANY(static_cast<AddrTy>(finalSize)), // size
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)), // offset
|
||||
V4(log(alignment)), // align
|
||||
V4(0), // reloff
|
||||
V4(0), // nreloc
|
||||
V4(S_REGULAR), // flags
|
||||
V4(0), // reserved1
|
||||
V4(0), // reserved2
|
||||
};
|
||||
|
||||
strncpy(sect.segname, segmentName, sizeof(sect.segname));
|
||||
strncpy(sect.sectname, sectionName, sizeof(sect.sectname));
|
||||
|
||||
StringTable strings;
|
||||
strings.add("");
|
||||
Buffer symbolList;
|
||||
|
||||
for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) {
|
||||
unsigned offset = strings.length;
|
||||
strings.write("_", 1);
|
||||
strings.add(sym->name);
|
||||
NList symbol = {
|
||||
V4(offset), // n_un
|
||||
V1(N_SECT | N_EXT), // n_type
|
||||
V1(1), // n_sect
|
||||
V2(0), // n_desc
|
||||
VANY(static_cast<AddrTy>(sym->addr)) // n_value
|
||||
};
|
||||
symbolList.write(&symbol, sizeof(NList));
|
||||
}
|
||||
|
||||
SymtabCommand symbolTable = {
|
||||
V4(LC_SYMTAB), // cmd
|
||||
V4(sizeof(SymtabCommand)), // cmdsize
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)
|
||||
+ finalSize), // symoff
|
||||
V4(symbols.count), // nsyms
|
||||
V4(sizeof(FileHeader)
|
||||
+ sizeof(SegmentCommand)
|
||||
+ sizeof(Section)
|
||||
+ sizeof(SymtabCommand)
|
||||
+ finalSize
|
||||
+ (sizeof(NList) * symbols.count)), // stroff
|
||||
V4(strings.length), // strsize
|
||||
};
|
||||
|
||||
out->writeChunk(&header, sizeof(header));
|
||||
out->writeChunk(&segment, sizeof(segment));
|
||||
out->writeChunk(§, sizeof(sect));
|
||||
out->writeChunk(&symbolTable, sizeof(symbolTable));
|
||||
|
||||
out->writeChunk(data.items, data.count);
|
||||
out->writeRepeat(0, finalSize - data.count);
|
||||
|
||||
out->writeChunk(symbolList.data, symbolList.length);
|
||||
|
||||
out->writeChunk(strings.data, strings.length);
|
||||
}
|
||||
|
||||
MachOPlatform(PlatformInfo::Architecture arch):
|
||||
Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {}
|
||||
|
||||
};
|
||||
|
||||
MachOPlatform<uint32_t> darwinx86Platform(PlatformInfo::x86);
|
||||
MachOPlatform<uint32_t> darwinArmPlatform(PlatformInfo::Arm);
|
||||
MachOPlatform<uint32_t, false> darwinPowerPCPlatform(PlatformInfo::PowerPC);
|
||||
MachOPlatform<uint64_t> darwinx86_64Platform(PlatformInfo::x86_64);
|
||||
|
||||
} // namespace
|
||||
|
||||
#define MACRO_MAKE_NAME(a, b, c) a##b##c
|
||||
#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c)
|
||||
|
||||
namespace binaryToObject {
|
||||
|
||||
bool
|
||||
MAKE_NAME(writeMachO, BITS_PER_WORD, Object)
|
||||
(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture, unsigned alignment,
|
||||
bool writable, bool executable)
|
||||
{
|
||||
cpu_type_t cpuType;
|
||||
cpu_subtype_t cpuSubType;
|
||||
if (strcmp(architecture, "x86_64") == 0) {
|
||||
cpuType = CPU_TYPE_X86_64;
|
||||
cpuSubType = CPU_SUBTYPE_X86_64_ALL;
|
||||
} else if (strcmp(architecture, "i386") == 0) {
|
||||
cpuType = CPU_TYPE_I386;
|
||||
cpuSubType = CPU_SUBTYPE_I386_ALL;
|
||||
} else if (strcmp(architecture, "powerpc") == 0) {
|
||||
cpuType = CPU_TYPE_POWERPC;
|
||||
cpuSubType = CPU_SUBTYPE_POWERPC_ALL;
|
||||
} else if (strcmp(architecture, "arm") == 0) {
|
||||
cpuType = CPU_TYPE_ARM;
|
||||
cpuSubType = CPU_SUBTYPE_ARM_V7;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %s\n", architecture);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* segmentName;
|
||||
const char* sectionName;
|
||||
if (writable) {
|
||||
if (executable) {
|
||||
segmentName = "__RWX";
|
||||
sectionName = "__rwx";
|
||||
} else {
|
||||
segmentName = "__DATA";
|
||||
sectionName = "__data";
|
||||
}
|
||||
} else {
|
||||
segmentName = "__TEXT";
|
||||
sectionName = "__text";
|
||||
}
|
||||
|
||||
unsigned startNameLength = strlen(startName);
|
||||
char myStartName[startNameLength + 2];
|
||||
myStartName[0] = '_';
|
||||
memcpy(myStartName + 1, startName, startNameLength + 1);
|
||||
|
||||
unsigned endNameLength = strlen(endName);
|
||||
char myEndName[endNameLength + 2];
|
||||
myEndName[0] = '_';
|
||||
memcpy(myEndName + 1, endName, endNameLength + 1);
|
||||
|
||||
writeObject(data, size, out, myStartName, myEndName, segmentName,
|
||||
sectionName, alignment, cpuType, cpuSubType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace binaryToObject
|
||||
|
@ -8,111 +8,60 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sys/stat.h"
|
||||
#include <sys/stat.h>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include "sys/mman.h"
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include "fcntl.h"
|
||||
#include "unistd.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace binaryToObject {
|
||||
#include "tools.h"
|
||||
|
||||
bool
|
||||
writeElf64Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
extern "C"
|
||||
void __cxa_pure_virtual() {
|
||||
abort();
|
||||
}
|
||||
|
||||
bool
|
||||
writeElf32Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
void* operator new(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
bool
|
||||
writeMachO64Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
|
||||
bool
|
||||
writeMachO32Object(uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable);
|
||||
|
||||
bool
|
||||
writePEObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture,
|
||||
unsigned alignment, bool writable, bool executable);
|
||||
|
||||
} // namespace binaryToObject
|
||||
void operator delete(void* mem) { abort(); }
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace avian::tools;
|
||||
|
||||
bool
|
||||
writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* platform,
|
||||
writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName,
|
||||
const char* endName, const char* os,
|
||||
const char* architecture, unsigned alignment, bool writable,
|
||||
bool executable)
|
||||
{
|
||||
using namespace binaryToObject;
|
||||
Platform* platform = Platform::getPlatform(PlatformInfo(os, architecture));
|
||||
|
||||
bool found = false;
|
||||
bool success = false;
|
||||
if (strcmp("linux", platform) == 0) {
|
||||
if (strcmp("x86_64", architecture) == 0) {
|
||||
found = true;
|
||||
success = writeElf64Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
} else if (strcmp("i386", architecture) == 0
|
||||
or strcmp("arm", architecture) == 0
|
||||
or strcmp("powerpc", architecture) == 0)
|
||||
{
|
||||
found = true;
|
||||
success = writeElf32Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
}
|
||||
} else if (strcmp("darwin", platform) == 0) {
|
||||
if (strcmp("x86_64", architecture) == 0) {
|
||||
found = true;
|
||||
success = writeMachO64Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
} else if (strcmp("i386", architecture) == 0
|
||||
or strcmp("powerpc", architecture) == 0
|
||||
or strcmp("arm", architecture) == 0)
|
||||
{
|
||||
found = true;
|
||||
success = writeMachO32Object
|
||||
(data, size, out, startName, endName, architecture, alignment,
|
||||
writable, executable);
|
||||
}
|
||||
} else if (strcmp("windows", platform) == 0
|
||||
and ((strcmp("x86_64", architecture) == 0
|
||||
or strcmp("i386", architecture) == 0)))
|
||||
{
|
||||
found = true;
|
||||
success = writePEObject
|
||||
(data, size, out, startName, endName, architecture, alignment, writable,
|
||||
executable);
|
||||
}
|
||||
|
||||
if (not found) {
|
||||
fprintf(stderr, "unsupported platform: %s/%s\n", platform, architecture);
|
||||
if(!platform) {
|
||||
fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture);
|
||||
return false;
|
||||
}
|
||||
|
||||
return success;
|
||||
SymbolInfo symbols[2];
|
||||
symbols[0].name = startName;
|
||||
symbols[0].addr = 0;
|
||||
symbols[1].name = endName;
|
||||
symbols[1].addr = size;
|
||||
|
||||
unsigned accessFlags = (writable ? Platform::Writable : 0) | (executable ? Platform::Executable : 0);
|
||||
|
||||
return platform->writeObject(out, Slice<SymbolInfo>(symbols, 2), Slice<const uint8_t>(data, size), accessFlags, alignment);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -191,13 +140,11 @@ main(int argc, const char** argv)
|
||||
bool success = false;
|
||||
|
||||
if (data) {
|
||||
FILE* out = fopen(argv[2], "wb");
|
||||
if (out) {
|
||||
FileOutputStream out(argv[2]);
|
||||
if (out.isValid()) {
|
||||
success = writeObject
|
||||
(data, size, out, argv[3], argv[4], argv[5], argv[6], alignment,
|
||||
(data, size, &out, argv[3], argv[4], argv[5], argv[6], alignment,
|
||||
writable, executable);
|
||||
|
||||
fclose(out);
|
||||
} else {
|
||||
fprintf(stderr, "unable to open %s\n", argv[2]);
|
||||
}
|
||||
|
@ -8,16 +8,21 @@
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
|
||||
#define IMAGE_FILE_RELOCS_STRIPPED 1
|
||||
#define IMAGE_FILE_LINE_NUMS_STRIPPED 4
|
||||
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_32BIT_MACHINE 256
|
||||
|
||||
#define IMAGE_SCN_ALIGN_1BYTES 0x100000
|
||||
@ -29,8 +34,6 @@
|
||||
#define IMAGE_SCN_MEM_WRITE 0x80000000
|
||||
#define IMAGE_SCN_CNT_CODE 32
|
||||
|
||||
namespace {
|
||||
|
||||
struct IMAGE_FILE_HEADER {
|
||||
uint16_t Machine;
|
||||
uint16_t NumberOfSections;
|
||||
@ -77,155 +80,202 @@ pad(unsigned n)
|
||||
return (n + (4 - 1)) & ~(4 - 1);
|
||||
}
|
||||
|
||||
void
|
||||
writeObject(const uint8_t* data, unsigned size, FILE* out,
|
||||
const char* startName, const char* endName,
|
||||
const char* sectionName, int machine, int machineMask,
|
||||
int sectionMask)
|
||||
{
|
||||
const unsigned sectionCount = 1;
|
||||
const unsigned symbolCount = 2;
|
||||
using namespace avian::tools;
|
||||
|
||||
const unsigned sectionNumber = 1;
|
||||
template<unsigned BytesPerWord>
|
||||
class WindowsPlatform : public Platform {
|
||||
public:
|
||||
|
||||
const unsigned startNameLength = strlen(startName) + 1;
|
||||
const unsigned endNameLength = strlen(endName) + 1;
|
||||
|
||||
const unsigned startNameOffset = 4;
|
||||
const unsigned endNameOffset = startNameOffset + startNameLength;
|
||||
class FileWriter {
|
||||
public:
|
||||
unsigned sectionCount;
|
||||
unsigned symbolCount;
|
||||
unsigned dataStart;
|
||||
unsigned dataOffset;
|
||||
|
||||
IMAGE_FILE_HEADER fileHeader = {
|
||||
machine, // Machine
|
||||
sectionCount, // NumberOfSections
|
||||
0, // TimeDateStamp
|
||||
sizeof(IMAGE_FILE_HEADER)
|
||||
+ sizeof(IMAGE_SECTION_HEADER)
|
||||
+ pad(size), // PointerToSymbolTable
|
||||
symbolCount, // NumberOfSymbols
|
||||
0, // SizeOfOptionalHeader
|
||||
IMAGE_FILE_RELOCS_STRIPPED
|
||||
| IMAGE_FILE_LINE_NUMS_STRIPPED
|
||||
| machineMask // Characteristics
|
||||
IMAGE_FILE_HEADER header;
|
||||
|
||||
StringTable strings;
|
||||
Buffer symbols;
|
||||
|
||||
FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount):
|
||||
sectionCount(0),
|
||||
symbolCount(symbolCount),
|
||||
dataStart(sizeof(IMAGE_FILE_HEADER)),
|
||||
dataOffset(0)
|
||||
{
|
||||
header.Machine = machine;
|
||||
// header.NumberOfSections = sectionCount;
|
||||
header.TimeDateStamp = 0;
|
||||
// header.PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER)
|
||||
// + sizeof(IMAGE_SECTION_HEADER)
|
||||
// + pad(size);
|
||||
// header.NumberOfSymbols = symbolCount;
|
||||
header.SizeOfOptionalHeader = 0;
|
||||
header.Characteristics = IMAGE_FILE_RELOCS_STRIPPED
|
||||
| IMAGE_FILE_LINE_NUMS_STRIPPED
|
||||
| machineMask;
|
||||
}
|
||||
|
||||
void writeHeader(OutputStream* out) {
|
||||
header.NumberOfSections = sectionCount;
|
||||
header.PointerToSymbolTable = dataStart + dataOffset;
|
||||
printf("symbol table start: 0x%x\n", header.PointerToSymbolTable);
|
||||
dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL));
|
||||
printf("string table start: 0x%x\n", dataStart + dataOffset);
|
||||
header.NumberOfSymbols = symbolCount;
|
||||
out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER));
|
||||
}
|
||||
|
||||
void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) {
|
||||
unsigned nameOffset = strings.add(name);
|
||||
IMAGE_SYMBOL symbol = {
|
||||
{ 0 }, // Name
|
||||
addr, // Value
|
||||
sectionNumber, // SectionNumber
|
||||
type, // Type
|
||||
storageClass, // StorageClass
|
||||
0, // NumberOfAuxSymbols
|
||||
};
|
||||
symbol.N.Name.Long = nameOffset+4;
|
||||
symbols.write(&symbol, sizeof(IMAGE_SYMBOL));
|
||||
}
|
||||
|
||||
void writeData(OutputStream* out) {
|
||||
out->writeChunk(symbols.data, symbols.length);
|
||||
uint32_t size = strings.length + 4;
|
||||
out->writeChunk(&size, 4);
|
||||
out->writeChunk(strings.data, strings.length);
|
||||
}
|
||||
};
|
||||
|
||||
IMAGE_SECTION_HEADER sectionHeader = {
|
||||
"", // Name
|
||||
0, // PhysicalAddress
|
||||
0, // VirtualAddress
|
||||
pad(size), // SizeOfRawData
|
||||
sizeof(IMAGE_FILE_HEADER)
|
||||
+ sizeof(IMAGE_SECTION_HEADER), // PointerToRawData
|
||||
0, // PointerToRelocations
|
||||
0, // PointerToLinenumbers
|
||||
0, // NumberOfRelocations
|
||||
0, // NumberOfLinenumbers
|
||||
sectionMask // Characteristics
|
||||
class SectionWriter {
|
||||
public:
|
||||
FileWriter& file;
|
||||
IMAGE_SECTION_HEADER header;
|
||||
size_t dataSize;
|
||||
size_t finalSize;
|
||||
const uint8_t* data;
|
||||
unsigned dataOffset;
|
||||
|
||||
SectionWriter(
|
||||
FileWriter& file,
|
||||
const char* name,
|
||||
unsigned sectionMask,
|
||||
const uint8_t* data,
|
||||
size_t dataSize):
|
||||
|
||||
file(file),
|
||||
data(data),
|
||||
dataSize(dataSize),
|
||||
finalSize(pad(dataSize))
|
||||
{
|
||||
file.sectionCount++;
|
||||
file.dataStart += sizeof(IMAGE_SECTION_HEADER);
|
||||
strcpy(reinterpret_cast<char*>(header.Name), name);
|
||||
header.Misc.VirtualSize = 0;
|
||||
header.SizeOfRawData = finalSize;
|
||||
// header.PointerToRawData = file.dataOffset;
|
||||
dataOffset = file.dataOffset;
|
||||
file.dataOffset += finalSize;
|
||||
header.PointerToRelocations = 0;
|
||||
header.PointerToLinenumbers = 0;
|
||||
header.NumberOfRelocations = 0;
|
||||
header.NumberOfLinenumbers = 0;
|
||||
header.Characteristics = sectionMask;
|
||||
}
|
||||
|
||||
void writeHeader(OutputStream* out) {
|
||||
header.PointerToRawData = dataOffset + file.dataStart;
|
||||
printf("section %s: data at 0x%x, ending at 0x%x\n", header.Name, header.PointerToRawData, header.PointerToRawData + header.SizeOfRawData);
|
||||
out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER));
|
||||
}
|
||||
|
||||
void writeData(OutputStream* out) {
|
||||
out->writeChunk(data, dataSize);
|
||||
out->writeRepeat(0, finalSize - dataSize);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
strncpy(reinterpret_cast<char*>(sectionHeader.Name), sectionName,
|
||||
sizeof(sectionHeader.Name));
|
||||
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) {
|
||||
|
||||
IMAGE_SYMBOL startSymbol = {
|
||||
{ 0 }, // Name
|
||||
0, // Value
|
||||
sectionNumber, // SectionNumber
|
||||
0, // Type
|
||||
2, // StorageClass
|
||||
0, // NumberOfAuxSymbols
|
||||
};
|
||||
startSymbol.N.Name.Long = startNameOffset;
|
||||
int machine;
|
||||
int machineMask;
|
||||
|
||||
IMAGE_SYMBOL endSymbol = {
|
||||
{ 0 }, // Name
|
||||
size, // Value
|
||||
sectionNumber, // SectionNumber
|
||||
0, // Type
|
||||
2, // StorageClass
|
||||
0, // NumberOfAuxSymbols
|
||||
};
|
||||
endSymbol.N.Name.Long = endNameOffset;
|
||||
if (BytesPerWord == 8) {
|
||||
machine = IMAGE_FILE_MACHINE_AMD64;
|
||||
machineMask = 0;
|
||||
} else { // if (BytesPerWord == 8)
|
||||
machine = IMAGE_FILE_MACHINE_I386;
|
||||
machineMask = IMAGE_FILE_32BIT_MACHINE;
|
||||
}
|
||||
|
||||
fwrite(&fileHeader, 1, sizeof(fileHeader), out);
|
||||
fwrite(§ionHeader, 1, sizeof(sectionHeader), out);
|
||||
int sectionMask;
|
||||
switch (alignment) {
|
||||
case 0:
|
||||
case 1:
|
||||
sectionMask = IMAGE_SCN_ALIGN_1BYTES;
|
||||
break;
|
||||
case 2:
|
||||
sectionMask = IMAGE_SCN_ALIGN_2BYTES;
|
||||
break;
|
||||
case 4:
|
||||
sectionMask = IMAGE_SCN_ALIGN_4BYTES;
|
||||
break;
|
||||
case 8:
|
||||
sectionMask = IMAGE_SCN_ALIGN_8BYTES;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unsupported alignment: %d\n", alignment);
|
||||
return false;
|
||||
}
|
||||
|
||||
fwrite(data, 1, size, out);
|
||||
for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out);
|
||||
sectionMask |= IMAGE_SCN_MEM_READ;
|
||||
|
||||
fwrite(&startSymbol, 1, sizeof(startSymbol), out);
|
||||
fwrite(&endSymbol, 1, sizeof(endSymbol), out);
|
||||
const char* sectionName;
|
||||
if (accessFlags & Platform::Writable) {
|
||||
if (accessFlags & Platform::Executable) {
|
||||
sectionName = ".rwx";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE
|
||||
| IMAGE_SCN_MEM_EXECUTE
|
||||
| IMAGE_SCN_CNT_CODE;
|
||||
} else {
|
||||
sectionName = ".data";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE;
|
||||
}
|
||||
} else {
|
||||
sectionName = ".text";
|
||||
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
|
||||
}
|
||||
|
||||
uint32_t symbolTableSize = endNameOffset + endNameLength;
|
||||
fwrite(&symbolTableSize, 1, 4, out);
|
||||
FileWriter file(machine, machineMask, symbols.count);
|
||||
|
||||
fwrite(startName, 1, startNameLength, out);
|
||||
fwrite(endName, 1, endNameLength, out);
|
||||
}
|
||||
SectionWriter section(file, sectionName, sectionMask, data.items, data.count);
|
||||
|
||||
file.writeHeader(out);
|
||||
|
||||
for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) {
|
||||
file.addSymbol(sym->name, sym->addr, 1, 0, 2);
|
||||
}
|
||||
|
||||
section.writeHeader(out);
|
||||
|
||||
section.writeData(out);
|
||||
|
||||
file.writeData(out);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
WindowsPlatform():
|
||||
Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {}
|
||||
};
|
||||
|
||||
WindowsPlatform<4> windows32Platform;
|
||||
WindowsPlatform<8> windows64Platform;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace binaryToObject {
|
||||
|
||||
bool
|
||||
writePEObject
|
||||
(uint8_t* data, unsigned size, FILE* out, const char* startName,
|
||||
const char* endName, const char* architecture, unsigned alignment,
|
||||
bool writable, bool executable)
|
||||
{
|
||||
int machine;
|
||||
int machineMask;
|
||||
if (strcmp(architecture, "x86_64") == 0) {
|
||||
machine = IMAGE_FILE_MACHINE_AMD64;
|
||||
machineMask = 0;
|
||||
} else if (strcmp(architecture, "i386") == 0) {
|
||||
machine = IMAGE_FILE_MACHINE_I386;
|
||||
machineMask = IMAGE_FILE_32BIT_MACHINE;
|
||||
} else {
|
||||
fprintf(stderr, "unsupported architecture: %s\n", architecture);
|
||||
return false;
|
||||
}
|
||||
|
||||
int sectionMask;
|
||||
switch (alignment) {
|
||||
case 0:
|
||||
case 1:
|
||||
sectionMask = IMAGE_SCN_ALIGN_1BYTES;
|
||||
break;
|
||||
case 2:
|
||||
sectionMask = IMAGE_SCN_ALIGN_2BYTES;
|
||||
break;
|
||||
case 4:
|
||||
sectionMask = IMAGE_SCN_ALIGN_4BYTES;
|
||||
break;
|
||||
case 8:
|
||||
sectionMask = IMAGE_SCN_ALIGN_8BYTES;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unsupported alignment: %d\n", alignment);
|
||||
return false;
|
||||
}
|
||||
|
||||
sectionMask |= IMAGE_SCN_MEM_READ;
|
||||
|
||||
const char* sectionName;
|
||||
if (writable) {
|
||||
if (executable) {
|
||||
sectionName = ".rwx";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE
|
||||
| IMAGE_SCN_MEM_EXECUTE
|
||||
| IMAGE_SCN_CNT_CODE;
|
||||
} else {
|
||||
sectionName = ".data";
|
||||
sectionMask |= IMAGE_SCN_MEM_WRITE;
|
||||
}
|
||||
} else {
|
||||
sectionName = ".text";
|
||||
sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
|
||||
}
|
||||
|
||||
writeObject(data, size, out, startName, endName, sectionName, machine,
|
||||
machineMask, sectionMask);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace binaryToObject
|
||||
|
125
src/binaryToObject/tools.cpp
Normal file
125
src/binaryToObject/tools.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/* Copyright (c) 2009, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tools.h"
|
||||
|
||||
namespace avian {
|
||||
|
||||
namespace tools {
|
||||
|
||||
String::String(const char* text):
|
||||
text(text),
|
||||
length(strlen(text)) {}
|
||||
|
||||
Buffer::Buffer():
|
||||
capacity(100),
|
||||
length(0),
|
||||
data((uint8_t*)malloc(capacity)) {}
|
||||
|
||||
Buffer::~Buffer() {
|
||||
free(data);
|
||||
}
|
||||
|
||||
void Buffer::ensure(size_t more) {
|
||||
if(length + more > capacity) {
|
||||
capacity = capacity * 2 + more;
|
||||
data = (uint8_t*)realloc(data, capacity);
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::write(const void* d, size_t size) {
|
||||
ensure(size);
|
||||
memcpy(data + length, d, size);
|
||||
length += size;
|
||||
}
|
||||
|
||||
unsigned StringTable::add(String str) {
|
||||
unsigned offset = Buffer::length;
|
||||
Buffer::write(str.text, str.length + 1);
|
||||
return offset;
|
||||
}
|
||||
|
||||
void OutputStream::write(uint8_t byte) {
|
||||
writeChunk(&byte, 1);
|
||||
}
|
||||
|
||||
void OutputStream::writeRepeat(uint8_t byte, size_t size) {
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
write(byte);
|
||||
}
|
||||
}
|
||||
|
||||
FileOutputStream::FileOutputStream(const char* name):
|
||||
file(fopen(name, "wb")) {}
|
||||
|
||||
FileOutputStream::~FileOutputStream() {
|
||||
if(file) {
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileOutputStream::isValid() {
|
||||
return file;
|
||||
}
|
||||
|
||||
void FileOutputStream::writeChunk(const void* data, size_t size) {
|
||||
fwrite(data, size, 1, file);
|
||||
}
|
||||
|
||||
void FileOutputStream::write(uint8_t byte) {
|
||||
fputc(byte, file);
|
||||
}
|
||||
|
||||
|
||||
Platform* Platform::first = 0;
|
||||
|
||||
PlatformInfo::OperatingSystem PlatformInfo::osFromString(const char* os) {
|
||||
if(strcmp(os, "linux") == 0) {
|
||||
return Linux;
|
||||
} else if(strcmp(os, "windows") == 0) {
|
||||
return Windows;
|
||||
} else if(strcmp(os, "darwin") == 0) {
|
||||
return Darwin;
|
||||
} else {
|
||||
return UnknownOS;
|
||||
}
|
||||
}
|
||||
|
||||
PlatformInfo::Architecture PlatformInfo::archFromString(const char* arch) {
|
||||
if(strcmp(arch, "i386") == 0) {
|
||||
return x86;
|
||||
} else if(strcmp(arch, "x86_64") == 0) {
|
||||
return x86_64;
|
||||
} else if(strcmp(arch, "powerpc") == 0) {
|
||||
return PowerPC;
|
||||
} else if(strcmp(arch, "arm") == 0) {
|
||||
return Arm;
|
||||
} else {
|
||||
return UnknownArch;
|
||||
}
|
||||
}
|
||||
|
||||
Platform* Platform::getPlatform(PlatformInfo info) {
|
||||
for(Platform* p = first; p; p = p->next) {
|
||||
if(p->info == info) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace tools
|
||||
|
||||
} // namespace avian
|
157
src/binaryToObject/tools.h
Normal file
157
src/binaryToObject/tools.h
Normal file
@ -0,0 +1,157 @@
|
||||
/* Copyright (c) 2009, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
#ifndef AVIAN_TOOLS_H_
|
||||
#define AVIAN_TOOLS_H_
|
||||
|
||||
namespace avian {
|
||||
|
||||
namespace tools {
|
||||
|
||||
class OutputStream {
|
||||
public:
|
||||
virtual void writeChunk(const void* data, size_t size) = 0;
|
||||
virtual void write(uint8_t byte);
|
||||
virtual void writeRepeat(uint8_t byte, size_t size);
|
||||
};
|
||||
|
||||
class FileOutputStream : public OutputStream {
|
||||
private:
|
||||
FILE* file;
|
||||
public:
|
||||
FileOutputStream(const char* name);
|
||||
~FileOutputStream();
|
||||
|
||||
bool isValid();
|
||||
|
||||
virtual void writeChunk(const void* data, size_t size);
|
||||
virtual void write(uint8_t byte);
|
||||
};
|
||||
|
||||
class String {
|
||||
public:
|
||||
const char* text;
|
||||
size_t length;
|
||||
|
||||
String(const char* text);
|
||||
};
|
||||
|
||||
class SymbolInfo {
|
||||
public:
|
||||
unsigned addr;
|
||||
String name;
|
||||
|
||||
inline SymbolInfo(uint64_t addr, const char* name):
|
||||
addr(addr),
|
||||
name(name) {}
|
||||
|
||||
inline SymbolInfo():
|
||||
name("") {}
|
||||
};
|
||||
|
||||
class Buffer {
|
||||
public:
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
uint8_t* data;
|
||||
|
||||
Buffer();
|
||||
~Buffer();
|
||||
|
||||
void ensure(size_t more);
|
||||
void write(const void* d, size_t size);
|
||||
};
|
||||
|
||||
class StringTable : public Buffer {
|
||||
public:
|
||||
unsigned add(String str);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class Slice {
|
||||
public:
|
||||
T* items;
|
||||
size_t count;
|
||||
|
||||
inline Slice(T* items, size_t count):
|
||||
items(items),
|
||||
count(count) {}
|
||||
|
||||
inline T* begin() {
|
||||
return items;
|
||||
}
|
||||
|
||||
inline T* end() {
|
||||
return items + count;
|
||||
}
|
||||
};
|
||||
|
||||
class PlatformInfo {
|
||||
public:
|
||||
enum OperatingSystem {
|
||||
Linux, Windows, Darwin, UnknownOS
|
||||
};
|
||||
|
||||
enum Architecture {
|
||||
x86, x86_64, PowerPC, Arm, UnknownArch
|
||||
};
|
||||
|
||||
const OperatingSystem os;
|
||||
const Architecture arch;
|
||||
|
||||
static OperatingSystem osFromString(const char* os);
|
||||
static Architecture archFromString(const char* arch);
|
||||
|
||||
inline PlatformInfo(OperatingSystem os, Architecture arch):
|
||||
os(os),
|
||||
arch(arch) {}
|
||||
|
||||
inline PlatformInfo(const char* os, const char* arch):
|
||||
os(osFromString(os)),
|
||||
arch(archFromString(arch)) {}
|
||||
|
||||
inline bool operator == (const PlatformInfo& other) {
|
||||
return os == other.os && arch == other.arch;
|
||||
}
|
||||
|
||||
inline bool isLittleEndian() {
|
||||
return arch != PowerPC;
|
||||
}
|
||||
};
|
||||
|
||||
class Platform {
|
||||
private:
|
||||
Platform* next;
|
||||
static Platform* first;
|
||||
public:
|
||||
PlatformInfo info;
|
||||
|
||||
inline Platform(PlatformInfo info):
|
||||
next(first),
|
||||
info(info)
|
||||
{
|
||||
first = this;
|
||||
}
|
||||
|
||||
enum AccessFlags {
|
||||
Writable = 1 << 0,
|
||||
Executable = 1 << 1
|
||||
};
|
||||
|
||||
virtual bool writeObject(OutputStream* out, Slice<SymbolInfo> symbols, Slice<const uint8_t> data, unsigned accessFlags, unsigned alignment) = 0;
|
||||
|
||||
static Platform* getPlatform(PlatformInfo info);
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
|
||||
} // namespace avian
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user