243 lines
6.1 KiB
C++
243 lines
6.1 KiB
C++
#include <ehs/EHS.h>
|
|
#include <ehs/io/Console.h>
|
|
#include <ehs/io/File.h>
|
|
|
|
#define ARCH_32 0x01
|
|
#define ARCH_64 0x02
|
|
|
|
#define END_LE 0x01
|
|
#define END_BE 0x02
|
|
|
|
#define TARGET_ABI_SYSTEMV 0x00
|
|
|
|
#define ELF_TYPE_EXEC 0x02
|
|
#define ELF_TYPE_DYN 0x03
|
|
|
|
#define MACHINE_ARCH_AMD_X86_64 0x003E
|
|
|
|
#define PROGRAM_TYPE_LOAD 0x00000001
|
|
|
|
#define PROGRAM_FLAG_EXEC 0x00000001
|
|
#define PROGRAM_FLAG_WRITE 0x00000002
|
|
#define PROGRAM_FLAG_READ 0x00000004
|
|
|
|
#define SECTION_TYPE_NULL 0x00
|
|
#define SECTION_TYPE_PROGBITS 0x01
|
|
#define SECTION_TYPE_STRTAB 0x03
|
|
|
|
#define SECTION_FLAG_ALLOC 0x02
|
|
#define SECTION_FLAG_EXEC 0x04
|
|
#define SECTION_FLAG_STRINGS 0x20
|
|
|
|
#define ELF_HEADER_SIZE 64
|
|
#define PROGRAM_HEADER_SIZE 56
|
|
#define SECTION_HEADER_SIZE 64
|
|
|
|
struct ElfHeader
|
|
{
|
|
ehs::UInt_8 architecture;
|
|
ehs::UInt_8 endianness;
|
|
ehs::UInt_8 elfV1;
|
|
ehs::UInt_8 targetABI;
|
|
ehs::UInt_8 abiV;
|
|
ehs::UInt_16 elfType;
|
|
ehs::UInt_16 machineArch;
|
|
ehs::UInt_32 elfV2;
|
|
ehs::UInt_64 entryAddress;
|
|
ehs::UInt_64 programsOffset;
|
|
ehs::UInt_64 sectionsOffset;
|
|
ehs::UInt_32 flags;
|
|
ehs::UInt_16 headerSize;
|
|
ehs::UInt_16 pHeaderSize;
|
|
ehs::UInt_16 pEntries;
|
|
ehs::UInt_16 sSize;
|
|
ehs::UInt_16 sEntries;
|
|
ehs::UInt_16 sIndex;
|
|
};
|
|
|
|
struct ProgramHeader
|
|
{
|
|
ehs::UInt_32 type;
|
|
ehs::UInt_32 flags;
|
|
ehs::UInt_64 offset;
|
|
ehs::UInt_64 vAddr;
|
|
ehs::UInt_64 pAddr;
|
|
ehs::UInt_64 fileSize;
|
|
ehs::UInt_64 memSize;
|
|
ehs::UInt_64 align;
|
|
};
|
|
|
|
struct SectionHeader
|
|
{
|
|
ehs::UInt_32 index;
|
|
ehs::UInt_32 type;
|
|
ehs::UInt_64 flags;
|
|
ehs::UInt_64 vAddr;
|
|
ehs::UInt_64 offset;
|
|
ehs::UInt_64 size;
|
|
ehs::UInt_32 associatedIndex;
|
|
ehs::UInt_32 info;
|
|
ehs::UInt_64 align;
|
|
ehs::UInt_64 entrySize;
|
|
};
|
|
|
|
// The executable code for the program
|
|
unsigned char code[] = {
|
|
0x48, 0xC7, 0xC0, 0x3C, 0x00, 0x00, 0x00, // mov eax, 60
|
|
0x48, 0x31, 0xFF, // xor edi, edi
|
|
0x0f, 0x05 // syscall
|
|
};
|
|
|
|
void WriteHeader(ElfHeader header, ehs::Serializer<ehs::UInt_64>& data)
|
|
{
|
|
data.Write((ehs::Byte)0x7F);
|
|
data.Write('E');
|
|
data.Write('L');
|
|
data.Write('F');
|
|
data.Write(header.architecture);
|
|
data.Write(header.endianness);
|
|
data.Write(header.elfV1);
|
|
data.Write(header.targetABI);
|
|
data.Write(header.abiV);
|
|
|
|
data.Resize(data.Size() + 7);
|
|
ehs::Util::Zero(&data[data.GetOffset()], 7);
|
|
data.SetOffset(data.GetOffset() + 7);
|
|
|
|
data.Write(header.elfType);
|
|
data.Write(header.machineArch);
|
|
data.Write(header.elfV2);
|
|
data.Write(header.entryAddress);
|
|
data.Write(header.programsOffset);
|
|
data.Write(header.sectionsOffset);
|
|
data.Write(header.flags);
|
|
data.Write(header.headerSize);
|
|
data.Write(header.pHeaderSize);
|
|
data.Write(header.pEntries);
|
|
data.Write(header.sSize);
|
|
data.Write(header.sEntries);
|
|
data.Write(header.sIndex);
|
|
}
|
|
|
|
void WriteHeader(ProgramHeader header, ehs::Serializer<ehs::UInt_64>& data)
|
|
{
|
|
data.Write(header.type);
|
|
data.Write(header.flags);
|
|
data.Write(header.offset);
|
|
data.Write(header.vAddr);
|
|
data.Write(header.pAddr);
|
|
data.Write(header.fileSize);
|
|
data.Write(header.memSize);
|
|
data.Write(header.align);
|
|
}
|
|
|
|
void WriteHeader(SectionHeader header, ehs::Serializer<ehs::UInt_64>& data)
|
|
{
|
|
data.Write(header.index);
|
|
data.Write(header.type);
|
|
data.Write(header.flags);
|
|
data.Write(header.vAddr);
|
|
data.Write(header.offset);
|
|
data.Write(header.size);
|
|
data.Write(header.associatedIndex);
|
|
data.Write(header.info);
|
|
data.Write(header.align);
|
|
data.Write(header.entrySize);
|
|
}
|
|
|
|
ehs::SInt_32 Main(ehs::Str_8* appName, ehs::Str_8* appVerId, ehs::Version* appVer)
|
|
{
|
|
*appName = "Compiler";
|
|
*appVerId = "Alpha";
|
|
*appVer = {1, 0, 0};
|
|
|
|
char sections[] = "\0.text\0.shstrtab\0";
|
|
|
|
ElfHeader elfHeader = {};
|
|
elfHeader.architecture = ARCH_64;
|
|
elfHeader.endianness = END_LE;
|
|
elfHeader.elfV1 = 1;
|
|
elfHeader.targetABI = TARGET_ABI_SYSTEMV;
|
|
elfHeader.abiV = 0;
|
|
elfHeader.elfType = ELF_TYPE_EXEC;
|
|
elfHeader.machineArch = MACHINE_ARCH_AMD_X86_64;
|
|
elfHeader.elfV2 = 1;
|
|
elfHeader.entryAddress = 0x400000 + ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE;
|
|
elfHeader.programsOffset = ELF_HEADER_SIZE;
|
|
elfHeader.sectionsOffset = ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE + sizeof(code) + sizeof(sections);
|
|
elfHeader.flags = 0;
|
|
elfHeader.headerSize = ELF_HEADER_SIZE;
|
|
elfHeader.pHeaderSize = PROGRAM_HEADER_SIZE;
|
|
elfHeader.pEntries = 1;
|
|
elfHeader.sSize = SECTION_HEADER_SIZE;
|
|
elfHeader.sEntries = 3;
|
|
elfHeader.sIndex = 2;
|
|
|
|
ProgramHeader programHeader = {};
|
|
programHeader.type = PROGRAM_TYPE_LOAD;
|
|
programHeader.flags = PROGRAM_FLAG_EXEC | PROGRAM_FLAG_READ;
|
|
programHeader.offset = 0;
|
|
programHeader.vAddr = 0x400000;
|
|
programHeader.pAddr = 0x400000;
|
|
programHeader.fileSize = ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE + sizeof(code);
|
|
programHeader.memSize = ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE + sizeof(code);
|
|
programHeader.align = 0x200000;
|
|
|
|
SectionHeader null = {};
|
|
null.index = 0;
|
|
null.type = SECTION_TYPE_NULL;
|
|
null.flags = 0;
|
|
null.vAddr = 0;
|
|
null.offset = 0;
|
|
null.size = 0;
|
|
null.associatedIndex = 0;
|
|
null.info = 0;
|
|
null.align = 0;
|
|
null.entrySize = 0;
|
|
|
|
SectionHeader text = {};
|
|
text.index = 1;
|
|
text.type = SECTION_TYPE_PROGBITS;
|
|
text.flags = SECTION_FLAG_ALLOC | SECTION_FLAG_EXEC;
|
|
text.vAddr = 0x400000 + ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE;
|
|
text.offset = ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE;
|
|
text.size = sizeof(code);
|
|
text.associatedIndex = 0;
|
|
text.info = 0;
|
|
text.align = 16;
|
|
text.entrySize = 0;
|
|
|
|
SectionHeader strTbl = {};
|
|
strTbl.index = 7;
|
|
strTbl.type = SECTION_TYPE_STRTAB;
|
|
strTbl.flags = SECTION_FLAG_STRINGS;
|
|
strTbl.vAddr = 0;
|
|
strTbl.offset = ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE + sizeof(code);
|
|
strTbl.size = sizeof(sections);
|
|
strTbl.associatedIndex = 0;
|
|
strTbl.info = 0;
|
|
strTbl.align = 0;
|
|
strTbl.entrySize = 0;
|
|
|
|
ehs::Serializer<ehs::UInt_64> data(ehs::Endianness::LE);
|
|
WriteHeader(elfHeader, data);
|
|
WriteHeader(programHeader, data);
|
|
|
|
data.Resize(data.Size() + sizeof(code));
|
|
ehs::Util::Copy(&data[data.GetOffset()], code, sizeof(code));
|
|
data.SetOffset(data.GetOffset() + sizeof(code));
|
|
|
|
data.Resize(data.Size() + sizeof(sections));
|
|
ehs::Util::Copy(&data[data.GetOffset()], sections, sizeof(sections));
|
|
data.SetOffset(data.GetOffset() + sizeof(sections));
|
|
|
|
WriteHeader(null, data);
|
|
WriteHeader(text, data);
|
|
WriteHeader(strTbl, data);
|
|
|
|
ehs::File file("app", ehs::Mode::WRITE, ehs::Disposition::CREATE_PERSISTENT);
|
|
file.WriteSerializer_64(data);
|
|
|
|
return 0;
|
|
}
|