summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-10-26 22:32:35 +0200
committerAndreas Kling <awesomekling@gmail.com>2018-10-26 22:33:15 +0200
commitc928b062180b10a9908325727e18483e029edada (patch)
tree38d9c7cafc21ed9d438cc137bbb613f38cb1415d
parent81627cf7d539b3aa15773967f6c3d7c6e7ca86be (diff)
downloadserenity-c928b062180b10a9908325727e18483e029edada.zip
Add a very hackish /proc/PID/stack.
It walks the stack and identifies anything that looks like a kernel symbol. This could be a lot more sophisticated.
-rw-r--r--Kernel/.gitignore1
-rw-r--r--Kernel/Console.h1
-rw-r--r--Kernel/Makefile9
-rw-r--r--Kernel/ProcFileSystem.cpp36
-rw-r--r--Kernel/Task.cpp12
-rw-r--r--Kernel/Task.h6
-rw-r--r--Kernel/_fs_contentsbin1024000 -> 1024000 bytes
-rw-r--r--Kernel/init.cpp51
-rw-r--r--Kernel/kmalloc.cpp4
-rw-r--r--Kernel/mkmap.sh5
-rwxr-xr-xKernel/sync-sh1
-rw-r--r--Kernel/system.h9
-rw-r--r--Userland/cat.cpp2
-rw-r--r--VirtualFileSystem/SyntheticFileSystem.cpp6
14 files changed, 130 insertions, 13 deletions
diff --git a/Kernel/.gitignore b/Kernel/.gitignore
index 7fa55bf91c..8a77724203 100644
--- a/Kernel/.gitignore
+++ b/Kernel/.gitignore
@@ -2,3 +2,4 @@
.floppy-image
Boot/boot.bin
kernel
+kernel.map
diff --git a/Kernel/Console.h b/Kernel/Console.h
index 3d82cb126e..196f9cb6ad 100644
--- a/Kernel/Console.h
+++ b/Kernel/Console.h
@@ -1,5 +1,6 @@
#pragma once
+#include <AK/Compiler.h>
#include <VirtualFileSystem/CharacterDevice.h>
class Console final : public CharacterDevice {
diff --git a/Kernel/Makefile b/Kernel/Makefile
index e74007fe1d..5c1a83e80f 100644
--- a/Kernel/Makefile
+++ b/Kernel/Makefile
@@ -56,8 +56,8 @@ 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 = -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 = -fomit-frame-pointer -mregparm=3 -march=i386 -m32 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections
+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
OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables
INCLUDE_FLAGS = -I.. -I.
@@ -71,7 +71,10 @@ LD = ld
LDFLAGS = -T linker.ld --strip-debug -melf_i386 --gc-sections --build-id=none -z norelro -z now
-all: $(KERNEL) $(IMAGE)
+all: $(KERNEL) $(IMAGE) kernel.map
+
+kernel.map: kernel
+ @echo "MKMAP $@"; sh mkmap.sh
$(KERNEL): $(OBJS)
@echo "LD $@"; $(LD) $(LDFLAGS) -o $@ -Ttext 0x10000 $(OBJS)
diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp
index 8c594eecf1..9560faad69 100644
--- a/Kernel/ProcFileSystem.cpp
+++ b/Kernel/ProcFileSystem.cpp
@@ -1,6 +1,7 @@
#include "ProcFileSystem.h"
#include "Task.h"
#include <VirtualFileSystem/VirtualFileSystem.h>
+#include "system.h"
static ProcFileSystem* s_the;
@@ -48,6 +49,41 @@ void ProcFileSystem::addProcess(Task& task)
*ptr = '\0';
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
}), dir.index());
+ addFile(createGeneratedFile("stack", [&task] {
+ InterruptDisabler disabler;
+ auto& syms = ksyms();
+ dword firstKsymAddress = syms.first().address;
+ dword lastKsymAddress = syms.last().address;
+ struct RecognizedSymbol {
+ dword address;
+ const char* name;
+ dword offset;
+ };
+ Vector<RecognizedSymbol> recognizedSymbols;
+ size_t bytesNeeded = 0;
+ for (dword* stackPtr = (dword*)task.stackPtr(); (dword)stackPtr < task.stackTop(); ++stackPtr) {
+ if (*stackPtr < firstKsymAddress || *stackPtr > lastKsymAddress)
+ continue;
+ const char* name = nullptr;
+ unsigned offset = 0;
+ for (unsigned i = 0; i < syms.size(); ++i) {
+ if (*stackPtr < syms[i+1].address) {
+ name = syms[i].name.characters();
+ offset = *stackPtr - syms[i].address;
+ bytesNeeded += syms[i].name.length() + 8 + 16;
+ break;
+ }
+ }
+ recognizedSymbols.append({ *stackPtr, name, offset });
+ }
+ auto buffer = ByteBuffer::createUninitialized(bytesNeeded);
+ char* ptr = (char*)buffer.pointer();
+ for (auto& symbol : recognizedSymbols) {
+ kprintf("%p %s +%u\n", symbol.address, symbol.name, symbol.offset);
+ }
+ buffer.trim(ptr - (char*)buffer.pointer());
+ return buffer;
+ }), dir.index());
}
void ProcFileSystem::removeProcess(Task& task)
diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp
index 15b407d675..79fd9d7c37 100644
--- a/Kernel/Task.cpp
+++ b/Kernel/Task.cpp
@@ -378,21 +378,21 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring)
// FIXME: This memory is leaked.
// But uh, there's also no kernel task termination, so I guess it's not technically leaked...
dword stackBottom = (dword)kmalloc(defaultStackSize);
- m_stackTop = (stackBottom + defaultStackSize) & 0xffffff8;
- m_tss.esp = m_stackTop;
+ m_stackTop0 = (stackBottom + defaultStackSize) & 0xffffff8;
+ m_tss.esp = m_stackTop0;
} else {
auto* region = allocateRegion(defaultStackSize, "stack");
ASSERT(region);
- m_stackTop = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
+ m_stackTop3 = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
+ m_tss.esp = m_stackTop3;
}
- m_tss.esp = m_stackTop;
if (isRing3()) {
// Ring3 tasks need a separate stack for Ring0.
m_kernelStack = kmalloc(defaultStackSize);
- DWORD ring0StackTop = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
+ m_stackTop0 = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
m_tss.ss0 = 0x10;
- m_tss.esp0 = ring0StackTop;
+ m_tss.esp0 = m_stackTop0;
}
// HACK: Ring2 SS in the TSS is the current PID.
diff --git a/Kernel/Task.h b/Kernel/Task.h
index 4a1e5fe164..dd06be7022 100644
--- a/Kernel/Task.h
+++ b/Kernel/Task.h
@@ -122,6 +122,9 @@ public:
size_t fileHandleCount() const { return m_fileHandles.size(); }
+ dword stackPtr() const { return m_tss.esp; }
+ dword stackTop() const { return m_tss.ss == 0x10 ? m_stackTop0 : m_stackTop3; }
+
private:
friend class MemoryManager;
friend bool scheduleNewTask();
@@ -140,7 +143,8 @@ private:
gid_t m_gid { 0 };
DWORD m_ticks { 0 };
DWORD m_ticksLeft { 0 };
- DWORD m_stackTop { 0 };
+ DWORD m_stackTop0 { 0 };
+ DWORD m_stackTop3 { 0 };
FarPtr m_farPtr;
State m_state { Invalid };
DWORD m_wakeupTime { 0 };
diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents
index 920ef4e3fa..cff5e6f491 100644
--- a/Kernel/_fs_contents
+++ b/Kernel/_fs_contents
Binary files differ
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index 0880d10419..8368e071c9 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -28,6 +28,7 @@
#include "RTC.h"
#define TEST_VFS
+#define KERNEL_MAP
//#define STRESS_TEST_SPAWNING
//#define TEST_ELF_LOADER
//#define TEST_CRASHY_USER_PROCESSES
@@ -49,6 +50,43 @@ void banner()
kprintf("\n");
}
+static byte parseHexDigit(char nibble)
+{
+ if (nibble >= '0' && nibble <= '9')
+ return nibble - '0';
+ ASSERT(nibble >= 'a' && nibble <= 'f');
+ return 10 + (nibble - 'a');
+}
+
+static Vector<KSym>* s_ksyms;
+
+Vector<KSym>& ksyms()
+{
+ return *s_ksyms;
+}
+
+static void loadKernelMap(const ByteBuffer& buffer)
+{
+ s_ksyms = new Vector<KSym>;
+ auto* bufptr = (const char*)buffer.pointer();
+ auto* startOfName = bufptr;
+ dword address = 0;
+
+ while (bufptr < buffer.endPointer()) {
+ for (unsigned i = 0; i < 8; ++i)
+ address = (address << 4) | parseHexDigit(*(bufptr++));
+ bufptr += 3;
+ startOfName = bufptr;
+ while (*(++bufptr)) {
+ if (*bufptr == '\n') {
+ break;
+ }
+ }
+ ksyms().append({ address, String(startOfName, bufptr - startOfName) });
+ ++bufptr;
+ }
+}
+
#ifdef TEST_CRASHY_USER_PROCESSES
static void user_main() NORETURN;
static void user_main()
@@ -108,6 +146,19 @@ static void init_stage2()
vfs->mountRoot(e2fs.copyRef());
+#ifdef KERNEL_MAP
+ {
+ auto handle = vfs->open("/kernel.map");
+ if (!handle) {
+ kprintf("Failed to open /kernel.map\n");
+ } else {
+ auto buffer = handle->readEntireFile();
+ ASSERT(buffer);
+ loadKernelMap(buffer);
+ }
+ }
+#endif
+
vfs->mount(ProcFileSystem::the(), "/proc");
#endif
diff --git a/Kernel/kmalloc.cpp b/Kernel/kmalloc.cpp
index 693c29e98a..082307ac3b 100644
--- a/Kernel/kmalloc.cpp
+++ b/Kernel/kmalloc.cpp
@@ -107,10 +107,10 @@ kmalloc( DWORD size )
}
}
- kprintf( "kmalloc(): PANIC! Out of memory (no suitable block)" );
+ kprintf("kmalloc(): PANIC! Out of memory (no suitable block for size %u)\n", size);
HANG;
- return 0L;
+ return nullptr;
}
PUBLIC void
diff --git a/Kernel/mkmap.sh b/Kernel/mkmap.sh
new file mode 100644
index 0000000000..01c84a81dd
--- /dev/null
+++ b/Kernel/mkmap.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+tmp=$(mktemp)
+nm -C kernel > $tmp
+perl -lpe '$_=hex' $tmp | paste -d" " - $tmp | sort -n | cut -d" " -f 2- > kernel.map
+rm $tmp
diff --git a/Kernel/sync-sh b/Kernel/sync-sh
index f885e7ab18..baa10ce637 100755
--- a/Kernel/sync-sh
+++ b/Kernel/sync-sh
@@ -12,5 +12,6 @@ cp ../Userland/false mnt/bin/false
cp ../Userland/hostname mnt/bin/hostname
cp ../Userland/cat mnt/bin/cat
cp ../Userland/uname mnt/bin/uname
+cp kernel.map mnt/
umount mnt
sync
diff --git a/Kernel/system.h b/Kernel/system.h
index a40569a02b..03de208bbb 100644
--- a/Kernel/system.h
+++ b/Kernel/system.h
@@ -1,6 +1,15 @@
#pragma once
#include "types.h"
+#include <AK/Vector.h>
+#include <AK/String.h>
+
+struct KSym {
+ dword address;
+ String name;
+};
+
+Vector<KSym>& ksyms() PURE;
struct system_t
{
diff --git a/Userland/cat.cpp b/Userland/cat.cpp
index ce99c6499b..c6c11b4127 100644
--- a/Userland/cat.cpp
+++ b/Userland/cat.cpp
@@ -15,7 +15,7 @@ int main(int argc, char** argv)
return 1;
}
for (;;) {
- char buf[128];
+ char buf[4096];
ssize_t nread = read(fd, buf, sizeof(buf));
if (nread == 0)
break;
diff --git a/VirtualFileSystem/SyntheticFileSystem.cpp b/VirtualFileSystem/SyntheticFileSystem.cpp
index 0943949475..f36deeed9c 100644
--- a/VirtualFileSystem/SyntheticFileSystem.cpp
+++ b/VirtualFileSystem/SyntheticFileSystem.cpp
@@ -79,6 +79,7 @@ auto SyntheticFileSystem::createGeneratedFile(String&& name, Function<ByteBuffer
InodeIdentifier SyntheticFileSystem::addFile(OwnPtr<File>&& file, InodeIndex parent)
{
+ ASSERT_INTERRUPTS_DISABLED();
ASSERT(file);
auto it = m_inodes.find(parent);
ASSERT(it != m_inodes.end());
@@ -92,6 +93,7 @@ InodeIdentifier SyntheticFileSystem::addFile(OwnPtr<File>&& file, InodeIndex par
bool SyntheticFileSystem::removeFile(InodeIndex inode)
{
+ ASSERT_INTERRUPTS_DISABLED();
auto it = m_inodes.find(inode);
if (it == m_inodes.end())
return false;
@@ -127,6 +129,7 @@ InodeIdentifier SyntheticFileSystem::rootInode() const
bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> callback) const
{
+ InterruptDisabler disabler;
ASSERT(inode.fileSystemID() == id());
#ifdef SYNTHFS_DEBUG
kprintf("[synthfs] enumerateDirectoryInode %u\n", inode.index());
@@ -150,6 +153,7 @@ bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Functio
InodeMetadata SyntheticFileSystem::inodeMetadata(InodeIdentifier inode) const
{
+ InterruptDisabler disabler;
ASSERT(inode.fileSystemID() == id());
#ifdef SYNTHFS_DEBUG
kprintf("[synthfs] inodeMetadata(%u)\n", inode.index());
@@ -186,6 +190,8 @@ bool SyntheticFileSystem::writeInode(InodeIdentifier, const ByteBuffer&)
Unix::ssize_t SyntheticFileSystem::readInodeBytes(InodeIdentifier inode, Unix::off_t offset, Unix::size_t count, byte* buffer) const
{
+ InterruptDisabler disabler;
+
ASSERT(inode.fileSystemID() == id());
#ifdef SYNTHFS_DEBUG
kprintf("[synthfs] readInode %u\n", inode.index());