MCPcopy Create free account
hub / github.com/MemNixFS/MemNixFS / walk_kernel_stack

Function walk_kernel_stack

src/os/linux/pscallstack.cpp:62–131  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

60} // anonymous
61
62KStackTrace walk_kernel_stack(const Engine& eng, const Process& p) {
63 KStackTrace out{};
64 const auto& isf = eng.isf();
65 const auto& ks = eng.kallsyms();
66 if (!ks.ok || p.task_va == 0) return out;
67
68 u64 ts_stack_off = 0, ts_thread_off = 0, thread_sp_off = 0;
69 try {
70 ts_stack_off = isf.field_offset("task_struct", "stack");
71 ts_thread_off = isf.field_offset("task_struct", "thread");
72 thread_sp_off = isf.field_offset("thread_struct", "sp");
73 } catch (const std::exception& e) {
74 log::debug("kstack: ISF lacks field — {}", e.what());
75 return out;
76 }
77
78 // task.stack is the BASE of the kernel stack (lowest address). The
79 // stack grows DOWN from base + THREAD_SIZE, so saved-sp >= base.
80 VAddr stack_base = 0;
81 if (!kva_read_pod(eng, p.task_va + ts_stack_off, stack_base) ||
82 stack_base == 0)
83 return out;
84 VAddr thread_sp = 0;
85 kva_read_pod(eng, p.task_va + ts_thread_off + thread_sp_off, thread_sp);
86
87 out.stack_base = stack_base;
88 out.thread_sp = thread_sp;
89
90 // Read the whole THREAD_SIZE window. Kernel stacks are slab-allocated
91 // (direct-map memory) so kva_read serves us via subtract-direct-map.
92 std::vector<u8> stack(kThreadSize, 0);
93 if (!kva_read(eng, stack_base, stack.data(), kThreadSize)) {
94 log::debug("kstack: pid {} stack @ {:#x} unreadable",
95 p.pid, stack_base);
96 return out;
97 }
98
99 AddrIndex ai = build_addr_index(ks);
100 TextBounds tb = resolve_text_bounds(ks);
101
102 // Scan every 8-byte aligned position for kernel-text return-address-
103 // shaped values. Dedup by symbol name (the same function can appear
104 // many times on a stack from spurious matches in stale memory).
105 std::unordered_set<std::string> seen;
106 for (std::size_t off = 0; off + 8 <= stack.size(); off += 8) {
107 u64 v = 0;
108 std::memcpy(&v, stack.data() + off, 8);
109 if (v < tb.start || v >= tb.end) continue;
110 const KallsymsEntry* sym = find_sym_below(ks, ai, v);
111 if (!sym) continue;
112 u64 dist = v - sym->address;
113 // Reject "way past nearest symbol" as not a real return into
114 // that function (some adjacent data section).
115 if (dist > 0x10000) continue;
116 // Dedup — only keep the first sighting of each symbol on the
117 // stack (lowest offset = closest to current frame).
118 if (!seen.insert(sym->name).second) continue;
119

Callers 1

format_kstackFunction · 0.85

Calls 8

debugFunction · 0.85
kva_read_podFunction · 0.85
kva_readFunction · 0.85
field_offsetMethod · 0.80
build_addr_indexFunction · 0.70
resolve_text_boundsFunction · 0.70
find_sym_belowFunction · 0.70
sizeMethod · 0.45

Tested by

no test coverage detected