nm_binutils/object/
elf.rs

1use goblin::{elf, Object};
2use std::vec::Vec;
3use std::collections::HashMap;
4use crate::object::symbol::Symbol;
5
6pub struct ELF<'a> {
7    data_bytes: &'a Vec<u8>,
8    object: elf::Elf<'a>,
9}
10
11impl<'a> ELF<'a> {
12    /// Load object binary data from a &Vec<u8>.
13    pub fn new(data_bytes: &'a Vec<u8>) -> Self {
14        let elf = match Object::parse(&data_bytes).unwrap() {
15            Object::Elf(elf) => elf,
16            _ => unimplemented!(),
17        };
18
19        Self {
20            data_bytes,
21            object: elf
22        }
23    }
24
25    /// Get symbols returned encapsulated in Vec.
26    pub fn symbol_to_vec(&self) -> Vec<Symbol> {
27        let mut result = Vec::<Symbol>::new();
28        for sym in self.object.syms.iter() {
29            result.push(Symbol::new(&self.object, &sym));
30        }
31        result
32    }
33
34    /// Get symbols returned encapsulated in HashMap.
35    /// 
36    /// The key is symbol's name, the value is symbol structure.
37    pub fn symbol_to_map(&self) -> HashMap<String, Symbol> {
38        let mut result = HashMap::<String, Symbol>::new();
39
40        for sym in self.object.syms.iter() {
41            let symbol = Symbol::new(&self.object, &sym);
42            result.insert(symbol.name.to_string(), symbol);
43        }
44
45        result
46    }
47
48    pub fn get_symbol_by_name(&self, name: &str) -> Option<Symbol> {
49        for sym in self.object.syms.iter() {
50            if Symbol::name(&self.object, &sym) == name {
51                return Some(Symbol::new(&self.object, &sym));
52            }
53        }
54        None
55    }
56
57}
58
59#[cfg(test)]
60mod test {
61    use super::*;
62
63    #[test]
64    fn test_symbol_to_vec() {
65        let elf_bytes = include_bytes!("../../test/simple.amd64.elf").to_vec();
66        let elf = ELF::new(&elf_bytes);
67        for symbol in elf.symbol_to_vec() {
68            assert!(symbol.name != "main" || (symbol.address, symbol.size) == (4393, 15));
69            assert!(symbol.name != "a" || (symbol.address, symbol.size) == (4408, 11));
70            assert!(symbol.name != "b" || (symbol.address, symbol.size) == (4419, 11));
71            assert!(symbol.name != "c" || (symbol.address, symbol.size) == (4430, 11));
72            println!("{:?}", symbol);
73        }
74    }
75
76    #[test]
77    fn test_symbol_to_map() {
78        let elf_bytes = include_bytes!("../../test/simple.amd64.elf").to_vec();
79        let elf = ELF::new(&elf_bytes);
80        let symbol_map = elf.symbol_to_map();
81        {
82            let validate_sym = symbol_map.get("main").unwrap();
83            assert!((validate_sym.address, validate_sym.size) == (4393, 15));
84        }
85        {
86            let validate_sym = symbol_map.get("a").unwrap();
87            assert!((validate_sym.address, validate_sym.size) == (4408, 11));
88        }
89        {
90            let validate_sym = symbol_map.get("b").unwrap();
91            assert!((validate_sym.address, validate_sym.size) == (4419, 11));
92        }
93        {
94            let validate_sym = symbol_map.get("c").unwrap();
95            assert!((validate_sym.address, validate_sym.size) == (4430, 11));
96        }
97    }
98
99    #[test]
100    fn test_get_symbol_by_name() {
101        let elf_bytes = include_bytes!("../../test/simple.amd64.elf").to_vec();
102        let elf = ELF::new(&elf_bytes);
103        assert!(elf.get_symbol_by_name("a").is_some());
104        assert!(elf.get_symbol_by_name("d").is_none());
105    }
106}