mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-29 14:14:45 +03:00
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.
This commit is contained in:
parent
81627cf7d5
commit
c928b06218
Notes:
sideshowbarker
2024-07-19 18:37:59 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/c928b062180
1
Kernel/.gitignore
vendored
1
Kernel/.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
.floppy-image
|
.floppy-image
|
||||||
Boot/boot.bin
|
Boot/boot.bin
|
||||||
kernel
|
kernel
|
||||||
|
kernel.map
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Compiler.h>
|
||||||
#include <VirtualFileSystem/CharacterDevice.h>
|
#include <VirtualFileSystem/CharacterDevice.h>
|
||||||
|
|
||||||
class Console final : public CharacterDevice {
|
class Console final : public CharacterDevice {
|
||||||
|
@ -56,8 +56,8 @@ ARCH_FLAGS =
|
|||||||
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
|
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib
|
||||||
KERNEL_FLAGS = -ffreestanding -fno-stack-protector -fno-ident
|
KERNEL_FLAGS = -ffreestanding -fno-stack-protector -fno-ident
|
||||||
WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings
|
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 = -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
|
||||||
OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables
|
OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables
|
||||||
INCLUDE_FLAGS = -I.. -I.
|
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
|
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)
|
$(KERNEL): $(OBJS)
|
||||||
@echo "LD $@"; $(LD) $(LDFLAGS) -o $@ -Ttext 0x10000 $(OBJS)
|
@echo "LD $@"; $(LD) $(LDFLAGS) -o $@ -Ttext 0x10000 $(OBJS)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "ProcFileSystem.h"
|
#include "ProcFileSystem.h"
|
||||||
#include "Task.h"
|
#include "Task.h"
|
||||||
#include <VirtualFileSystem/VirtualFileSystem.h>
|
#include <VirtualFileSystem/VirtualFileSystem.h>
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
static ProcFileSystem* s_the;
|
static ProcFileSystem* s_the;
|
||||||
|
|
||||||
@ -48,6 +49,41 @@ void ProcFileSystem::addProcess(Task& task)
|
|||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
|
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
|
||||||
}), dir.index());
|
}), 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)
|
void ProcFileSystem::removeProcess(Task& task)
|
||||||
|
@ -378,21 +378,21 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring)
|
|||||||
// FIXME: This memory is leaked.
|
// FIXME: This memory is leaked.
|
||||||
// But uh, there's also no kernel task termination, so I guess it's not technically leaked...
|
// But uh, there's also no kernel task termination, so I guess it's not technically leaked...
|
||||||
dword stackBottom = (dword)kmalloc(defaultStackSize);
|
dword stackBottom = (dword)kmalloc(defaultStackSize);
|
||||||
m_stackTop = (stackBottom + defaultStackSize) & 0xffffff8;
|
m_stackTop0 = (stackBottom + defaultStackSize) & 0xffffff8;
|
||||||
m_tss.esp = m_stackTop;
|
m_tss.esp = m_stackTop0;
|
||||||
} else {
|
} else {
|
||||||
auto* region = allocateRegion(defaultStackSize, "stack");
|
auto* region = allocateRegion(defaultStackSize, "stack");
|
||||||
ASSERT(region);
|
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()) {
|
if (isRing3()) {
|
||||||
// Ring3 tasks need a separate stack for Ring0.
|
// Ring3 tasks need a separate stack for Ring0.
|
||||||
m_kernelStack = kmalloc(defaultStackSize);
|
m_kernelStack = kmalloc(defaultStackSize);
|
||||||
DWORD ring0StackTop = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
|
m_stackTop0 = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
|
||||||
m_tss.ss0 = 0x10;
|
m_tss.ss0 = 0x10;
|
||||||
m_tss.esp0 = ring0StackTop;
|
m_tss.esp0 = m_stackTop0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: Ring2 SS in the TSS is the current PID.
|
// HACK: Ring2 SS in the TSS is the current PID.
|
||||||
|
@ -122,6 +122,9 @@ public:
|
|||||||
|
|
||||||
size_t fileHandleCount() const { return m_fileHandles.size(); }
|
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:
|
private:
|
||||||
friend class MemoryManager;
|
friend class MemoryManager;
|
||||||
friend bool scheduleNewTask();
|
friend bool scheduleNewTask();
|
||||||
@ -140,7 +143,8 @@ private:
|
|||||||
gid_t m_gid { 0 };
|
gid_t m_gid { 0 };
|
||||||
DWORD m_ticks { 0 };
|
DWORD m_ticks { 0 };
|
||||||
DWORD m_ticksLeft { 0 };
|
DWORD m_ticksLeft { 0 };
|
||||||
DWORD m_stackTop { 0 };
|
DWORD m_stackTop0 { 0 };
|
||||||
|
DWORD m_stackTop3 { 0 };
|
||||||
FarPtr m_farPtr;
|
FarPtr m_farPtr;
|
||||||
State m_state { Invalid };
|
State m_state { Invalid };
|
||||||
DWORD m_wakeupTime { 0 };
|
DWORD m_wakeupTime { 0 };
|
||||||
|
Binary file not shown.
@ -28,6 +28,7 @@
|
|||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
|
|
||||||
#define TEST_VFS
|
#define TEST_VFS
|
||||||
|
#define KERNEL_MAP
|
||||||
//#define STRESS_TEST_SPAWNING
|
//#define STRESS_TEST_SPAWNING
|
||||||
//#define TEST_ELF_LOADER
|
//#define TEST_ELF_LOADER
|
||||||
//#define TEST_CRASHY_USER_PROCESSES
|
//#define TEST_CRASHY_USER_PROCESSES
|
||||||
@ -49,6 +50,43 @@ void banner()
|
|||||||
kprintf("\n");
|
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
|
#ifdef TEST_CRASHY_USER_PROCESSES
|
||||||
static void user_main() NORETURN;
|
static void user_main() NORETURN;
|
||||||
static void user_main()
|
static void user_main()
|
||||||
@ -108,6 +146,19 @@ static void init_stage2()
|
|||||||
|
|
||||||
vfs->mountRoot(e2fs.copyRef());
|
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");
|
vfs->mount(ProcFileSystem::the(), "/proc");
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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;
|
HANG;
|
||||||
|
|
||||||
return 0L;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUBLIC void
|
PUBLIC void
|
||||||
|
5
Kernel/mkmap.sh
Normal file
5
Kernel/mkmap.sh
Normal file
@ -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
|
@ -12,5 +12,6 @@ cp ../Userland/false mnt/bin/false
|
|||||||
cp ../Userland/hostname mnt/bin/hostname
|
cp ../Userland/hostname mnt/bin/hostname
|
||||||
cp ../Userland/cat mnt/bin/cat
|
cp ../Userland/cat mnt/bin/cat
|
||||||
cp ../Userland/uname mnt/bin/uname
|
cp ../Userland/uname mnt/bin/uname
|
||||||
|
cp kernel.map mnt/
|
||||||
umount mnt
|
umount mnt
|
||||||
sync
|
sync
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <AK/Vector.h>
|
||||||
|
#include <AK/String.h>
|
||||||
|
|
||||||
|
struct KSym {
|
||||||
|
dword address;
|
||||||
|
String name;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<KSym>& ksyms() PURE;
|
||||||
|
|
||||||
struct system_t
|
struct system_t
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ int main(int argc, char** argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char buf[128];
|
char buf[4096];
|
||||||
ssize_t nread = read(fd, buf, sizeof(buf));
|
ssize_t nread = read(fd, buf, sizeof(buf));
|
||||||
if (nread == 0)
|
if (nread == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -79,6 +79,7 @@ auto SyntheticFileSystem::createGeneratedFile(String&& name, Function<ByteBuffer
|
|||||||
|
|
||||||
InodeIdentifier SyntheticFileSystem::addFile(OwnPtr<File>&& file, InodeIndex parent)
|
InodeIdentifier SyntheticFileSystem::addFile(OwnPtr<File>&& file, InodeIndex parent)
|
||||||
{
|
{
|
||||||
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
ASSERT(file);
|
ASSERT(file);
|
||||||
auto it = m_inodes.find(parent);
|
auto it = m_inodes.find(parent);
|
||||||
ASSERT(it != m_inodes.end());
|
ASSERT(it != m_inodes.end());
|
||||||
@ -92,6 +93,7 @@ InodeIdentifier SyntheticFileSystem::addFile(OwnPtr<File>&& file, InodeIndex par
|
|||||||
|
|
||||||
bool SyntheticFileSystem::removeFile(InodeIndex inode)
|
bool SyntheticFileSystem::removeFile(InodeIndex inode)
|
||||||
{
|
{
|
||||||
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
auto it = m_inodes.find(inode);
|
auto it = m_inodes.find(inode);
|
||||||
if (it == m_inodes.end())
|
if (it == m_inodes.end())
|
||||||
return false;
|
return false;
|
||||||
@ -127,6 +129,7 @@ InodeIdentifier SyntheticFileSystem::rootInode() const
|
|||||||
|
|
||||||
bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> callback) const
|
bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Function<bool(const DirectoryEntry&)> callback) const
|
||||||
{
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
ASSERT(inode.fileSystemID() == id());
|
ASSERT(inode.fileSystemID() == id());
|
||||||
#ifdef SYNTHFS_DEBUG
|
#ifdef SYNTHFS_DEBUG
|
||||||
kprintf("[synthfs] enumerateDirectoryInode %u\n", inode.index());
|
kprintf("[synthfs] enumerateDirectoryInode %u\n", inode.index());
|
||||||
@ -150,6 +153,7 @@ bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Functio
|
|||||||
|
|
||||||
InodeMetadata SyntheticFileSystem::inodeMetadata(InodeIdentifier inode) const
|
InodeMetadata SyntheticFileSystem::inodeMetadata(InodeIdentifier inode) const
|
||||||
{
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
ASSERT(inode.fileSystemID() == id());
|
ASSERT(inode.fileSystemID() == id());
|
||||||
#ifdef SYNTHFS_DEBUG
|
#ifdef SYNTHFS_DEBUG
|
||||||
kprintf("[synthfs] inodeMetadata(%u)\n", inode.index());
|
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
|
Unix::ssize_t SyntheticFileSystem::readInodeBytes(InodeIdentifier inode, Unix::off_t offset, Unix::size_t count, byte* buffer) const
|
||||||
{
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
|
|
||||||
ASSERT(inode.fileSystemID() == id());
|
ASSERT(inode.fileSystemID() == id());
|
||||||
#ifdef SYNTHFS_DEBUG
|
#ifdef SYNTHFS_DEBUG
|
||||||
kprintf("[synthfs] readInode %u\n", inode.index());
|
kprintf("[synthfs] readInode %u\n", inode.index());
|
||||||
|
Loading…
Reference in New Issue
Block a user