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