Compiler/main.cpp

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;
}