summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ELFLoader/ELFImage.h12
-rw-r--r--ELFLoader/ELFLoader.cpp29
-rw-r--r--ELFLoader/ExecSpace.cpp26
-rw-r--r--ELFLoader/ExecSpace.h13
-rw-r--r--Kernel/Makefile6
-rw-r--r--Kernel/MemoryManager.cpp76
-rw-r--r--Kernel/MemoryManager.h9
-rw-r--r--Kernel/ProcFileSystem.cpp8
-rw-r--r--Kernel/Task.cpp83
-rw-r--r--Kernel/Task.h20
-rw-r--r--Kernel/i386.cpp14
-rw-r--r--Kernel/types.h2
-rw-r--r--LibC/Makefile2
-rw-r--r--LibC/stdio.cpp2
-rw-r--r--Userland/Makefile6
-rw-r--r--Userland/ls.cpp7
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() == &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;
}
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;
}