mirror of
https://github.com/kenshineto/kern.git
synced 2025-04-16 23:47:25 +00:00
backtrace
This commit is contained in:
parent
7c83d33976
commit
331a2a442b
7 changed files with 86 additions and 113 deletions
|
@ -32,10 +32,11 @@ const kernel_src = &[_][]const u8{
|
|||
"kernel/drivers/clock.c",
|
||||
"kernel/drivers/drivers.c",
|
||||
"kernel/drivers/pci.c",
|
||||
"kernel/drivers/tty.c",
|
||||
"kernel/drivers/term.c",
|
||||
"kernel/drivers/uart.c",
|
||||
"kernel/fs/fs.c",
|
||||
"kernel/lib/atox.c",
|
||||
"kernel/lib/backtrace.c",
|
||||
"kernel/lib/bound.c",
|
||||
"kernel/lib/btoa.c",
|
||||
"kernel/lib/ctoi.c",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "lib/klib.h"
|
||||
#include <lib.h>
|
||||
#include <comus/memory.h>
|
||||
#include <comus/asm.h>
|
||||
|
@ -197,6 +198,8 @@ void idt_exception_handler(uint64_t exception, uint64_t code, regs_t *state)
|
|||
|
||||
kputs("\n");
|
||||
|
||||
log_backtrace_ex((void *)state->rip, (void *)state->rbp);
|
||||
|
||||
while (1) {
|
||||
halt();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <lib.h>
|
||||
#include <comus/drivers/tty.h>
|
||||
#include <comus/drivers/term.h>
|
||||
#include <comus/asm.h>
|
||||
#include <comus/memory.h>
|
||||
|
||||
|
@ -18,7 +18,7 @@ static uint8_t fg = 15, bg = 0;
|
|||
// blank color
|
||||
const uint16_t blank = (uint16_t)0 | 0 << 12 | 15 << 8;
|
||||
|
||||
static void term_clear_line(int line)
|
||||
void term_clear_line(int line)
|
||||
{
|
||||
if (line < 0 || line >= height)
|
||||
return;
|
||||
|
@ -28,13 +28,13 @@ static void term_clear_line(int line)
|
|||
}
|
||||
}
|
||||
|
||||
static void term_clear(void)
|
||||
void term_clear(void)
|
||||
{
|
||||
for (uint8_t y = 0; y < height; y++)
|
||||
term_clear_line(y);
|
||||
}
|
||||
|
||||
static void term_scroll(int lines)
|
||||
void term_scroll(int lines)
|
||||
{
|
||||
cli();
|
||||
y -= lines;
|
||||
|
@ -52,7 +52,7 @@ static void term_scroll(int lines)
|
|||
sti();
|
||||
}
|
||||
|
||||
void tty_out(char c)
|
||||
void term_out(char c)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
@ -98,8 +98,8 @@ void tty_out(char c)
|
|||
outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
|
||||
}
|
||||
|
||||
void tty_out_str(const char *str)
|
||||
void term_out_str(const char *str)
|
||||
{
|
||||
while (*str)
|
||||
tty_out(*str++);
|
||||
term_out(*str++);
|
||||
}
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
#include <lib.h>
|
||||
#include <comus/drivers/term.h>
|
||||
#include <comus/asm.h>
|
||||
#include <comus/memory.h>
|
||||
|
||||
#define VGA_ADDR 0xB8000
|
||||
|
||||
static const uint8_t width = 80;
|
||||
static const uint8_t height = 25;
|
||||
static volatile uint16_t *buffer = (uint16_t *)VGA_ADDR;
|
||||
|
||||
// position
|
||||
static uint32_t x = 0, y = 0;
|
||||
|
||||
// color
|
||||
static uint8_t fg = 15, bg = 0;
|
||||
|
||||
// blank color
|
||||
const uint16_t blank = (uint16_t)0 | 0 << 12 | 15 << 8;
|
||||
|
||||
void term_clear_line(int line)
|
||||
{
|
||||
if (line < 0 || line >= height)
|
||||
return;
|
||||
for (uint8_t x = 0; x < width; x++) {
|
||||
const size_t index = line * width + x;
|
||||
buffer[index] = blank;
|
||||
}
|
||||
}
|
||||
|
||||
void term_clear(void)
|
||||
{
|
||||
for (uint8_t y = 0; y < height; y++)
|
||||
term_clear_line(y);
|
||||
}
|
||||
|
||||
void term_scroll(int lines)
|
||||
{
|
||||
cli();
|
||||
y -= lines;
|
||||
if (!lines)
|
||||
return;
|
||||
if (lines >= height || lines <= -height) {
|
||||
term_clear();
|
||||
} else if (lines > 0) {
|
||||
memmovev(buffer, buffer + lines * width, 2 * (height - lines) * width);
|
||||
term_clear_line(height - lines);
|
||||
} else {
|
||||
memmovev(buffer + lines * width, buffer + lines,
|
||||
(height + lines) * width);
|
||||
}
|
||||
sti();
|
||||
}
|
||||
|
||||
void term_out(char c)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
// handle special chars
|
||||
switch (c) {
|
||||
case '\n':
|
||||
x = 0;
|
||||
y++;
|
||||
break;
|
||||
case '\t':
|
||||
x += 4;
|
||||
break;
|
||||
case '\v':
|
||||
case '\f':
|
||||
y++;
|
||||
break;
|
||||
case '\r':
|
||||
x = 0;
|
||||
break;
|
||||
default: {
|
||||
const size_t index = y * width + x;
|
||||
buffer[index] = c | bg << 12 | fg << 8;
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
// wrap cursor if needed
|
||||
if (x >= width) {
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
if (y >= height) {
|
||||
term_scroll(y - (height - 1));
|
||||
y = height - 1;
|
||||
}
|
||||
|
||||
// set cursor position on screen
|
||||
const uint16_t pos = y * width + x;
|
||||
outb(0x3D4, 0x0F);
|
||||
outb(0x3D5, (uint8_t)(pos & 0xFF));
|
||||
outb(0x3D4, 0x0E);
|
||||
outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF));
|
||||
}
|
||||
|
||||
void term_out_str(const char *str)
|
||||
{
|
||||
while (*str)
|
||||
term_out(*str++);
|
||||
}
|
|
@ -193,4 +193,30 @@ unsigned int bound(unsigned int min, unsigned int value, unsigned int max);
|
|||
*/
|
||||
__attribute__((noreturn)) void panic(const char *format, ...);
|
||||
|
||||
/**
|
||||
* Fill dst with a stack trace consisting of return addresses in order
|
||||
* from top to bottom
|
||||
*
|
||||
* @returns number of backtraces (at most len)
|
||||
*/
|
||||
size_t backtrace(void **dst, size_t len);
|
||||
|
||||
/**
|
||||
* Fill dst with a stack trace consisting of return addresses in order
|
||||
* from top to bottom, starting at a provided ip/bp
|
||||
*
|
||||
* @returns number of backtraces (at most len)
|
||||
*/
|
||||
size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp);
|
||||
|
||||
/**
|
||||
* Log a backtrace to output
|
||||
*/
|
||||
void log_backtrace(void);
|
||||
|
||||
/**
|
||||
* Log a backtrace to output starting at a provided ip/bp
|
||||
*/
|
||||
void log_backtrace_ex(void *ip, void *bp);
|
||||
|
||||
#endif /* klib.h */
|
||||
|
|
46
kernel/lib/backtrace.c
Normal file
46
kernel/lib/backtrace.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include <lib.h>
|
||||
|
||||
struct stackframe {
|
||||
struct stackframe *rbp;
|
||||
void *rip;
|
||||
};
|
||||
|
||||
size_t backtrace(void **dst, size_t len)
|
||||
{
|
||||
struct stackframe *rbp;
|
||||
__asm__("mov %%rbp, %0" : "=r"(rbp));
|
||||
return backtrace_ex(dst, len, rbp->rip, rbp->rbp);
|
||||
}
|
||||
|
||||
size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp)
|
||||
{
|
||||
struct stackframe *frame = bp;
|
||||
__asm__("mov %%rbp, %0" : "=r"(frame));
|
||||
if (len > 0) {
|
||||
dst[0] = ip;
|
||||
}
|
||||
size_t i;
|
||||
for (i = 1; frame && i < len; i++) {
|
||||
dst[i] = frame->rip;
|
||||
frame = frame->rbp;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void log_backtrace(void)
|
||||
{
|
||||
struct stackframe *rbp;
|
||||
__asm__("mov %%rbp, %0" : "=r"(rbp));
|
||||
log_backtrace_ex(rbp->rip, rbp->rbp);
|
||||
}
|
||||
|
||||
void log_backtrace_ex(void *ip, void *bp)
|
||||
{
|
||||
struct stackframe *frame = bp;
|
||||
kputs("Stack trace:\n");
|
||||
kprintf(" %p\n", ip);
|
||||
while (frame) {
|
||||
kprintf(" %p\n", frame->rip);
|
||||
frame = frame->rbp;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
#include "lib/klib.h"
|
||||
#include <lib.h>
|
||||
#include <stdarg.h>
|
||||
#include <comus/asm.h>
|
||||
|
@ -10,6 +11,7 @@ __attribute__((noreturn)) void panic(const char *format, ...)
|
|||
kprintf("\n\n!!! PANIC !!!\n");
|
||||
kvprintf(format, list);
|
||||
kprintf("\n\n");
|
||||
log_backtrace();
|
||||
|
||||
while (1)
|
||||
halt();
|
||||
|
|
Loading…
Add table
Reference in a new issue