squid/backends/clang/
symbol.rs1use 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#[allow(missing_docs)]
16#[derive(Debug, Clone)]
17pub enum SymbolType {
18 Function,
19 Data,
20}
21
22#[allow(missing_docs)]
24#[derive(Debug, Clone)]
25pub enum SymbolVisibility {
26 Public,
27 Private,
28}
29
30#[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 pub fn is_function(&self) -> bool {
45 matches!(self.typ, SymbolType::Function)
46 }
47
48 pub fn is_data(&self) -> bool {
50 matches!(self.typ, SymbolType::Data)
51 }
52
53 pub fn address(&self) -> VAddr {
55 self.address
56 }
57
58 pub fn size(&self) -> usize {
60 self.size
61 }
62
63 pub fn is_public(&self) -> bool {
65 matches!(self.visibility, SymbolVisibility::Public)
66 }
67
68 pub fn is_private(&self) -> bool {
70 matches!(self.visibility, SymbolVisibility::Private)
71 }
72
73 pub fn name(&self) -> &str {
75 &self.name
76 }
77
78 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}