From acab23d1e1fc1779b40caff0e710b352857ca7e8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Tue, 13 Jun 2017 21:43:37 -0600 Subject: [PATCH] Add symbol lookup (still very WIP) --- Cargo.toml | 2 +- src/elf.rs | 86 +++++++++++++++++++++++++++++++++++++++++- src/interrupt/trace.rs | 43 +++++++++++++++++++++ src/start.rs | 5 +++ 4 files changed, 133 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a6b285a6..bcc7579b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ raw-cpuid = { git = "https://github.com/gz/rust-cpuid", branch = "master" } redox_syscall = "0.1" [dependencies.goblin] -version = "0.0.8" +version = "0.0.10" default-features = false features = ["elf32", "elf64"] diff --git a/src/elf.rs b/src/elf.rs index bf484fe9..240cf56e 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -4,11 +4,13 @@ use collections::String; use core::str; +use goblin::elf::section_header::SHT_SYMTAB; + #[cfg(target_arch = "x86")] -pub use goblin::elf32::{header, program_header}; +pub use goblin::elf32::{header, program_header, section_header, sym}; #[cfg(target_arch = "x86_64")] -pub use goblin::elf64::{header, program_header}; +pub use goblin::elf64::{header, program_header, section_header, sym}; /// An ELF executable pub struct Elf<'a> { @@ -33,6 +35,14 @@ impl<'a> Elf<'a> { } } + pub fn sections(&'a self) -> ElfSections<'a> { + ElfSections { + data: self.data, + header: self.header, + i: 0 + } + } + pub fn segments(&'a self) -> ElfSegments<'a> { ElfSegments { data: self.data, @@ -41,12 +51,58 @@ impl<'a> Elf<'a> { } } + pub fn symbols(&'a self) -> Option<ElfSymbols<'a>> { + let mut symtab_opt = None; + for section in self.sections() { + if section.sh_type == SHT_SYMTAB { + symtab_opt = Some(section); + break; + } + } + + if let Some(symtab) = symtab_opt { + Some(ElfSymbols { + data: self.data, + header: self.header, + symtab: symtab, + i: 0 + }) + } else { + None + } + } + /// Get the entry field of the header pub fn entry(&self) -> usize { self.header.e_entry as usize } } +pub struct ElfSections<'a> { + data: &'a [u8], + header: &'a header::Header, + i: usize +} + +impl<'a> Iterator for ElfSections<'a> { + type Item = &'a section_header::SectionHeader; + fn next(&mut self) -> Option<Self::Item> { + if self.i < self.header.e_shnum as usize { + let item = unsafe { + &* (( + self.data.as_ptr() as usize + + self.header.e_shoff as usize + + self.i * self.header.e_shentsize as usize + ) as *const section_header::SectionHeader) + }; + self.i += 1; + Some(item) + } else { + None + } + } +} + pub struct ElfSegments<'a> { data: &'a [u8], header: &'a header::Header, @@ -71,3 +127,29 @@ impl<'a> Iterator for ElfSegments<'a> { } } } + +pub struct ElfSymbols<'a> { + data: &'a [u8], + header: &'a header::Header, + symtab: &'a section_header::SectionHeader, + i: usize +} + +impl<'a> Iterator for ElfSymbols<'a> { + type Item = &'a sym::Sym; + fn next(&mut self) -> Option<Self::Item> { + if self.i < (self.symtab.sh_size as usize) / sym::SIZEOF_SYM { + let item = unsafe { + &* (( + self.data.as_ptr() as usize + + self.symtab.sh_offset as usize + + self.i * sym::SIZEOF_SYM + ) as *const sym::Sym) + }; + self.i += 1; + Some(item) + } else { + None + } + } +} diff --git a/src/interrupt/trace.rs b/src/interrupt/trace.rs index 0778ac01..dcc1b443 100644 --- a/src/interrupt/trace.rs +++ b/src/interrupt/trace.rs @@ -22,6 +22,7 @@ pub unsafe fn stack_trace() { } println!(" {:>016X}: {:>016X}", rbp, rip); rbp = *(rbp as *const usize); + symbol_trace(rip); } else { println!(" {:>016X}: GUARD PAGE", rbp); break; @@ -31,3 +32,45 @@ pub unsafe fn stack_trace() { } } } + + +pub unsafe fn symbol_trace(addr: usize) { + use core::slice; + use core::sync::atomic::Ordering; + + use elf::Elf; + use start::{KERNEL_BASE, KERNEL_SIZE}; + + let kernel_ptr = (KERNEL_BASE.load(Ordering::SeqCst) + ::KERNEL_OFFSET) as *const u8; + let kernel_slice = slice::from_raw_parts(kernel_ptr, KERNEL_SIZE.load(Ordering::SeqCst)); + if let Ok(elf) = Elf::from(kernel_slice) { + let mut strtab_opt = None; + for section in elf.sections() { + if section.sh_type == ::goblin::elf::section_header::SHT_STRTAB { + strtab_opt = Some(section); + break; + } + } + + if let Some(symbols) = elf.symbols() { + for sym in symbols { + if addr >= sym.st_value as usize && addr < (sym.st_value + sym.st_size) as usize { + println!(" {:>016X}+{:>04X}", sym.st_value, addr - sym.st_value as usize); + + if let Some(strtab) = strtab_opt { + print!(" "); + + for &b in elf.data[strtab.sh_offset as usize + sym.st_name as usize ..].iter() { + if b == 0 { + break; + } + print!("{}", b as char); + } + + println!(""); + } + } + } + } + } +} diff --git a/src/start.rs b/src/start.rs index f95a1c3f..bf9dedac 100644 --- a/src/start.rs +++ b/src/start.rs @@ -26,6 +26,8 @@ static mut TBSS_TEST_ZERO: usize = 0; #[thread_local] static mut TDATA_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF; +pub static KERNEL_BASE: AtomicUsize = ATOMIC_USIZE_INIT; +pub static KERNEL_SIZE: AtomicUsize = ATOMIC_USIZE_INIT; pub static CPU_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub static AP_READY: AtomicBool = ATOMIC_BOOL_INIT; static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT; @@ -47,6 +49,9 @@ pub unsafe extern fn kstart(kernel_base: usize, kernel_size: usize, stack_base: assert_eq!(DATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF); } + KERNEL_BASE.store(kernel_base, Ordering::SeqCst); + KERNEL_SIZE.store(kernel_size, Ordering::SeqCst); + println!("Kernel: {:X}:{:X}", kernel_base, kernel_base + kernel_size); println!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size); -- GitLab