diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-10-26 22:32:35 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-10-26 22:33:15 +0200 |
commit | c928b062180b10a9908325727e18483e029edada (patch) | |
tree | 38d9c7cafc21ed9d438cc137bbb613f38cb1415d | |
parent | 81627cf7d539b3aa15773967f6c3d7c6e7ca86be (diff) | |
download | serenity-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/.gitignore | 1 | ||||
-rw-r--r-- | Kernel/Console.h | 1 | ||||
-rw-r--r-- | Kernel/Makefile | 9 | ||||
-rw-r--r-- | Kernel/ProcFileSystem.cpp | 36 | ||||
-rw-r--r-- | Kernel/Task.cpp | 12 | ||||
-rw-r--r-- | Kernel/Task.h | 6 | ||||
-rw-r--r-- | Kernel/_fs_contents | bin | 1024000 -> 1024000 bytes | |||
-rw-r--r-- | Kernel/init.cpp | 51 | ||||
-rw-r--r-- | Kernel/kmalloc.cpp | 4 | ||||
-rw-r--r-- | Kernel/mkmap.sh | 5 | ||||
-rwxr-xr-x | Kernel/sync-sh | 1 | ||||
-rw-r--r-- | Kernel/system.h | 9 | ||||
-rw-r--r-- | Userland/cat.cpp | 2 | ||||
-rw-r--r-- | VirtualFileSystem/SyntheticFileSystem.cpp | 6 |
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 Binary files differindex 920ef4e3fa..cff5e6f491 100644 --- a/Kernel/_fs_contents +++ b/Kernel/_fs_contents 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()); |