squid/backends/clang/
symbol.rs

1use std::collections::HashMap;
2
3use crate::{
4    backends::clang::{
5        address::POINTER_CODE_SHIFT,
6        AddressSpace,
7    },
8    frontend::{
9        ProcessImage,
10        VAddr,
11    },
12};
13
14/// The type of a symbol in the runtime's symbol store
15#[allow(missing_docs)]
16#[derive(Debug, Clone)]
17pub enum SymbolType {
18    Function,
19    Data,
20}
21
22/// The visibility of a symbol in the runtime's symbol store
23#[allow(missing_docs)]
24#[derive(Debug, Clone)]
25pub enum SymbolVisibility {
26    Public,
27    Private,
28}
29
30/// The Symbols in the ClangRuntime are constructed from the symbols in the
31/// process image except that there is one runtime Symbol for every private +
32/// public name of a process image symbol.
33#[derive(Debug, Clone)]
34pub struct Symbol {
35    name: String,
36    visibility: SymbolVisibility,
37    address: VAddr,
38    size: usize,
39    typ: SymbolType,
40}
41
42impl Symbol {
43    /// Return true if this symbol is a function
44    pub fn is_function(&self) -> bool {
45        matches!(self.typ, SymbolType::Function)
46    }
47
48    /// Return true if this symbol holds data
49    pub fn is_data(&self) -> bool {
50        matches!(self.typ, SymbolType::Data)
51    }
52
53    /// Get the virtual address of this symbol
54    pub fn address(&self) -> VAddr {
55        self.address
56    }
57
58    /// Get the size of this symbol
59    pub fn size(&self) -> usize {
60        self.size
61    }
62
63    /// Return true if this is a publicly exported symbol (from the .dynsym)
64    pub fn is_public(&self) -> bool {
65        matches!(self.visibility, SymbolVisibility::Public)
66    }
67
68    /// Return true if this is a private symbol (from .symtab)
69    pub fn is_private(&self) -> bool {
70        matches!(self.visibility, SymbolVisibility::Private)
71    }
72
73    /// Get the name of this symbol
74    pub fn name(&self) -> &str {
75        &self.name
76    }
77
78    /// Check whether this symbol contains the given address
79    pub fn contains_address(&self, addr: VAddr) -> bool {
80        match AddressSpace::decode(addr) {
81            AddressSpace::Data(_) => self.address <= addr && addr < self.address + self.size as VAddr,
82            AddressSpace::Code(_) => {
83                let search_addr = addr >> POINTER_CODE_SHIFT;
84                let this_addr = self.address >> POINTER_CODE_SHIFT;
85                this_addr <= search_addr && search_addr < this_addr + self.size as VAddr
86            },
87        }
88    }
89}
90
91pub(crate) fn create_symbol_store(image: &ProcessImage) -> HashMap<String, Vec<Symbol>> {
92    let mut ret = HashMap::new();
93
94    for elf in image.iter_elfs() {
95        let file: &str = &elf.path().file_name().unwrap().to_string_lossy();
96
97        for section in elf.iter_sections() {
98            for symbol in section.iter_symbols() {
99                let end_addr = symbol.last_addr() + 1;
100
101                for public_name in symbol.public_names() {
102                    let address = symbol.public_name(public_name).unwrap();
103                    let size = (end_addr - address) as usize;
104                    let typ = if section.perms().is_executable() { SymbolType::Function } else { SymbolType::Data };
105
106                    ret.entry(file.to_string()).or_insert_with(Vec::new).push(Symbol {
107                        name: public_name.clone(),
108                        visibility: SymbolVisibility::Public,
109                        address,
110                        size,
111                        typ,
112                    });
113                }
114
115                for private_name in symbol.private_names() {
116                    let address = symbol.private_name(private_name).unwrap();
117                    let size = (end_addr - address) as usize;
118                    let typ = if section.perms().is_executable() { SymbolType::Function } else { SymbolType::Data };
119
120                    ret.entry(file.to_string()).or_insert_with(Vec::new).push(Symbol {
121                        name: private_name.clone(),
122                        visibility: SymbolVisibility::Private,
123                        address,
124                        size,
125                        typ,
126                    });
127                }
128            }
129        }
130    }
131
132    ret
133}