mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 16:37:35 +00:00
Merge ExecSpace into ELFLoader.
This commit is contained in:
parent
d90b891406
commit
422b5403e5
7 changed files with 55 additions and 120 deletions
|
@ -3,8 +3,7 @@
|
||||||
|
|
||||||
//#define ELFLOADER_DEBUG
|
//#define ELFLOADER_DEBUG
|
||||||
|
|
||||||
ELFLoader::ELFLoader(ExecSpace& execSpace, ByteBuffer&& buffer)
|
ELFLoader::ELFLoader(ByteBuffer&& buffer)
|
||||||
: m_execSpace(execSpace)
|
|
||||||
{
|
{
|
||||||
m_image = make<ELFImage>(move(buffer));
|
m_image = make<ELFImage>(move(buffer));
|
||||||
}
|
}
|
||||||
|
@ -43,7 +42,7 @@ bool ELFLoader::layout()
|
||||||
#ifdef ELFLOADER_DEBUG
|
#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());
|
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
|
#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) {
|
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)
|
void* ELFLoader::lookup(const ELFImage::Symbol& symbol)
|
||||||
{
|
{
|
||||||
if (symbol.section().isUndefined())
|
if (symbol.section().isUndefined())
|
||||||
return m_execSpace.symbolPtr(symbol.name());
|
return symbol_ptr(symbol.name());
|
||||||
return areaForSection(symbol.section()) + symbol.value();
|
return areaForSection(symbol.section()) + symbol.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,10 +177,35 @@ void ELFLoader::exportSymbols()
|
||||||
ptr = areaForSection(symbol.section()) + symbol.value();
|
ptr = areaForSection(symbol.section()) + symbol.value();
|
||||||
else
|
else
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
m_execSpace.addSymbol(symbol.name(), ptr, symbol.size());
|
add_symbol(symbol.name(), ptr, symbol.size());
|
||||||
}
|
}
|
||||||
// FIXME: What about other symbol types?
|
// FIXME: What about other symbol types?
|
||||||
return true;
|
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 });
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Function.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include "ExecSpace.h"
|
|
||||||
#include "ELFImage.h"
|
#include "ELFImage.h"
|
||||||
|
|
||||||
class ELFLoader {
|
class ELFLoader {
|
||||||
public:
|
public:
|
||||||
ELFLoader(ExecSpace&, ByteBuffer&&);
|
ELFLoader(ByteBuffer&&);
|
||||||
~ELFLoader();
|
~ELFLoader();
|
||||||
|
|
||||||
bool load();
|
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:
|
private:
|
||||||
bool layout();
|
bool layout();
|
||||||
|
@ -21,7 +25,18 @@ private:
|
||||||
char* areaForSection(const ELFImage::Section&);
|
char* areaForSection(const ELFImage::Section&);
|
||||||
char* areaForSectionName(const char*);
|
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;
|
HashMap<String, char*> m_sections;
|
||||||
OwnPtr<ELFImage> m_image;
|
OwnPtr<ELFImage> m_image;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 });
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
|
@ -39,8 +39,7 @@ VFS_OBJS = \
|
||||||
|
|
||||||
ELFLOADER_OBJS = \
|
ELFLOADER_OBJS = \
|
||||||
../ELFLoader/ELFImage.o \
|
../ELFLoader/ELFImage.o \
|
||||||
../ELFLoader/ELFLoader.o \
|
../ELFLoader/ELFLoader.o
|
||||||
../ELFLoader/ExecSpace.o
|
|
||||||
|
|
||||||
AK_OBJS = \
|
AK_OBJS = \
|
||||||
../AK/String.o \
|
../AK/String.o \
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include <VirtualFileSystem/FileHandle.h>
|
#include <VirtualFileSystem/FileHandle.h>
|
||||||
#include <VirtualFileSystem/VirtualFileSystem.h>
|
#include <VirtualFileSystem/VirtualFileSystem.h>
|
||||||
#include <ELFLoader/ExecSpace.h>
|
#include <ELFLoader/ELFLoader.h>
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
#include "i8253.h"
|
#include "i8253.h"
|
||||||
|
@ -302,9 +302,6 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
|
||||||
PageDirectory* old_page_directory;
|
PageDirectory* old_page_directory;
|
||||||
PageDirectory* new_page_directory;
|
PageDirectory* new_page_directory;
|
||||||
{
|
{
|
||||||
ExecSpace space;
|
|
||||||
Region* region = nullptr;
|
|
||||||
|
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
// Okay, here comes the sleight of hand, pay close attention..
|
// Okay, here comes the sleight of hand, pay close attention..
|
||||||
auto old_regions = move(m_regions);
|
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);
|
MM.populate_page_directory(*new_page_directory);
|
||||||
m_page_directory = new_page_directory;
|
m_page_directory = new_page_directory;
|
||||||
MM.enter_process_paging_scope(*this);
|
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);
|
ASSERT(size);
|
||||||
size = ((size / 4096) + 1) * 4096; // FIXME: Use ceil_div?
|
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();
|
return laddr.asPtr();
|
||||||
};
|
};
|
||||||
bool success = space.loadELF(move(elfData));
|
bool success = loader.load();
|
||||||
if (!success) {
|
if (!success) {
|
||||||
m_page_directory = old_page_directory;
|
m_page_directory = old_page_directory;
|
||||||
MM.enter_process_paging_scope(*this);
|
MM.enter_process_paging_scope(*this);
|
||||||
|
@ -329,7 +327,7 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
|
||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry_eip = (dword)space.symbolPtr("_start");
|
entry_eip = (dword)loader.symbol_ptr("_start");
|
||||||
if (!entry_eip) {
|
if (!entry_eip) {
|
||||||
m_page_directory = old_page_directory;
|
m_page_directory = old_page_directory;
|
||||||
MM.enter_process_paging_scope(*this);
|
MM.enter_process_paging_scope(*this);
|
||||||
|
|
|
@ -219,7 +219,7 @@ static void init_stage2()
|
||||||
|
|
||||||
ExecSpace space;
|
ExecSpace space;
|
||||||
space.loadELF(move(testExecutableData));
|
space.loadELF(move(testExecutableData));
|
||||||
auto* elf_entry = space.symbolPtr("_start");
|
auto* elf_entry = space.symbol_ptr("_start");
|
||||||
ASSERT(elf_entry);
|
ASSERT(elf_entry);
|
||||||
|
|
||||||
typedef int (*MainFunctionPtr)(void);
|
typedef int (*MainFunctionPtr)(void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue