Kernel: Allow loading PIEs
This is initial work towards implementing dynamic loader and shared library support.
This commit is contained in:
parent
2c520391eb
commit
5121d0d934
|
@ -1,6 +1,7 @@
|
|||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Random.h>
|
||||
#include <LibELF/LoadableELF.h>
|
||||
#include <LibELF/Values.h>
|
||||
|
||||
|
@ -96,10 +97,10 @@ namespace LibELF
|
|||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
if (m_file_header.e_type != ET_EXEC)
|
||||
if (m_file_header.e_type != ET_EXEC && m_file_header.e_type != ET_DYN)
|
||||
{
|
||||
dprintln("Only executable files are supported");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
dprintln("Unsupported file header type {}", m_file_header.e_type);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
if (m_file_header.e_version != EV_CURRENT)
|
||||
|
@ -110,24 +111,36 @@ namespace LibELF
|
|||
|
||||
ASSERT(m_file_header.e_phentsize <= sizeof(ElfNativeProgramHeader));
|
||||
|
||||
TRY(m_program_headers.resize(m_file_header.e_phnum));
|
||||
BAN::Vector<uint8_t> pheader_buffer;
|
||||
TRY(pheader_buffer.resize(m_file_header.e_phnum * m_file_header.e_phentsize));
|
||||
TRY(m_inode->read(m_file_header.e_phoff, BAN::ByteSpan(pheader_buffer.span())));
|
||||
|
||||
const vaddr_t dyn_base = (m_file_header.e_type == ET_DYN) ? 0x40000000 + (Random::get_u32() & 0x3FFFF000) : 0;
|
||||
m_file_header.e_entry += dyn_base;
|
||||
|
||||
for (size_t i = 0; i < m_file_header.e_phnum; i++)
|
||||
{
|
||||
TRY(m_inode->read(m_file_header.e_phoff + m_file_header.e_phentsize * i, BAN::ByteSpan::from(m_program_headers[i])));
|
||||
|
||||
const auto& pheader = m_program_headers[i];
|
||||
if (pheader.p_type != PT_NULL && pheader.p_type != PT_LOAD)
|
||||
{
|
||||
dprintln("Unsupported program header type {}", pheader.p_type);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
const auto& pheader = *reinterpret_cast<ElfNativeProgramHeader*>(pheader_buffer.data() + i * m_file_header.e_phentsize);
|
||||
if (pheader.p_memsz < pheader.p_filesz)
|
||||
{
|
||||
dprintln("Invalid program header");
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
||||
switch (pheader.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
case PT_DYNAMIC:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
TRY(m_program_headers.push_back(pheader));
|
||||
m_program_headers.back().p_vaddr += dyn_base;
|
||||
m_virtual_page_count += BAN::Math::div_round_up<size_t>((pheader.p_vaddr % PAGE_SIZE) + pheader.p_memsz, PAGE_SIZE);
|
||||
break;
|
||||
default:
|
||||
dprintln("Unsupported program header type {}", pheader.p_type);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -142,17 +155,9 @@ namespace LibELF
|
|||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
continue;
|
||||
case PT_LOAD:
|
||||
ASSERT(program_header.p_type == PT_LOAD);
|
||||
if (program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -161,21 +166,11 @@ namespace LibELF
|
|||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
ASSERT(program_header.p_type == PT_LOAD);
|
||||
const vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
const size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
if (!m_page_table.is_range_free(page_vaddr, pages * PAGE_SIZE))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -184,21 +179,12 @@ namespace LibELF
|
|||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
ASSERT(m_page_table.reserve_range(page_vaddr, pages * PAGE_SIZE));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT(program_header.p_type == PT_LOAD);
|
||||
const vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK;
|
||||
const size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz);
|
||||
if (!m_page_table.reserve_range(page_vaddr, pages * PAGE_SIZE))
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
m_loaded = true;
|
||||
}
|
||||
|
||||
|
@ -214,12 +200,8 @@ namespace LibELF
|
|||
{
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
ASSERT(program_header.p_type == PT_LOAD);
|
||||
|
||||
if (!(program_header.p_vaddr <= address && address < program_header.p_vaddr + program_header.p_memsz))
|
||||
continue;
|
||||
|
||||
|
@ -229,8 +211,8 @@ namespace LibELF
|
|||
if (program_header.p_flags & LibELF::PF_X)
|
||||
flags |= PageTable::Flags::Execute;
|
||||
|
||||
vaddr_t vaddr = address & PAGE_ADDR_MASK;
|
||||
paddr_t paddr = Heap::get().take_free_page();
|
||||
const vaddr_t vaddr = address & PAGE_ADDR_MASK;
|
||||
const paddr_t paddr = Heap::get().take_free_page();
|
||||
if (paddr == 0)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
|
||||
|
@ -259,13 +241,8 @@ namespace LibELF
|
|||
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> LoadableELF::clone(Kernel::PageTable& new_page_table)
|
||||
{
|
||||
|
@ -283,12 +260,8 @@ namespace LibELF
|
|||
|
||||
for (const auto& program_header : m_program_headers)
|
||||
{
|
||||
switch (program_header.p_type)
|
||||
{
|
||||
case PT_NULL:
|
||||
break;
|
||||
case PT_LOAD:
|
||||
{
|
||||
ASSERT(program_header.p_type == PT_LOAD);
|
||||
|
||||
if (!(program_header.p_flags & LibELF::PF_W))
|
||||
continue;
|
||||
|
||||
|
@ -317,12 +290,6 @@ namespace LibELF
|
|||
new_page_table.map_page_at(paddr, start + i * PAGE_SIZE, flags);
|
||||
elf->m_physical_page_count++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
return elf;
|
||||
|
|
|
@ -80,6 +80,16 @@ namespace LibELF
|
|||
Elf32Word p_align;
|
||||
};
|
||||
|
||||
struct Elf32Dynamic
|
||||
{
|
||||
Elf32Sword d_tag;
|
||||
union
|
||||
{
|
||||
Elf32Word d_val;
|
||||
Elf32Addr d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
|
||||
using Elf64Addr = uint64_t;
|
||||
using Elf64Off = uint64_t;
|
||||
using Elf64Half = uint16_t;
|
||||
|
@ -155,6 +165,16 @@ namespace LibELF
|
|||
Elf64Xword p_align;
|
||||
};
|
||||
|
||||
struct Elf64Dynamic
|
||||
{
|
||||
Elf64Sxword d_tag;
|
||||
union
|
||||
{
|
||||
Elf64Xword d_val;
|
||||
Elf64Addr d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
|
||||
#if ARCH(i686)
|
||||
using ElfNativeAddr = Elf32Addr;
|
||||
using ElfNativeOff = Elf32Off;
|
||||
|
@ -167,6 +187,7 @@ namespace LibELF
|
|||
using ElfNativeRelocation = Elf32Relocation;
|
||||
using ElfNativeRelocationA = Elf32RelocationA;
|
||||
using ElfNativeProgramHeader = Elf32ProgramHeader;
|
||||
using ElfNativeDynamic = Elf32Dynamic;
|
||||
#elif ARCH(x86_64)
|
||||
using ElfNativeAddr = Elf64Addr;
|
||||
using ElfNativeOff = Elf64Off;
|
||||
|
@ -181,6 +202,7 @@ namespace LibELF
|
|||
using ElfNativeRelocation = Elf64Relocation;
|
||||
using ElfNativeRelocationA = Elf64RelocationA;
|
||||
using ElfNativeProgramHeader = Elf64ProgramHeader;
|
||||
using ElfNativeDynamic = Elf64Dynamic;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue