xref: /DragonOS/tools/debugging/logmonitor/src/backend/loader.rs (revision 8d72b68da9339ec97e1b8929bcf2946f0fd83cd5)
1 use std::{ops::Deref, path::PathBuf};
2 
3 use goblin::elf::Sym;
4 use log::info;
5 
6 use crate::app::AppResult;
7 
8 use super::error::{BackendError, BackendErrorKind};
9 
10 #[derive(Debug)]
11 pub struct KernelLoader;
12 
13 impl KernelLoader {
14     pub fn load(kernel: &PathBuf) -> AppResult<KernelMetadata> {
15         info!("Loading kernel: {:?}", kernel);
16         let kernel_bytes = std::fs::read(kernel)?;
17         let elf = goblin::elf::Elf::parse(&kernel_bytes).map_err(|e| {
18             BackendError::new(
19                 BackendErrorKind::KernelLoadError,
20                 Some(format!("Failed to load kernel: {:?}", e)),
21             )
22         })?;
23         let mut result = KernelMetadata::new(kernel.clone());
24 
25         info!("Parsing symbols...");
26         for sym in elf.syms.iter() {
27             let name = elf.strtab.get_at(sym.st_name).unwrap_or("");
28             result.add_symbol(sym.clone(), name.to_string());
29         }
30         info!("Parsed {} symbols", result.symbols().len());
31         info!("Loaded kernel: {:?}", kernel);
32         return Ok(result);
33     }
34 }
35 
36 #[derive(Debug)]
37 pub struct KernelMetadata {
38     pub kernel: PathBuf,
39     sym_collection: SymbolCollection,
40 }
41 
42 impl KernelMetadata {
43     pub fn new(kernel: PathBuf) -> Self {
44         Self {
45             kernel,
46             sym_collection: SymbolCollection::new(),
47         }
48     }
49 
50     pub fn symbols(&self) -> &[Symbol] {
51         &self.sym_collection.symbols
52     }
53 
54     pub fn sym_collection(&self) -> &SymbolCollection {
55         &self.sym_collection
56     }
57 
58     pub fn add_symbol(&mut self, sym: Sym, name: String) {
59         self.sym_collection.add_symbol(sym, name);
60     }
61 }
62 
63 #[derive(Debug)]
64 pub struct SymbolCollection {
65     symbols: Vec<Symbol>,
66 }
67 
68 impl SymbolCollection {
69     pub fn new() -> Self {
70         Self {
71             symbols: Vec::new(),
72         }
73     }
74 
75     pub fn add_symbol(&mut self, sym: Sym, name: String) {
76         self.symbols.push(Symbol::new(sym, name));
77     }
78 
79     #[allow(dead_code)]
80     pub fn len(&self) -> usize {
81         self.symbols.len()
82     }
83 
84     pub fn find_by_name(&self, name: &str) -> Option<&Symbol> {
85         self.symbols.iter().find(|sym| sym.name() == name)
86     }
87 }
88 
89 #[derive(Debug, Clone)]
90 pub struct Symbol {
91     sym: Sym,
92     name: String,
93 }
94 
95 impl Symbol {
96     pub fn new(sym: Sym, name: String) -> Self {
97         Self { sym, name }
98     }
99 
100     pub fn name(&self) -> &str {
101         &self.name
102     }
103 
104     /// Returns the virtual address of the symbol.
105     #[allow(dead_code)]
106     pub fn vaddr(&self) -> usize {
107         self.sym.st_value as usize
108     }
109 
110     /// Returns the offset of the symbol in the kernel memory.
111     pub fn memory_offset(&self) -> u64 {
112         self.sym.st_value & (!0xffff_8000_0000_0000)
113     }
114 }
115 
116 impl Deref for Symbol {
117     type Target = Sym;
118 
119     fn deref(&self) -> &Self::Target {
120         &self.sym
121     }
122 }
123