Implement loading of linked ELF executables.

This took me a couple hours. :^)

The ELF loading code now allocates a single region for the entire
file and creates virtual memory mappings for the sections as needed.

Very nice!
This commit is contained in:
Andreas Kling 2018-10-27 14:56:52 +02:00
parent 99ee6acd69
commit 9a71c7759a
16 changed files with 258 additions and 57 deletions

View file

@ -67,6 +67,7 @@ public:
unsigned size() const { return m_sectionHeader.sh_size; }
unsigned entrySize() const { return m_sectionHeader.sh_entsize; }
unsigned entryCount() const { return size() / entrySize(); }
dword address() const { return m_sectionHeader.sh_addr; }
const char* rawData() const { return m_image.rawData(m_sectionHeader.sh_offset); }
bool isUndefined() const { return m_sectionIndex == SHN_UNDEF; }
const RelocationSection relocations() const;
@ -115,6 +116,7 @@ public:
const Symbol symbol(unsigned) const;
const Section section(unsigned) const;
template<typename F> void forEachSection(F) const;
template<typename F> void forEachSectionOfType(unsigned, F) const;
template<typename F> void forEachSymbol(F) const;
@ -122,6 +124,9 @@ public:
// FIXME: I don't love this API.
const Section lookupSection(const char* name) const;
bool isExecutable() const { return header().e_type == ET_EXEC; }
bool isRelocatable() const { return header().e_type == ET_REL; }
private:
bool parseHeader();
const char* rawData(unsigned offset) const;
@ -142,6 +147,13 @@ private:
unsigned m_stringTableSectionIndex { 0 };
};
template<typename F>
inline void ELFImage::forEachSection(F func) const
{
for (unsigned i = 0; i < sectionCount(); ++i)
func(section(i));
}
template<typename F>
inline void ELFImage::forEachSectionOfType(unsigned type, F func) const
{

View file

@ -40,13 +40,26 @@ bool ELFLoader::layout()
kprintf("[ELFLoader] Layout\n");
#endif
bool failed = false;
dword highestOffset = 0;
dword sizeNeeded = 0;
m_image->forEachSection([&] (auto& section) {
if (section.offset() > highestOffset) {
highestOffset = section.offset();
sizeNeeded = highestOffset + section.size();
}
});
#ifdef ELFLOADER_DEBUG
kprintf("[ELFLoader] Highest section offset: %u, Size needed: %u\n", highestOffset, sizeNeeded);
#endif
m_execSpace.allocateUniverse(sizeNeeded);
m_image->forEachSectionOfType(SHT_PROGBITS, [this, &failed] (const ELFImage::Section& section) {
#ifdef ELFLOADER_DEBUG
kprintf("[ELFLoader] Allocating progbits section: %s\n", section.name());
#endif
if (!section.size())
return true;
char* ptr = m_execSpace.allocateArea(section.name(), section.size());
char* ptr = m_execSpace.allocateArea(section.name(), section.size(), section.offset(), LinearAddress(section.address()));
if (!ptr) {
kprintf("ELFLoader: failed to allocate section '%s'\n", section.name());
failed = true;
@ -62,7 +75,7 @@ bool ELFLoader::layout()
#endif
if (!section.size())
return true;
char* ptr = m_execSpace.allocateArea(section.name(), section.size());
char* ptr = m_execSpace.allocateArea(section.name(), section.size(), section.offset(), LinearAddress(section.address()));
if (!ptr) {
kprintf("ELFLoader: failed to allocate section '%s'\n", section.name());
failed = true;
@ -163,8 +176,16 @@ void ELFLoader::exportSymbols()
#ifdef ELFLOADER_DEBUG
kprintf("symbol: %u, type=%u, name=%s, section=%u\n", symbol.index(), symbol.type(), symbol.name(), symbol.sectionIndex());
#endif
if (symbol.type() == STT_FUNC)
m_execSpace.addSymbol(symbol.name(), areaForSection(symbol.section()) + symbol.value(), symbol.size());
if (symbol.type() == STT_FUNC) {
char* ptr;
if (m_image->isExecutable())
ptr = (char*)symbol.value();
else if (m_image->isRelocatable())
ptr = areaForSection(symbol.section()) + symbol.value();
else
ASSERT_NOT_REACHED();
m_execSpace.addSymbol(symbol.name(), ptr, symbol.size());
}
// FIXME: What about other symbol types?
return true;
});

View file

@ -101,19 +101,31 @@ char* ExecSpace::symbolPtr(const char* name)
return nullptr;
}
char* ExecSpace::allocateArea(String&& name, unsigned size)
void ExecSpace::allocateUniverse(size_t size)
{
char* ptr;
ASSERT(!m_universe);
if (hookableAlloc)
ptr = static_cast<char*>(hookableAlloc(name, size));
m_universe = static_cast<char*>(hookableAlloc("elf-sec", size));
else
ptr = static_cast<char*>(kmalloc(size));
if (size)
ASSERT(ptr);
m_areas.append(make<Area>(move(name), ptr, size));
m_universe = static_cast<char*>(kmalloc(size));
}
char* ExecSpace::allocateArea(String&& name, unsigned size, dword offset, LinearAddress laddr)
{
ASSERT(m_universe);
char* ptr = m_universe + offset;
m_areas.append(make<Area>(move(name), offset, ptr, size, laddr));
return ptr;
}
void ExecSpace::forEachArea(Function<void(const String& name, dword offset, size_t size, LinearAddress)> callback)
{
for (auto& a : m_areas) {
auto& area = *a;
callback(area.name, area.offset, area.size, area.laddr);
}
}
void ExecSpace::addSymbol(String&& name, char* ptr, unsigned size)
{
m_symbols.set(move(name), { ptr, size });

View file

@ -11,16 +11,20 @@ class ELFLoader;
class ExecSpace {
public:
struct Area {
Area(String&& n, char* m, unsigned s)
Area(String&& n, dword o, char* m, unsigned s, LinearAddress l)
: name(move(n))
, offset(o)
, memory(m)
, size(s)
, laddr(l)
{
}
String name;
dword offset { 0 };
char* memory { 0 };
unsigned size { 0 };
LinearAddress laddr;
};
struct PtrAndSize {
@ -48,13 +52,18 @@ public:
char* symbolPtr(const char* name);
char* allocateArea(String&& name, unsigned size);
char* allocateArea(String&& name, unsigned size, dword offset, LinearAddress);
void addSymbol(String&& name, char* ptr, unsigned size);
void allocateUniverse(size_t);
void forEachArea(Function<void(const String& name, dword offset, size_t size, LinearAddress)>);
private:
void initializeBuiltins();
Vector<OwnPtr<Area>> m_areas;
HashMap<String, PtrAndSize> m_symbols;
char* m_universe { nullptr };
};

View file

@ -55,8 +55,7 @@ ARCH_FLAGS =
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
KERNEL_FLAGS = -ffreestanding -fno-stack-protector -fno-ident
WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings
FLAVOR_FLAGS = -mregparm=3 -march=i386 -m32 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fmerge-all-constants -fno-unroll-loops -falign-functions=1 -falign-jumps=1 -falign-loops=1 -fno-pie -fno-pic
#FLAVOR_FLAGS = -mregparm=3 -march=i386 -m32 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections
FLAVOR_FLAGS = -mregparm=3 -march=i386 -m32 -fno-exceptions -fno-rtti -fmerge-all-constants -fno-unroll-loops -fno-pie -fno-pic
OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables
INCLUDE_FLAGS = -I.. -I.
@ -65,11 +64,10 @@ DEFINES = -DSERENITY -DSANITIZE_PTRS
CXXFLAGS = $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(KERNEL_FLAGS) $(FLAVOR_FLAGS) $(ARCH_FLAGS) $(STANDARD_FLAGS) $(INCLUDE_FLAGS) $(DEFINES)
#CXX = /usr/local/gcc-4.8.1-for-linux64/bin/x86_64-pc-linux-g++
#LD = /usr/local/gcc-4.8.1-for-linux64/bin/x86_64-pc-linux-ld
CXX = g++
CXX = g++-8
LD = ld
LDFLAGS = -T linker.ld --strip-debug -melf_i386 --gc-sections --build-id=none -z norelro -z now
all: $(KERNEL) $(IMAGE) kernel.map
kernel.map: kernel

View file

@ -8,7 +8,7 @@
static MemoryManager* s_the;
MemoryManager& MemoryManager::the()
MemoryManager& MM
{
return *s_the;
}
@ -43,8 +43,8 @@ void MemoryManager::initializePaging()
identityMap(LinearAddress(4096), 4 * MB);
// Put pages between 4MB and 16MB in the page freelist.
for (size_t i = (4 * MB) + 1024; i < (16 * MB); i += PAGE_SIZE) {
// Put pages between 4MB and 8MB in the page freelist.
for (size_t i = (4 * MB) + PAGE_SIZE; i < (8 * MB); i += PAGE_SIZE) {
m_freePages.append(PhysicalAddress(i));
}
@ -56,6 +56,14 @@ void MemoryManager::initializePaging()
);
}
void* MemoryManager::allocatePageTable()
{
auto ppages = allocatePhysicalPages(1);
dword address = ppages[0].get();
identityMap(LinearAddress(address), 4096);
return (void*)address;
}
auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
{
ASSERT_INTERRUPTS_DISABLED();
@ -76,8 +84,13 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
pde.setPresent(true);
pde.setWritable(true);
} else {
// FIXME: We need an allocator!
ASSERT_NOT_REACHED();
auto* pageTable = allocatePageTable();
kprintf("allocated page table %u (for laddr=%p) at %p\n", pageDirectoryIndex, linearAddress.get(), pageTable);
memset(pageTable, 0, 4096);
pde.setPageTableBase((dword)pageTable);
pde.setUserAllowed(true);
pde.setPresent(true);
pde.setWritable(true);
}
}
return PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
@ -190,7 +203,27 @@ bool MemoryManager::unmapRegion(Task& task, Task::Region& region)
pte.setWritable(false);
pte.setUserAllowed(false);
flushTLB(laddr);
// kprintf("MM: >> Unmapped L%x => P%x <<\n", laddr, zone.m_pages[i].get());
//kprintf("MM: >> Unmapped L%x => P%x <<\n", laddr, zone.m_pages[i].get());
}
return true;
}
bool MemoryManager::unmapSubregion(Task& task, Task::Subregion& subregion)
{
InterruptDisabler disabler;
auto& region = *subregion.region;
auto& zone = *region.zone;
size_t numPages = subregion.size / 4096;
ASSERT(numPages);
for (size_t i = 0; i < numPages; ++i) {
auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
auto pte = ensurePTE(laddr);
pte.setPhysicalPageBase(0);
pte.setPresent(false);
pte.setWritable(false);
pte.setUserAllowed(false);
flushTLB(laddr);
//kprintf("MM: >> Unmapped subregion %s L%x => P%x <<\n", subregion.name.characters(), laddr, zone.m_pages[i].get());
}
return true;
}
@ -202,6 +235,31 @@ bool MemoryManager::unmapRegionsForTask(Task& task)
if (!unmapRegion(task, *region))
return false;
}
for (auto& subregion : task.m_subregions) {
if (!unmapSubregion(task, *subregion))
return false;
}
return true;
}
bool MemoryManager::mapSubregion(Task& task, Task::Subregion& subregion)
{
InterruptDisabler disabler;
auto& region = *subregion.region;
auto& zone = *region.zone;
size_t firstPage = subregion.offset / 4096;
size_t numPages = subregion.size / 4096;
ASSERT(numPages);
for (size_t i = 0; i < numPages; ++i) {
auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
auto pte = ensurePTE(laddr);
pte.setPhysicalPageBase(zone.m_pages[firstPage + i].get());
pte.setPresent(true);
pte.setWritable(true);
pte.setUserAllowed(!task.isRing0());
flushTLB(laddr);
//kprintf("MM: >> Mapped subregion %s L%x => P%x (%u into region)<<\n", subregion.name.characters(), laddr, zone.m_pages[firstPage + i].get(), subregion.offset);
}
return true;
}
@ -229,6 +287,10 @@ bool MemoryManager::mapRegionsForTask(Task& task)
if (!mapRegion(task, *region))
return false;
}
for (auto& subregion : task.m_subregions) {
if (!mapSubregion(task, *subregion))
return false;
}
return true;
}
@ -243,7 +305,7 @@ bool copyToZone(Zone& zone, const void* data, size_t size)
auto* dataptr = (const byte*)data;
size_t remaining = size;
for (size_t i = 0; i < zone.m_pages.size(); ++i) {
byte* dest = MemoryManager::the().quickMapOnePage(zone.m_pages[i]);
byte* dest = MM.quickMapOnePage(zone.m_pages[i]);
kprintf("memcpy(%p, %p, %u)\n", dest, dataptr, min(PAGE_SIZE, remaining));
memcpy(dest, dataptr, min(PAGE_SIZE, remaining));
dataptr += PAGE_SIZE;

View file

@ -35,6 +35,8 @@ private:
bool copyToZone(Zone&, const void* data, size_t);
#define MM MemoryManager::the()
class MemoryManager {
public:
static MemoryManager& the() PURE;
@ -50,6 +52,11 @@ public:
// HACK: don't use this jeez :(
byte* quickMapOnePage(PhysicalAddress);
bool mapSubregion(Task&, Task::Subregion&);
bool unmapSubregion(Task&, Task::Subregion&);
bool mapSubregionsForTask(Task&);
bool unmapSubregionsForTask(Task&);
bool mapRegion(Task&, Task::Region&);
bool unmapRegion(Task&, Task::Region&);
bool mapRegionsForTask(Task&);
@ -63,6 +70,8 @@ private:
void flushEntireTLB();
void flushTLB(LinearAddress);
void* allocatePageTable();
void protectMap(LinearAddress, size_t length);
void identityMap(LinearAddress, size_t length);

View file

@ -49,8 +49,8 @@ ByteBuffer procfs$pid_stack(Task& task)
{
InterruptDisabler disabler;
if (current != &task) {
MemoryManager::the().unmapRegionsForTask(*current);
MemoryManager::the().mapRegionsForTask(task);
MM.unmapRegionsForTask(*current);
MM.mapRegionsForTask(task);
}
struct RecognizedSymbol {
dword address;
@ -78,8 +78,8 @@ ByteBuffer procfs$pid_stack(Task& task)
}
buffer.trim(bufptr - (char*)buffer.pointer());
if (current != &task) {
MemoryManager::the().unmapRegionsForTask(task);
MemoryManager::the().mapRegionsForTask(*current);
MM.unmapRegionsForTask(task);
MM.mapRegionsForTask(*current);
}
return buffer;
}

View file

@ -13,6 +13,7 @@
#include "i8253.h"
#include "RTC.h"
#include "ProcFileSystem.h"
#include <AK/StdLib.h>
//#define DEBUG_IO
//#define TASK_DEBUG
@ -132,9 +133,9 @@ Task::Region* Task::allocateRegion(size_t size, String&& name)
{
// FIXME: This needs sanity checks. What if this overlaps existing regions?
auto zone = MemoryManager::the().createZone(size);
auto zone = MM.createZone(size);
ASSERT(zone);
m_regions.append(make<Region>(m_nextRegion, size, move(zone), move(name)));
m_regions.append(adopt(*new Region(m_nextRegion, size, move(zone), move(name))));
m_nextRegion = m_nextRegion.offset(size).offset(16384);
return m_regions.last().ptr();
}
@ -144,7 +145,7 @@ bool Task::deallocateRegion(Region& region)
for (size_t i = 0; i < m_regions.size(); ++i) {
if (m_regions[i].ptr() == &region) {
// FIXME: This seems racy.
MemoryManager::the().unmapRegion(*this, region);
MM.unmapRegion(*this, region);
m_regions.remove(i);
return true;
}
@ -168,7 +169,7 @@ void* Task::sys$mmap(void* addr, size_t size)
auto* region = allocateRegion(size, "mmap");
if (!region)
return (void*)-1;
MemoryManager::the().mapRegion(*this, *region);
MM.mapRegion(*this, *region);
return (void*)region->linearAddress.get();
}
@ -250,39 +251,55 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
t->m_arguments = move(taskArguments);
ExecSpace space;
Region* region = nullptr;
space.hookableAlloc = [&] (const String& name, size_t size) {
if (!size)
return (void*)nullptr;
size = ((size / 4096) + 1) * 4096;
Region* region = t->allocateRegion(size, String(name));
region = t->allocateRegion(size, String(name));
ASSERT(region);
MemoryManager::the().mapRegion(*t, *region);
MM.mapRegion(*t, *region);
return (void*)region->linearAddress.asPtr();
};
bool success = space.loadELF(move(elfData));
if (!success) {
// FIXME: This is ugly. If we need to do this, it should be at a different level.
MemoryManager::the().unmapRegionsForTask(*t);
MemoryManager::the().mapRegionsForTask(*current);
MM.unmapRegionsForTask(*t);
MM.mapRegionsForTask(*current);
delete t;
kprintf("Failure loading ELF %s\n", path.characters());
error = -ENOEXEC;
return nullptr;
}
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);
t->m_subregions.append(make<Subregion>(*region, roundedOffset, roundedSize, roundedLaddr, String(name)));
#ifdef SUBREGION_DEBUG
kprintf(" req subregion %s (offset: %u, size: %u) @ %p\n", name.characters(), offset, size, laddr.get());
kprintf("actual subregion %s (offset: %u, size: %u) @ %p\n", name.characters(), roundedOffset, roundedSize, roundedLaddr.get());
#endif
MM.mapSubregion(*t, *t->m_subregions.last());
});
t->m_tss.eip = (dword)space.symbolPtr("_start");
if (!t->m_tss.eip) {
// FIXME: This is ugly. If we need to do this, it should be at a different level.
MemoryManager::the().unmapRegionsForTask(*t);
MemoryManager::the().mapRegionsForTask(*current);
MM.unmapRegionsForTask(*t);
MM.mapRegionsForTask(*current);
delete t;
error = -ENOEXEC;
return nullptr;
}
// FIXME: This is ugly. If we need to do this, it should be at a different level.
MemoryManager::the().unmapRegionsForTask(*t);
MemoryManager::the().mapRegionsForTask(*current);
MM.unmapRegionsForTask(*t);
MM.mapRegionsForTask(*current);
s_tasks->prepend(t);
system.nprocess++;
@ -299,7 +316,7 @@ int Task::sys$get_arguments(int* argc, char*** argv)
auto* region = allocateRegion(4096, "argv");
if (!region)
return -ENOMEM;
MemoryManager::the().mapRegion(*this, *region);
MM.mapRegion(*this, *region);
char* argpage = (char*)region->linearAddress.get();
*argc = m_arguments.size();
*argv = (char**)argpage;
@ -380,7 +397,7 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring)
m_tss.ss = ss;
m_tss.cs = cs;
m_tss.cr3 = MemoryManager::the().pageDirectoryBase().get();
m_tss.cr3 = MM.pageDirectoryBase().get();
if (isRing0()) {
// FIXME: This memory is leaked.
@ -435,6 +452,18 @@ void Task::dumpRegions()
region->size,
region->name.characters());
}
kprintf("Task %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 Task::sys$exit(int status)
@ -446,7 +475,7 @@ void Task::sys$exit(int status)
setState(Exiting);
MemoryManager::the().unmapRegionsForTask(*this);
MM.unmapRegionsForTask(*this);
s_tasks->remove(this);
@ -474,7 +503,7 @@ void Task::taskDidCrash(Task* crashedTask)
s_tasks->remove(crashedTask);
MemoryManager::the().unmapRegionsForTask(*crashedTask);
MM.unmapRegionsForTask(*crashedTask);
if (!scheduleNewTask()) {
kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
@ -630,11 +659,11 @@ static bool contextSwitch(Task* t)
if (current->state() == Task::Running)
current->setState(Task::Runnable);
bool success = MemoryManager::the().unmapRegionsForTask(*current);
bool success = MM.unmapRegionsForTask(*current);
ASSERT(success);
}
bool success = MemoryManager::the().mapRegionsForTask(*t);
bool success = MM.mapRegionsForTask(*t);
ASSERT(success);
current = t;
@ -911,6 +940,20 @@ Task::Region::~Region()
{
}
Task::Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
: region(r)
, offset(o)
, size(s)
, linearAddress(l)
, name(move(n))
{
}
Task::Subregion::~Subregion()
{
}
bool Task::isValidAddressForKernel(LinearAddress laddr) const
{
InterruptDisabler disabler;
@ -928,5 +971,9 @@ bool Task::isValidAddressForUser(LinearAddress laddr) const
if (laddr >= region->linearAddress && laddr < region->linearAddress.offset(region->size))
return true;
}
for (auto& subregion: m_subregions) {
if (laddr >= subregion->linearAddress && laddr < subregion->linearAddress.offset(subregion->size))
return true;
}
return false;
}

View file

@ -112,7 +112,7 @@ public:
static void taskDidCrash(Task*);
size_t regionCount() const { return m_regions.size(); }
const Vector<OwnPtr<Region>>& regions() const { return m_regions; }
const Vector<RetainPtr<Region>>& regions() const { return m_regions; }
void dumpRegions();
void didSchedule() { ++m_timesScheduled; }
@ -166,7 +166,7 @@ private:
RetainPtr<VirtualFileSystem::Node> m_cwd;
struct Region {
struct Region : public Retainable<Region> {
Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&);
~Region();
LinearAddress linearAddress;
@ -174,12 +174,26 @@ private:
RetainPtr<Zone> zone;
String name;
};
struct Subregion {
Subregion(Region&, dword offset, size_t, LinearAddress, String&& name);
~Subregion();
RetainPtr<Region> region;
dword offset;
size_t size { 0 };
LinearAddress linearAddress;
String name;
};
Region* allocateRegion(size_t, String&& name);
Region* allocateRegion(size_t, String&& name, LinearAddress);
bool deallocateRegion(Region& region);
Region* regionFromRange(LinearAddress, size_t);
Vector<OwnPtr<Region>> m_regions;
Vector<RetainPtr<Region>> m_regions;
Vector<OwnPtr<Subregion>> m_subregions;
// FIXME: Implement some kind of ASLR?
LinearAddress m_nextRegion;

