diff options
-rw-r--r-- | ELFLoader/ELFImage.h | 12 | ||||
-rw-r--r-- | ELFLoader/ELFLoader.cpp | 29 | ||||
-rw-r--r-- | ELFLoader/ExecSpace.cpp | 26 | ||||
-rw-r--r-- | ELFLoader/ExecSpace.h | 13 | ||||
-rw-r--r-- | Kernel/Makefile | 6 | ||||
-rw-r--r-- | Kernel/MemoryManager.cpp | 76 | ||||
-rw-r--r-- | Kernel/MemoryManager.h | 9 | ||||
-rw-r--r-- | Kernel/ProcFileSystem.cpp | 8 | ||||
-rw-r--r-- | Kernel/Task.cpp | 83 | ||||
-rw-r--r-- | Kernel/Task.h | 20 | ||||
-rw-r--r-- | Kernel/i386.cpp | 14 | ||||
-rw-r--r-- | Kernel/types.h | 2 | ||||
-rw-r--r-- | LibC/Makefile | 2 | ||||
-rw-r--r-- | LibC/stdio.cpp | 2 | ||||
-rw-r--r-- | Userland/Makefile | 6 | ||||
-rw-r--r-- | Userland/ls.cpp | 7 |
16 files changed, 258 insertions, 57 deletions
diff --git a/ELFLoader/ELFImage.h b/ELFLoader/ELFImage.h index ff0715ee21..5181b637e2 100644 --- a/ELFLoader/ELFImage.h +++ b/ELFLoader/ELFImage.h @@ -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; @@ -143,6 +148,13 @@ private: }; 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 { for (unsigned i = 0; i < sectionCount(); ++i) { diff --git a/ELFLoader/ELFLoader.cpp b/ELFLoader/ELFLoader.cpp index 35e8020405..a4b4614e16 100644 --- a/ELFLoader/ELFLoader.cpp +++ b/ELFLoader/ELFLoader.cpp @@ -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; }); diff --git a/ELFLoader/ExecSpace.cpp b/ELFLoader/ExecSpace.cpp index 67c69bba20..9a751495e0 100644 --- a/ELFLoader/ExecSpace.cpp +++ b/ELFLoader/ExecSpace.cpp @@ -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 }); diff --git a/ELFLoader/ExecSpace.h b/ELFLoader/ExecSpace.h index 432bf0a82e..b08640efb7 100644 --- a/ELFLoader/ExecSpace.h +++ b/ELFLoader/ExecSpace.h @@ -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 }; }; diff --git a/Kernel/Makefile b/Kernel/Makefile index 982b9300da..b93376664a 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -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 diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index e8477491bb..0f32eb9679 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -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; diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index d2873c0d79..0c88607433 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -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); diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index a763549e11..6596ac2dd8 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -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; } diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index aa96881258..72293365c1 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -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() == ®ion) { // 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; } diff --git a/Kernel/Task.h b/Kernel/Task.h index 495dbde41c..c683f50088 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -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; diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index 7bca2f0b93..5a771a12c9 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -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"); diff --git a/Kernel/types.h b/Kernel/types.h index 8f90b215a7..99fa7c989a 100644 --- a/Kernel/types.h +++ b/Kernel/types.h @@ -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; } diff --git a/LibC/Makefile b/LibC/Makefile index 956e01894a..d0ab3ef533 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -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 diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index 5ddb06b757..3448659fab 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -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) diff --git a/Userland/Makefile b/Userland/Makefile index 9798053d6d..d7b2d408b9 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -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) diff --git a/Userland/ls.cpp b/Userland/ls.cpp index 4847e5ede9..b37b3f07d3 100644 --- a/Userland/ls.cpp +++ b/Userland/ls.cpp @@ -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; } |