mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
378 lines
8.6 KiB
C++
378 lines
8.6 KiB
C++
/* Copyright (c) 2008-2010, 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 "string.h"
|
|
|
|
#define V1(v) v
|
|
|
|
#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
|
|
|
|
#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
|
|
|
|
#define N_SECT 0xe
|
|
#define N_EXT 0x1
|
|
|
|
#define CPU_ARCH_ABI64 0x01000000
|
|
|
|
#define CPU_TYPE_I386 7
|
|
#define CPU_TYPE_X86_64 (CPU_TYPE_I386 | CPU_ARCH_ABI64)
|
|
#define CPU_TYPE_POWERPC 18
|
|
|
|
#define CPU_SUBTYPE_I386_ALL 3
|
|
#define CPU_SUBTYPE_X86_64_ALL CPU_SUBTYPE_I386_ALL
|
|
#define CPU_SUBTYPE_POWERPC_ALL 0
|
|
|
|
#if (BITS_PER_WORD == 64)
|
|
# define VW(v) V8(v)
|
|
# 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 VW(v) V4(v)
|
|
# 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 {
|
|
|
|
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;
|
|
};
|
|
|
|
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);
|
|
}
|
|
|
|
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
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
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
|
|
}
|
|
};
|
|
|
|
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);
|
|
}
|
|
|
|
} // 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)
|
|
{
|
|
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 {
|
|
fprintf(stderr, "unsupported architecture: %s\n", architecture);
|
|
return false;
|
|
}
|
|
|
|
const char* segmentName;
|
|
const char* sectionName;
|
|
if (writable) {
|
|
segmentName = "__RWX";
|
|
sectionName = "__rwx";
|
|
} 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
|