Ver Fonte

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!
Andreas Kling há 6 anos atrás
pai
commit
97e0d75bcb

+ 4 - 4
ELFLoader/ELFImage.cpp

@@ -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);

+ 2 - 2
ELFLoader/ELFImage.h

@@ -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

+ 6 - 2
ELFLoader/ELFLoader.cpp

@@ -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?
     });
 }

+ 4 - 0
ELFLoader/ELFLoader.h

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

+ 22 - 6
ELFLoader/ExecSpace.cpp

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

+ 4 - 0
ELFLoader/ExecSpace.h

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

BIN
Kernel/_fs_contents


+ 7 - 0
Kernel/_hello.cpp

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

+ 1 - 1
Kernel/_test.cpp

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

+ 22 - 0
Kernel/init.cpp

@@ -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");