strat9_kernel/boot/
symbols.rs1use core::sync::atomic::{AtomicBool, Ordering};
7
8#[derive(Clone, Copy)]
10struct KernelSymbol {
11 addr: u64,
12 size: u64,
13 name_offset: u32,
14}
15
16static INITIALIZED: AtomicBool = AtomicBool::new(false);
18static mut SYMBOLS: [KernelSymbol; 8192] = [KernelSymbol {
19 addr: 0,
20 size: 0,
21 name_offset: 0,
22}; 8192];
23static mut SYMBOL_COUNT: usize = 0;
24static mut STRTAB: [u8; 65536] = [0; 65536];
25static mut STRTAB_LEN: usize = 0;
26
27pub fn init() {
29 if INITIALIZED.load(Ordering::Relaxed) {
30 return;
31 }
32
33 let elf_bytes = match super::dtb_boot::kernel_elf_bytes() {
34 Some(b) => b,
35 None => return,
36 };
37 #[cfg(not(target_arch = "x86_64"))]
38 let elf_bytes: &[u8] = &[];
39
40 let elf = match xmas_elf::ElfFile::new(elf_bytes) {
41 Ok(e) => e,
42 Err(_) => return,
43 };
44
45 let strtab_data = find_section_data(&elf, ".strtab");
47 if strtab_data.is_empty() {
48 return;
49 }
50 let copy_len = strtab_data.len().min(65536);
51 unsafe {
52 STRTAB[..copy_len].copy_from_slice(&strtab_data[..copy_len]);
53 STRTAB_LEN = copy_len;
54 }
55
56 let symtab_data = find_section_data(&elf, ".symtab");
58 if symtab_data.is_empty() {
59 return;
60 }
61
62 let entry_size = 24;
65 let count = symtab_data.len() / entry_size;
66 let max = 8192;
67 let mut n = 0usize;
68
69 for i in 0..count.min(max) {
70 let off = i * entry_size;
71 if off + entry_size > symtab_data.len() {
72 break;
73 }
74 let st_name = u32::from_le_bytes([
75 symtab_data[off],
76 symtab_data[off + 1],
77 symtab_data[off + 2],
78 symtab_data[off + 3],
79 ]);
80 let st_value = u64::from_le_bytes([
81 symtab_data[off + 8],
82 symtab_data[off + 9],
83 symtab_data[off + 10],
84 symtab_data[off + 11],
85 symtab_data[off + 12],
86 symtab_data[off + 13],
87 symtab_data[off + 14],
88 symtab_data[off + 15],
89 ]);
90 let st_size = u64::from_le_bytes([
91 symtab_data[off + 16],
92 symtab_data[off + 17],
93 symtab_data[off + 18],
94 symtab_data[off + 19],
95 symtab_data[off + 20],
96 symtab_data[off + 21],
97 symtab_data[off + 22],
98 symtab_data[off + 23],
99 ]);
100
101 if st_value == 0 {
103 continue;
104 }
105
106 unsafe {
107 SYMBOLS[n] = KernelSymbol {
108 addr: st_value,
109 size: st_size,
110 name_offset: st_name,
111 };
112 }
113 n += 1;
114 }
115
116 unsafe {
118 SYMBOL_COUNT = n;
119 let syms = &mut SYMBOLS[..n];
120 syms.sort_unstable_by_key(|s| s.addr);
121 }
122
123 INITIALIZED.store(true, Ordering::Relaxed);
124}
125
126fn find_section_data<'a>(elf: &xmas_elf::ElfFile<'a>, name: &str) -> &'a [u8] {
128 match elf.find_section_by_name(name) {
129 Some(section) => section.raw_data(elf),
130 None => &[],
131 }
132}
133
134pub fn lookup(addr: u64) -> Option<(&'static str, u64)> {
137 if !INITIALIZED.load(Ordering::Relaxed) {
138 return None;
139 }
140
141 let syms = unsafe { &SYMBOLS[..SYMBOL_COUNT] };
142
143 let idx = match syms.binary_search_by_key(&addr, |s| s.addr) {
145 Ok(i) => i,
146 Err(i) => {
147 if i == 0 {
148 return None;
149 }
150 i - 1
151 }
152 };
153
154 let sym = &syms[idx];
155 let offset = addr.saturating_sub(sym.addr);
156
157 if sym.size > 0 && offset >= sym.size {
159 return None;
160 }
161
162 let name = get_symbol_name(sym.name_offset);
163 Some((name, offset))
164}
165
166fn get_symbol_name(offset: u32) -> &'static str {
168 let off = offset as usize;
169 let tab = unsafe { &STRTAB[..STRTAB_LEN] };
170 if off >= tab.len() {
171 return "<unknown>";
172 }
173 let end = tab[off..]
174 .iter()
175 .position(|&b| b == 0)
176 .map(|p| off + p)
177 .unwrap_or(tab.len());
178 core::str::from_utf8(&tab[off..end]).unwrap_or("<unknown>")
179}