Kernel: make load_elf() its own function
This commit is contained in:
parent
37b93da650
commit
51f4c0c750
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace LibELF { class ELF; }
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -86,7 +88,7 @@ namespace Kernel
|
||||||
static Process* create_process();
|
static Process* create_process();
|
||||||
static void register_process(Process*);
|
static void register_process(Process*);
|
||||||
|
|
||||||
BAN::ErrorOr<void> cleanup_and_load_elf(BAN::StringView);
|
void load_elf(LibELF::ELF&);
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||||
|
|
||||||
|
|
|
@ -46,15 +46,19 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<Process*> Process::create_userspace(BAN::StringView path)
|
BAN::ErrorOr<Process*> Process::create_userspace(BAN::StringView path)
|
||||||
{
|
{
|
||||||
|
auto* elf = TRY(LibELF::ELF::load_from_file(path));
|
||||||
|
if (!elf->is_native())
|
||||||
|
{
|
||||||
|
derrorln("ELF has invalid architecture");
|
||||||
|
delete elf;
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
auto* process = create_process();
|
auto* process = create_process();
|
||||||
MUST(process->m_working_directory.push_back('/'));
|
MUST(process->m_working_directory.push_back('/'));
|
||||||
process->m_page_table = MUST(PageTable::create_userspace());
|
process->m_page_table = MUST(PageTable::create_userspace());
|
||||||
|
|
||||||
if (auto res = process->cleanup_and_load_elf(path); res.is_error())
|
process->load_elf(*elf);
|
||||||
{
|
|
||||||
delete process;
|
|
||||||
return res.error();
|
|
||||||
}
|
|
||||||
|
|
||||||
char** argv = nullptr;
|
char** argv = nullptr;
|
||||||
{
|
{
|
||||||
|
@ -68,6 +72,9 @@ namespace Kernel
|
||||||
|
|
||||||
process->m_userspace_entry.argc = 1;
|
process->m_userspace_entry.argc = 1;
|
||||||
process->m_userspace_entry.argv = argv;
|
process->m_userspace_entry.argv = argv;
|
||||||
|
process->m_userspace_entry.entry = elf->file_header_native().e_entry;
|
||||||
|
|
||||||
|
delete elf;
|
||||||
|
|
||||||
auto* thread = MUST(Thread::create_userspace(process));
|
auto* thread = MUST(Thread::create_userspace(process));
|
||||||
process->add_thread(thread);
|
process->add_thread(thread);
|
||||||
|
@ -198,9 +205,30 @@ namespace Kernel
|
||||||
if (str_envp.emplace_back(*envp++).is_error())
|
if (str_envp.emplace_back(*envp++).is_error())
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
|
auto* elf = TRY(LibELF::ELF::load_from_file(path));
|
||||||
|
if (!elf->is_native())
|
||||||
|
{
|
||||||
|
derrorln("ELF has invalid architecture");
|
||||||
|
delete elf;
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
LockGuard lock_guard(m_lock);
|
LockGuard lock_guard(m_lock);
|
||||||
|
|
||||||
MUST(cleanup_and_load_elf(path));
|
m_fixed_width_allocators.clear();
|
||||||
|
m_general_allocator.clear();
|
||||||
|
|
||||||
|
for (auto* range : m_mapped_ranges)
|
||||||
|
delete range;
|
||||||
|
m_mapped_ranges.clear();
|
||||||
|
|
||||||
|
m_open_files.clear();
|
||||||
|
|
||||||
|
load_elf(*elf);
|
||||||
|
|
||||||
|
m_userspace_entry.entry = elf->file_header_native().e_entry;
|
||||||
|
|
||||||
|
delete elf;
|
||||||
|
|
||||||
ASSERT(m_threads.size() == 1);
|
ASSERT(m_threads.size() == 1);
|
||||||
ASSERT(&Process::current() == this);
|
ASSERT(&Process::current() == this);
|
||||||
|
@ -231,33 +259,14 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::cleanup_and_load_elf(BAN::StringView path)
|
void Process::load_elf(LibELF::ELF& elf)
|
||||||
{
|
{
|
||||||
auto* elf = TRY(LibELF::ELF::load_from_file(path));
|
ASSERT(elf.is_native());
|
||||||
if (!elf->is_native())
|
|
||||||
{
|
|
||||||
derrorln("ELF has invalid architecture");
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* allocator : m_fixed_width_allocators)
|
auto& elf_file_header = elf.file_header_native();
|
||||||
delete allocator;
|
|
||||||
m_fixed_width_allocators.clear();
|
|
||||||
|
|
||||||
if (m_general_allocator)
|
|
||||||
delete m_general_allocator;
|
|
||||||
m_general_allocator = nullptr;
|
|
||||||
|
|
||||||
for (auto* range : m_mapped_ranges)
|
|
||||||
delete range;
|
|
||||||
m_mapped_ranges.clear();
|
|
||||||
|
|
||||||
m_open_files.clear();
|
|
||||||
|
|
||||||
auto& elf_file_header = elf->file_header_native();
|
|
||||||
for (size_t i = 0; i < elf_file_header.e_phnum; i++)
|
for (size_t i = 0; i < elf_file_header.e_phnum; i++)
|
||||||
{
|
{
|
||||||
auto& elf_program_header = elf->program_header_native(i);
|
auto& elf_program_header = elf.program_header_native(i);
|
||||||
|
|
||||||
switch (elf_program_header.p_type)
|
switch (elf_program_header.p_type)
|
||||||
{
|
{
|
||||||
|
@ -265,7 +274,14 @@ namespace Kernel
|
||||||
break;
|
break;
|
||||||
case LibELF::PT_LOAD:
|
case LibELF::PT_LOAD:
|
||||||
{
|
{
|
||||||
ASSERT(page_table().is_range_free(elf_program_header.p_vaddr, elf_program_header.p_memsz));
|
if (!page_table().is_range_free(elf_program_header.p_vaddr, elf_program_header.p_memsz))
|
||||||
|
{
|
||||||
|
page_table().debug_dump();
|
||||||
|
Kernel::panic("vaddr {8H}-{8H} not free",
|
||||||
|
elf_program_header.p_vaddr,
|
||||||
|
elf_program_header.p_vaddr + elf_program_header.p_memsz
|
||||||
|
);
|
||||||
|
}
|
||||||
uint8_t flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present;
|
uint8_t flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present;
|
||||||
if (elf_program_header.p_flags & LibELF::PF_W)
|
if (elf_program_header.p_flags & LibELF::PF_W)
|
||||||
flags |= PageTable::Flags::ReadWrite;
|
flags |= PageTable::Flags::ReadWrite;
|
||||||
|
@ -277,7 +293,7 @@ namespace Kernel
|
||||||
|
|
||||||
{
|
{
|
||||||
PageTableScope _(page_table());
|
PageTableScope _(page_table());
|
||||||
memcpy((void*)elf_program_header.p_vaddr, elf->data() + elf_program_header.p_offset, elf_program_header.p_filesz);
|
memcpy((void*)elf_program_header.p_vaddr, elf.data() + elf_program_header.p_offset, elf_program_header.p_filesz);
|
||||||
memset((void*)(elf_program_header.p_vaddr + elf_program_header.p_filesz), 0, elf_program_header.p_memsz - elf_program_header.p_filesz);
|
memset((void*)(elf_program_header.p_vaddr + elf_program_header.p_filesz), 0, elf_program_header.p_memsz - elf_program_header.p_filesz);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -286,12 +302,6 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_userspace_entry.entry = elf_file_header.e_entry;
|
|
||||||
|
|
||||||
delete elf;
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<int> Process::open(BAN::StringView path, int flags)
|
BAN::ErrorOr<int> Process::open(BAN::StringView path, int flags)
|
||||||
|
|
Loading…
Reference in New Issue