Merge ExecSpace into ELFLoader.

This commit is contained in:
Andreas Kling 2018-11-04 13:52:53 +01:00
parent d90b891406
commit 422b5403e5
7 changed files with 55 additions and 120 deletions

View file

@ -3,8 +3,7 @@
//#define ELFLOADER_DEBUG
ELFLoader::ELFLoader(ExecSpace& execSpace, ByteBuffer&& buffer)
: m_execSpace(execSpace)
ELFLoader::ELFLoader(ByteBuffer&& buffer)
{
m_image = make<ELFImage>(move(buffer));
}
@ -43,7 +42,7 @@ bool ELFLoader::layout()
#ifdef ELFLOADER_DEBUG
kprintf("PH: L%x %u r:%u w:%u\n", program_header.laddr().get(), program_header.size_in_memory(), program_header.is_readable(), program_header.is_writable());
#endif
m_execSpace.allocate_section(program_header.laddr(), program_header.size_in_memory(), program_header.alignment(), program_header.is_readable(), program_header.is_writable());
allocate_section(program_header.laddr(), program_header.size_in_memory(), program_header.alignment(), program_header.is_readable(), program_header.is_writable());
});
m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) {
@ -85,7 +84,7 @@ bool ELFLoader::layout()
void* ELFLoader::lookup(const ELFImage::Symbol& symbol)
{
if (symbol.section().isUndefined())
return m_execSpace.symbolPtr(symbol.name());
return symbol_ptr(symbol.name());
return areaForSection(symbol.section()) + symbol.value();
}
@ -178,10 +177,35 @@ void ELFLoader::exportSymbols()
ptr = areaForSection(symbol.section()) + symbol.value();
else
ASSERT_NOT_REACHED();
m_execSpace.addSymbol(symbol.name(), ptr, symbol.size());
add_symbol(symbol.name(), ptr, symbol.size());
}
// FIXME: What about other symbol types?
return true;
});
}
char* ELFLoader::symbol_ptr(const char* name)
{
if (auto it = m_symbols.find(name); it != m_symbols.end()) {
auto& symbol = (*it).value;
#ifdef EXECSPACE_DEBUG
kprintf("[ELFLoader] symbol_ptr(%s) dump:\n", name);
disassemble(symbol.ptr, symbol.size);
#endif
return symbol.ptr;
}
return nullptr;
}
bool ELFLoader::allocate_section(LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable)
{
ASSERT(alloc_section_hook);
char namebuf[16];
ksprintf(namebuf, "elf-%s%s", is_readable ? "r" : "", is_writable ? "w" : "");
return alloc_section_hook(laddr, size, alignment, is_readable, is_writable, namebuf);
}
void ELFLoader::add_symbol(String&& name, char* ptr, unsigned size)
{
m_symbols.set(move(name), { ptr, size });
}

View file

@ -1,17 +1,21 @@
#pragma once
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
#include <AK/Vector.h>
#include "ExecSpace.h"
#include "ELFImage.h"
class ELFLoader {
public:
ELFLoader(ExecSpace&, ByteBuffer&&);
ELFLoader(ByteBuffer&&);
~ELFLoader();
bool load();
Function<void*(LinearAddress, size_t, size_t, bool, bool, const String&)> alloc_section_hook;
char* symbol_ptr(const char* name);
void add_symbol(String&& name, char* ptr, unsigned size);
bool allocate_section(LinearAddress, size_t, size_t alignment, bool is_readable, bool is_writable);
private:
bool layout();
@ -21,7 +25,18 @@ private:
char* areaForSection(const ELFImage::Section&);
char* areaForSectionName(const char*);
ExecSpace& m_execSpace;
struct PtrAndSize {
PtrAndSize() { }
PtrAndSize(char* p, unsigned s)
: ptr(p)
, size(s)
{
}
char* ptr { nullptr };
unsigned size { 0 };
};
HashMap<String, PtrAndSize> m_symbols;
HashMap<String, char*> m_sections;
OwnPtr<ELFImage> m_image;
};

View file

@ -1,58 +0,0 @@
#include "ExecSpace.h"
#include "ELFLoader.h"
#include <AK/Types.h>
//#define EXECSPACE_DEBUG
ExecSpace::ExecSpace()
{
}
ExecSpace::~ExecSpace()
{
}
bool ExecSpace::loadELF(ByteBuffer&& file)
{
ELFLoader loader(*this, move(file));
if (!loader.load())
return false;
#ifdef EXECSPACE_DEBUG
kprintf("ExecSpace: ELF loaded, symbol map now:\n");
for (auto& s : m_symbols) {
kprintf("> %p: %s (%u)\n",
s.value.ptr,
s.key.characters(),
s.value.size);
}
#endif
return true;
}
char* ExecSpace::symbolPtr(const char* name)
{
if (auto it = m_symbols.find(name); it != m_symbols.end()) {
auto& symbol = (*it).value;
#ifdef EXECSPACE_DEBUG
kprintf("[ELFLoader] symbolPtr(%s) dump:\n", name);
disassemble(symbol.ptr, symbol.size);
#endif
return symbol.ptr;
}
return nullptr;
}
bool ExecSpace::allocate_section(LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable)
{
ASSERT(alloc_section_hook);
char namebuf[16];
ksprintf(namebuf, "elf-%s%s", is_readable ? "r" : "", is_writable ? "w" : "");
auto* ptr = static_cast<char*>(alloc_section_hook(laddr, size, alignment, is_readable, is_writable, namebuf));
m_allocated_regions.append(ptr);
return true;
}
void ExecSpace::addSymbol(String&& name, char* ptr, unsigned size)
{
m_symbols.set(move(name), { ptr, size });
}

View file

@ -1,43 +0,0 @@
#pragma once
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
#include <AK/Vector.h>
#include <AK/String.h>
#include "types.h"
class ELFLoader;
class ExecSpace {
public:
struct PtrAndSize {
PtrAndSize() { }
PtrAndSize(char* p, unsigned s)
: ptr(p)
, size(s)
{
}
char* ptr { nullptr };
unsigned size { 0 };
};
ExecSpace();
~ExecSpace();
Function<void*(LinearAddress, size_t, size_t, bool, bool, const String&)> alloc_section_hook;
bool loadELF(ByteBuffer&&);
char* symbolPtr(const char* name);
void addSymbol(String&& name, char* ptr, unsigned size);
bool allocate_section(LinearAddress, size_t, size_t alignment, bool is_readable, bool is_writable);
private:
Vector<char*> m_allocated_regions;
HashMap<String, PtrAndSize> m_symbols;
};

View file

@ -39,8 +39,7 @@ VFS_OBJS = \
ELFLOADER_OBJS = \
../ELFLoader/ELFImage.o \
../ELFLoader/ELFLoader.o \
../ELFLoader/ExecSpace.o
../ELFLoader/ELFLoader.o
AK_OBJS = \
../AK/String.o \

View file

@ -7,7 +7,7 @@
#include "system.h"
#include <VirtualFileSystem/FileHandle.h>
#include <VirtualFileSystem/VirtualFileSystem.h>
#include <ELFLoader/ExecSpace.h>
#include <ELFLoader/ELFLoader.h>
#include "MemoryManager.h"
#include "errno.h"
#include "i8253.h"
@ -302,9 +302,6 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
PageDirectory* old_page_directory;
PageDirectory* new_page_directory;
{
ExecSpace space;
Region* region = nullptr;
InterruptDisabler disabler;
// Okay, here comes the sleight of hand, pay close attention..
auto old_regions = move(m_regions);
@ -313,13 +310,14 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
MM.populate_page_directory(*new_page_directory);
m_page_directory = new_page_directory;
MM.enter_process_paging_scope(*this);
space.alloc_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable, const String& name) {
ELFLoader loader(move(elfData));
loader.alloc_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable, const String& name) {
ASSERT(size);
size = ((size / 4096) + 1) * 4096; // FIXME: Use ceil_div?
region = allocate_region(laddr, size, String(name), is_readable, is_writable);
(void) allocate_region(laddr, size, String(name), is_readable, is_writable);
return laddr.asPtr();
};
bool success = space.loadELF(move(elfData));
bool success = loader.load();
if (!success) {
m_page_directory = old_page_directory;
MM.enter_process_paging_scope(*this);
@ -329,7 +327,7 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
return -ENOEXEC;
}
entry_eip = (dword)space.symbolPtr("_start");
entry_eip = (dword)loader.symbol_ptr("_start");
if (!entry_eip) {
m_page_directory = old_page_directory;
MM.enter_process_paging_scope(*this);

View file

@ -219,7 +219,7 @@ static void init_stage2()
ExecSpace space;
space.loadELF(move(testExecutableData));
auto* elf_entry = space.symbolPtr("_start");
auto* elf_entry = space.symbol_ptr("_start");
ASSERT(elf_entry);
typedef int (*MainFunctionPtr)(void);