feat(loader): add static x86_64 ELF loader
This commit is contained in:
1 parent
831a2e1de7
commit
afd0649188
2 files changed
+87
No files matched your search
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef FROSTBYTE_ELF_H
|
||||||
|
#define FROSTBYTE_ELF_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
typedef struct Elf64Header {
|
||||||
|
uint8 ident[16];
|
||||||
|
uint16 type;
|
||||||
|
uint16 machine;
|
||||||
|
uint32 version;
|
||||||
|
uint64 entry;
|
||||||
|
uint64 programHeaderOffset;
|
||||||
|
uint64 sectionHeaderOffset;
|
||||||
|
uint32 flags;
|
||||||
|
uint16 headerSize;
|
||||||
|
uint16 programHeaderEntrySize;
|
||||||
|
uint16 programHeaderCount;
|
||||||
|
uint16 sectionHeaderEntrySize;
|
||||||
|
uint16 sectionHeaderCount;
|
||||||
|
uint16 sectionNameIndex;
|
||||||
|
} __attribute__((packed)) Elf64Header;
|
||||||
|
|
||||||
|
typedef struct Elf64ProgramHeader {
|
||||||
|
uint32 type;
|
||||||
|
uint32 flags;
|
||||||
|
uint64 offset;
|
||||||
|
uint64 virtualAddr;
|
||||||
|
uint64 physicalAddr;
|
||||||
|
uint64 fileSize;
|
||||||
|
uint64 memorySize;
|
||||||
|
uint64 align;
|
||||||
|
} __attribute__((packed)) Elf64ProgramHeader;
|
||||||
|
|
||||||
|
uint64 elfLoad(const void* image, uint64 imageSize);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#include "elf.h"
|
||||||
|
#include "paging.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
#define programTypeLoad 1
|
||||||
|
#define elfTypeExec 2
|
||||||
|
#define elfMachineX8664 62
|
||||||
|
|
||||||
|
static bool validHeader(const Elf64Header* header)
|
||||||
|
{
|
||||||
|
if (header->ident[0] != 0x7F || header->ident[1] != 'E' ||
|
||||||
|
header->ident[2] != 'L' || header->ident[3] != 'F')
|
||||||
|
return false;
|
||||||
|
if (header->ident[4] != 2)
|
||||||
|
return false;
|
||||||
|
if (header->type != elfTypeExec)
|
||||||
|
return false;
|
||||||
|
if (header->machine != elfMachineX8664)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 elfLoad(const void* image, uint64 imageSize)
|
||||||
|
{
|
||||||
|
const Elf64Header* header = (const Elf64Header*)image;
|
||||||
|
|
||||||
|
if (imageSize < sizeof(Elf64Header) || !validHeader(header)) {
|
||||||
|
kprintf("[elf] rejected image: not a static x86_64 ELF\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8* base = (const uint8*)image;
|
||||||
|
|
||||||
|
for (uint16 i = 0; i < header->programHeaderCount; i++) {
|
||||||
|
const Elf64ProgramHeader* segment = (const Elf64ProgramHeader*)
|
||||||
|
(base + header->programHeaderOffset + (uint64)i * header->programHeaderEntrySize);
|
||||||
|
|
||||||
|
if (segment->type != programTypeLoad)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!pagingMapUserRange(segment->virtualAddr, segment->memorySize)) {
|
||||||
|
kprintf("[elf] failed to map segment at %p\n", (void*)segment->virtualAddr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((void*)segment->virtualAddr, base + segment->offset, segment->fileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return header->entry;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user