View file

@ -218,10 +218,22 @@ void exception_14_handler()
kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi);
byte* codeptr = (byte*)regs.eip;
kprintf("code: %b %b %b %b %b %b %b %b\n",
codeptr[0],
codeptr[1],
codeptr[2],
codeptr[3],
codeptr[4],
codeptr[5],
codeptr[6],
codeptr[7]
);
if (current->isRing0())
HANG;
auto response = MemoryManager::the().handlePageFault(PageFault(exception_code, LinearAddress(faultAddress)));
auto response = MM.handlePageFault(PageFault(exception_code, LinearAddress(faultAddress)));
if (response == PageFaultResponse::ShouldCrash) {
kprintf("Crashing after unresolved page fault\n");

View file

@ -80,6 +80,8 @@ public:
LinearAddress() { }
explicit LinearAddress(dword address) : m_address(address) { }
bool isNull() const { return m_address == 0; }
LinearAddress offset(dword o) const { return LinearAddress(m_address + o); }
dword get() const { return m_address; }
void set(dword address) { m_address = address; }

View file

@ -22,7 +22,7 @@ INCLUDE_FLAGS = -I.. -I.
DEFINES = -DSERENITY -DSANITIZE_PTRS
CXXFLAGS = $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(LIBC_FLAGS) $(FLAVOR_FLAGS) $(ARCH_FLAGS) $(STANDARD_FLAGS) $(INCLUDE_FLAGS) $(DEFINES)
CXX = g++
CXX = g++-8
LD = ld
AR = ar
LDFLAGS = -T linker.ld --strip-debug -melf_i386 --gc-sections --build-id=none -z norelro -z now

View file

@ -7,7 +7,7 @@
#define ALWAYS_INLINE __attribute__ ((always_inline))
static const char h[] = { '0','1','2','3','4','5','6','7', '8','9','a','b','c','d','e','f' };
static constexpr const char* h = "0123456789abcdef";
template<typename PutChFunc>
ALWAYS_INLINE int printHex(PutChFunc putch, char*& bufptr, dword number, byte fields)

View file

@ -30,17 +30,17 @@ ARCH_FLAGS =
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
USERLAND_FLAGS = -ffreestanding -fno-stack-protector -fno-ident
WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings
FLAVOR_FLAGS = -fomit-frame-pointer -mregparm=3 -march=i386 -m32 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fmerge-all-constants -fno-unroll-loops -falign-functions=1 -falign-jumps=1 -falign-loops=1 -fno-pie -fno-pic
FLAVOR_FLAGS = -march=i386 -mregparm=3 -m32 -fno-exceptions -fno-rtti -fmerge-all-constants -fno-unroll-loops -fno-pie -fno-pic
OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables
INCLUDE_FLAGS = -I.. -I.
DEFINES = -DSERENITY -DSANITIZE_PTRS -DUSERLAND
CXXFLAGS = $(WARNING_FLAGS) $(OPTIMIZATION_FLAGS) $(USERLAND_FLAGS) $(FLAVOR_FLAGS) $(ARCH_FLAGS) $(STANDARD_FLAGS) $(INCLUDE_FLAGS) $(DEFINES)
CXX = g++
CXX = g++-8
LD = ld
AR = ar
LDFLAGS = -r -static --strip-debug -melf_i386 --build-id=none -z norelro -z now -e _start
LDFLAGS = -static --strip-debug -melf_i386 --build-id=none -z norelro -z now -e _start --gc-sections
all: $(OBJS) $(APPS)

View file

@ -1,21 +1,24 @@
#include <LibC/stdio.h>
#include <LibC/unistd.h>
#include <LibC/dirent.h>
#include <LibC/errno.h>
#include <LibC/string.h>
int main(int c, char** v)
{
DIR* dirp = opendir(".");
if (!dirp) {
printf("opendir failed :(\n");
perror("opendir failed");
return 1;
}
char pathbuf[256];
while (auto* de = readdir(dirp)) {
sprintf(pathbuf, "%s", de->d_name);
stat st;
int rc = lstat(pathbuf, &st);
if (rc == -1) {
printf("Failed to stat '%s'\n", pathbuf);
printf("lstat(%s) failed: %s\n", pathbuf, strerror(errno));
return 2;
}