SimpleKernel 1.17.0
Loading...
Searching...
No Matches
backtrace.cpp
Go to the documentation of this file.
1
5#include <cpu_io.h>
6#include <elf.h>
7
8#include <array>
9#include <cstdint>
10
11#include "arch.h"
12#include "basic_info.hpp"
13#include "kernel.h"
14#include "kernel_elf.hpp"
15#include "kernel_log.hpp"
16
17__always_inline auto backtrace(std::array<uint64_t, kMaxFrameCount>& buffer)
18 -> int {
19 auto fp_value = cpu_io::Fp::Read();
20 size_t count = 0;
21
22 // RISC-V 栈帧布局 (使用 -fno-omit-frame-pointer):
23 // fp[-1] (fp - 8): 保存的返回地址 (ra)
24 // fp[-2] (fp - 16): 保存的上一个帧指针 (saved fp)
25
26 while ((fp_value & 0x07) == 0 && count < buffer.max_size()) {
27 auto* fp = reinterpret_cast<uint64_t*>(fp_value);
28 auto ra = *(fp - 1);
29 auto saved_fp = *(fp - 2);
30
31 // 检查返回地址是否在代码段范围内
32 if (ra < reinterpret_cast<uint64_t>(__executable_start) ||
33 ra > reinterpret_cast<uint64_t>(__etext)) {
34 break;
35 }
36
37 buffer[count++] = ra;
38
39 // 如果 saved_fp 为 0 或无效,停止遍历
40 if (saved_fp == 0) {
41 break;
42 }
43 fp_value = saved_fp;
44 }
45 return static_cast<int>(count);
46}
47
48auto DumpStack() -> void {
49 std::array<uint64_t, kMaxFrameCount> buffer{};
50
51 // 获取调用栈中的地址
52 auto num_frames = backtrace(buffer);
53
54 // 打印函数名
55 for (auto current_frame_idx = 0; current_frame_idx < num_frames;
56 current_frame_idx++) {
57 for (auto symtab : KernelElfSingleton::instance().symtab) {
58 if ((ELF64_ST_TYPE(symtab.st_info) == STT_FUNC) &&
59 (buffer[current_frame_idx] >= symtab.st_value) &&
60 (buffer[current_frame_idx] <= symtab.st_value + symtab.st_size)) {
61 klog::Err("[{}] {:#x}",
62 reinterpret_cast<const char*>(
63 KernelElfSingleton::instance().strtab + symtab.st_name),
64 buffer[current_frame_idx]);
65 }
66 }
67 }
68}
auto DumpStack() -> void
打印调用栈
Definition backtrace.cpp:34
__always_inline auto backtrace(std::array< uint64_t, kMaxFrameCount > &buffer) -> int
Definition backtrace.cpp:18
void * __etext[]
代码段结束
void * __executable_start[]
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志