ELFLoader works inside the kernel!

We load /_hello.o which just prints out a simple message.
It executes inside the kernel itself, so no fancy userspace process
or anything, but this is still so cool!
This commit is contained in:
Andreas Kling 2018-10-18 15:38:04 +02:00
parent 6ab0649ad6
commit 97e0d75bcb
10 changed files with 72 additions and 15 deletions

View file

@ -2,8 +2,8 @@
#include <AK/kstdio.h>
#ifdef SERENITY_KERNEL
ELFImage::ELFImage(const byte* data)
: m_data(data)
ELFImage::ELFImage(ByteBuffer&& buffer)
: m_buffer(buffer)
{
m_isValid = parse();
}
@ -137,7 +137,7 @@ const char* ELFImage::tableString(unsigned offset) const
const char* ELFImage::rawData(unsigned offset) const
{
#ifdef SERENITY_KERNEL
return reinterpret_cast<const char*>(m_data) + offset;
return reinterpret_cast<const char*>(m_buffer.pointer()) + offset;
#else
return reinterpret_cast<const char*>(m_file.pointer()) + offset;
#endif
@ -178,7 +178,7 @@ const ELFImage::RelocationSection ELFImage::Section::relocations() const
{
// FIXME: This is ugly.
char relocationSectionName[128];
ksprintf(relocationSectionName, ".rel%s", name());
int x = ksprintf(relocationSectionName, ".rel%s", name());
kprintf("looking for '%s'\n", relocationSectionName);
auto relocationSection = m_image.lookupSection(relocationSectionName);

View file

@ -12,7 +12,7 @@
class ELFImage {
public:
#ifdef SERENITY_KERNEL
explicit ELFImage(const byte* data);
explicit ELFImage(ByteBuffer&&);
#else
explicit ELFImage(MappedFile&&);
#endif
@ -132,7 +132,7 @@ private:
const char* sectionIndexToString(unsigned index);
#ifdef SERENITY_KERNEL
const byte* m_data;
ByteBuffer m_buffer;
#else
MappedFile m_file;
#endif

View file

@ -1,7 +1,11 @@
#include "ELFLoader.h"
#include <AK/kstdio.h>
#ifdef SERENITY_KERNEL
ELFLoader::ELFLoader(ExecSpace& execSpace, ByteBuffer&& file)
#else
ELFLoader::ELFLoader(ExecSpace& execSpace, MappedFile&& file)
#endif
: m_execSpace(execSpace)
{
m_image = make<ELFImage>(move(file));
@ -104,9 +108,9 @@ void ELFLoader::performRelocations()
void ELFLoader::exportSymbols()
{
m_image->forEachSymbol([&] (const ELFImage::Symbol symbol) {
kprintf("symbol: %u, type=%u, name=%s\n", symbol.index(), symbol.type(), symbol.name());
kprintf("symbol: %u, type=%u, name=%s, section=%u\n", symbol.index(), symbol.type(), symbol.name(), symbol.sectionIndex());
if (symbol.type() == STT_FUNC)
m_execSpace.addSymbol(symbol.name(), areaForSectionName(".text") + symbol.value(), symbol.size());
m_execSpace.addSymbol(symbol.name(), areaForSection(symbol.section()) + symbol.value(), symbol.size());
// FIXME: What about other symbol types?
});
}

View file

@ -9,7 +9,11 @@
class ELFLoader {
public:
#ifdef SERENITY_KERNEL
ELFLoader(ExecSpace&, ByteBuffer&&);
#else
ELFLoader(ExecSpace&, MappedFile&&);
#endif
~ELFLoader();
bool load();

View file

@ -12,19 +12,31 @@ ExecSpace::~ExecSpace()
{
}
#ifdef SERENITY_KERNEL
int puts(const char* str)
{
kprintf("%s\n", str);
return 0;
}
#endif
void ExecSpace::initializeBuiltins()
{
m_symbols.set("puts", { (char*)puts, 0 });
}
#ifdef SERENITY_KERNEL
bool ExecSpace::loadELF(ByteBuffer&& file)
#else
bool ExecSpace::loadELF(MappedFile&& file)
#endif
{
ELFLoader loader(*this, move(file));
if (!loader.load())
return false;
printf("[ExecSpace] ELF loaded, symbol map now:\n");
kprintf("[ExecSpace] ELF loaded, symbol map now:\n");
for (auto& s : m_symbols) {
printf("> %p: %s (%u)\n",
kprintf("> %p: %s (%u)\n",
s.value.ptr,
s.key.characters(),
s.value.size);
@ -34,11 +46,15 @@ bool ExecSpace::loadELF(MappedFile&& file)
static void disassemble(const char* data, size_t length)
{
#ifdef SERENITY_KERNEL
#else
if (!length)
return;
#ifdef SERENITY_KERNEL
for (unsigned i = 0; i < length; ++i) {
kprintf("%b ", (unsigned char)data[i]);
}
kprintf("\n");
#else
TemporaryFile temp;
if (!temp.isValid()) {
fprintf(stderr, "Unable to create temp file for disassembly.\n");
@ -52,7 +68,7 @@ static void disassemble(const char* data, size_t length)
temp.sync();
char cmdbuf[128];
sprintf(cmdbuf, "nasm -f bin -o /dev/stdout %s | ndisasm -b32 -", temp.fileName().characters());
ksprintf(cmdbuf, "nasm -f bin -o /dev/stdout %s | ndisasm -b32 -", temp.fileName().characters());
system(cmdbuf);
#endif
}
@ -60,7 +76,7 @@ static void disassemble(const char* data, size_t length)
char* ExecSpace::symbolPtr(const char* name)
{
if (auto it = m_symbols.find(name); it != m_symbols.end()) {
printf("[ELFLoader] symbolPtr(%s) dump:\n", name);
kprintf("[ELFLoader] symbolPtr(%s) dump:\n", name);
auto& symbol = (*it).value;
disassemble(symbol.ptr, symbol.size);
return symbol.ptr;

View file

@ -37,7 +37,11 @@ public:
ExecSpace();
~ExecSpace();
#ifdef SERENITY_KERNEL
bool loadELF(ByteBuffer&&);
#else
bool loadELF(MappedFile&&);
#endif
char* symbolPtr(const char* name);

Binary file not shown.

7
Kernel/_hello.cpp Normal file
View file

@ -0,0 +1,7 @@
extern "C" int puts(const char*);
extern "C" int elf_entry()
{
puts("Home, where you are supposed to be...");
return 0;
}

View file

@ -2,7 +2,7 @@
using namespace Userspace;
int elf_entry()
extern "C" int elf_entry()
{
int fd = open("/Banner.txt");
char buf[2048];

View file

@ -23,6 +23,7 @@
#include <VirtualFileSystem/FileHandle.h>
#include <AK/OwnPtr.h>
#include "MemoryManager.h"
#include <ELFLoader/ELFLoader.h>
#if 0
/* Keyboard LED disco task ;^) */
@ -82,6 +83,8 @@ static void user_kprintf_main()
DO_SYSCALL_A1(0x4000, 0);
kprintf("This should not work!\n");
HANG;
for (;;) {
}
}
system_t system;
@ -179,6 +182,25 @@ void init()
}
#endif
{
auto testExecutable = vfs->open("/_hello.o");
ASSERT(testExecutable);
auto testExecutableData = testExecutable->readEntireFile();
ASSERT(testExecutableData);
ExecSpace space;
space.loadELF(move(testExecutableData));
auto* elf_entry = space.symbolPtr("elf_entry");
ASSERT(elf_entry);
typedef int (*MainFunctionPtr)(void);
kprintf("elf_entry: %p\n", elf_entry);
int rc = reinterpret_cast<MainFunctionPtr>(elf_entry)();
kprintf("it returned %d\n", rc);
HANG;
}
// The idle task will spend its eternity here for now.
for (;;) {
asm("hlt");