mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-27 14:58:46 +00:00
Use ELF program headers to load executables smarter.
This turned out way better than the old code. ELF loading is now quite straightforward, and we don't need the weird concept of subregions anymore. Next step is to respect the is_writable flag.
This commit is contained in:
parent
dd060d0fa8
commit
aa6d06b47e
Notes:
sideshowbarker
2024-07-19 18:34:04 +09:00
Author: https://github.com/awesomekling
Commit: aa6d06b47e
9 changed files with 42 additions and 198 deletions
|
@ -134,19 +134,26 @@ Vector<Process*> Process::allProcesses()
|
|||
return processes;
|
||||
}
|
||||
|
||||
Region* Process::allocateRegion(size_t size, String&& name)
|
||||
Region* Process::allocate_region(LinearAddress laddr, size_t size, String&& name, bool is_readable, bool is_writable)
|
||||
{
|
||||
// FIXME: This needs sanity checks. What if this overlaps existing regions?
|
||||
if (laddr.is_null()) {
|
||||
laddr = m_nextRegion;
|
||||
m_nextRegion = m_nextRegion.offset(size).offset(PAGE_SIZE);
|
||||
}
|
||||
|
||||
laddr.mask(0xfffff000);
|
||||
|
||||
auto zone = MM.createZone(size);
|
||||
ASSERT(zone);
|
||||
m_regions.append(adopt(*new Region(m_nextRegion, size, move(zone), move(name))));
|
||||
m_nextRegion = m_nextRegion.offset(size).offset(16384);
|
||||
|
||||
m_regions.append(adopt(*new Region(laddr, size, move(zone), move(name))));
|
||||
|
||||
MM.mapRegion(*this, *m_regions.last());
|
||||
return m_regions.last().ptr();
|
||||
}
|
||||
|
||||
bool Process::deallocateRegion(Region& region)
|
||||
bool Process::deallocate_region(Region& region)
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
for (size_t i = 0; i < m_regions.size(); ++i) {
|
||||
|
@ -183,7 +190,7 @@ void* Process::sys$mmap(void* addr, size_t size)
|
|||
InterruptDisabler disabler;
|
||||
// FIXME: Implement mapping at a client-preferred address.
|
||||
ASSERT(addr == nullptr);
|
||||
auto* region = allocateRegion(size, "mmap");
|
||||
auto* region = allocate_region(LinearAddress(), size, "mmap");
|
||||
if (!region)
|
||||
return (void*)-1;
|
||||
MM.mapRegion(*this, *region);
|
||||
|
@ -196,7 +203,7 @@ int Process::sys$munmap(void* addr, size_t size)
|
|||
auto* region = regionFromRange(LinearAddress((dword)addr), size);
|
||||
if (!region)
|
||||
return -1;
|
||||
if (!deallocateRegion(*region))
|
||||
if (!deallocate_region(*region))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -229,17 +236,6 @@ Process* Process::fork(RegisterDump& regs)
|
|||
dbgprintf("fork: cloning Region{%p}\n", region.ptr());
|
||||
#endif
|
||||
auto cloned_region = region->clone();
|
||||
// FIXME: Move subregions into Region?
|
||||
for (auto& subregion : m_subregions) {
|
||||
if (subregion->region.ptr() != region.ptr())
|
||||
continue;
|
||||
#ifdef FORK_DEBUG
|
||||
dbgprintf("fork: cloning Subregion{%p}\n", subregion.ptr());
|
||||
#endif
|
||||
auto cloned_subregion = make<Subregion>(*cloned_region, subregion->offset, subregion->size, subregion->linearAddress, String(subregion->name));
|
||||
child->m_subregions.append(move(cloned_subregion));
|
||||
MM.mapSubregion(*child, *child->m_subregions.last());
|
||||
}
|
||||
child->m_regions.append(move(cloned_region));
|
||||
MM.mapRegion(*child, *child->m_regions.last());
|
||||
}
|
||||
|
@ -312,18 +308,16 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
|
|||
InterruptDisabler disabler;
|
||||
// Okay, here comes the sleight of hand, pay close attention..
|
||||
auto old_regions = move(m_regions);
|
||||
auto old_subregions = move(m_subregions);
|
||||
old_page_directory = m_page_directory;
|
||||
new_page_directory = reinterpret_cast<PageDirectory*>(kmalloc_page_aligned(sizeof(PageDirectory)));
|
||||
MM.populate_page_directory(*new_page_directory);
|
||||
m_page_directory = new_page_directory;
|
||||
MM.enter_process_paging_scope(*this);
|
||||
space.hookableAlloc = [&] (const String& name, size_t size) {
|
||||
if (!size)
|
||||
return (void*)nullptr;
|
||||
space.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 = allocateRegion(size, String(name));
|
||||
return (void*)region->linearAddress.get();
|
||||
region = allocate_region(laddr, size, String(name), is_readable, is_writable);
|
||||
return laddr.asPtr();
|
||||
};
|
||||
bool success = space.loadELF(move(elfData));
|
||||
if (!success) {
|
||||
|
@ -331,29 +325,16 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
|
|||
MM.enter_process_paging_scope(*this);
|
||||
MM.release_page_directory(*new_page_directory);
|
||||
m_regions = move(old_regions);
|
||||
m_subregions = move(old_subregions);
|
||||
kprintf("sys$execve: Failure loading %s\n", path.characters());
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
space.forEachArea([&] (const String& name, dword offset, size_t size, LinearAddress laddr) {
|
||||
if (laddr.isNull())
|
||||
return;
|
||||
dword roundedOffset = offset & 0xfffff000;
|
||||
size_t roundedSize = 4096 * ceilDiv((offset - roundedOffset) + size, 4096u);
|
||||
LinearAddress roundedLaddr = laddr;
|
||||
roundedLaddr.mask(0xfffff000);
|
||||
m_subregions.append(make<Subregion>(*region, roundedOffset, roundedSize, roundedLaddr, String(name)));
|
||||
MM.mapSubregion(*this, *m_subregions.last());
|
||||
});
|
||||
|
||||
entry_eip = (dword)space.symbolPtr("_start");
|
||||
if (!entry_eip) {
|
||||
m_page_directory = old_page_directory;
|
||||
MM.enter_process_paging_scope(*this);
|
||||
MM.release_page_directory(*new_page_directory);
|
||||
m_regions = move(old_regions);
|
||||
m_subregions = move(old_subregions);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +356,7 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
|
|||
m_tss.fs = 0x23;
|
||||
m_tss.ss = 0x23;
|
||||
m_tss.cr3 = (dword)m_page_directory;
|
||||
auto* stack_region = allocateRegion(defaultStackSize, "stack");
|
||||
auto* stack_region = allocate_region(LinearAddress(), defaultStackSize, "stack");
|
||||
ASSERT(stack_region);
|
||||
m_stackTop3 = stack_region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
|
||||
m_tss.esp = m_stackTop3;
|
||||
|
@ -512,7 +493,7 @@ Process* Process::create_user_process(const String& path, uid_t uid, gid_t gid,
|
|||
|
||||
int Process::sys$get_environment(char*** environ)
|
||||
{
|
||||
auto* region = allocateRegion(4096, "environ");
|
||||
auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "environ");
|
||||
if (!region)
|
||||
return -ENOMEM;
|
||||
MM.mapRegion(*this, *region);
|
||||
|
@ -531,7 +512,7 @@ int Process::sys$get_environment(char*** environ)
|
|||
|
||||
int Process::sys$get_arguments(int* argc, char*** argv)
|
||||
{
|
||||
auto* region = allocateRegion(4096, "argv");
|
||||
auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "argv");
|
||||
if (!region)
|
||||
return -ENOMEM;
|
||||
MM.mapRegion(*this, *region);
|
||||
|
@ -656,7 +637,7 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel
|
|||
if (fork_parent) {
|
||||
m_stackTop3 = fork_parent->m_stackTop3;
|
||||
} else {
|
||||
auto* region = allocateRegion(defaultStackSize, "stack");
|
||||
auto* region = allocate_region(LinearAddress(), defaultStackSize, "stack");
|
||||
ASSERT(region);
|
||||
m_stackTop3 = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
|
||||
m_tss.esp = m_stackTop3;
|
||||
|
@ -703,18 +684,6 @@ void Process::dumpRegions()
|
|||
region->size,
|
||||
region->name.characters());
|
||||
}
|
||||
|
||||
kprintf("Process %s(%u) subregions:\n", name().characters(), pid());
|
||||
kprintf("REGION OFFSET BEGIN END SIZE NAME\n");
|
||||
for (auto& subregion : m_subregions) {
|
||||
kprintf("%x %x %x -- %x %x %s\n",
|
||||
subregion->region->linearAddress.get(),
|
||||
subregion->offset,
|
||||
subregion->linearAddress.get(),
|
||||
subregion->linearAddress.offset(subregion->size - 1).get(),
|
||||
subregion->size,
|
||||
subregion->name.characters());
|
||||
}
|
||||
}
|
||||
|
||||
void Process::notify_waiters(pid_t waitee, int exit_status, int signal)
|
||||
|
@ -1303,19 +1272,6 @@ Region::~Region()
|
|||
{
|
||||
}
|
||||
|
||||
Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
|
||||
: region(r)
|
||||
, offset(o)
|
||||
, size(s)
|
||||
, linearAddress(l)
|
||||
, name(move(n))
|
||||
{
|
||||
}
|
||||
|
||||
Subregion::~Subregion()
|
||||
{
|
||||
}
|
||||
|
||||
bool Process::isValidAddressForKernel(LinearAddress laddr) const
|
||||
{
|
||||
// We check extra carefully here since the first 4MB of the address space is identity-mapped.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue