squid/backends/clang/
concretize.rs

1use std::collections::HashMap;
2
3use crate::frontend::{
4    ao::Op,
5    ChunkContent,
6    FixedVec,
7    Pointer,
8    ProcessImage,
9    VAddr,
10};
11
12fn lookup_pointer(image: &ProcessImage, pointer: &Pointer, table: &mut HashMap<Pointer, VAddr>) {
13    if table.contains_key(pointer) {
14        return;
15    }
16
17    let addr = match pointer {
18        Pointer::Function(pointer) => {
19            let chunk = image
20                .elf(pointer.elf)
21                .unwrap()
22                .section(pointer.section)
23                .unwrap()
24                .symbol(pointer.symbol)
25                .unwrap()
26                .chunk(pointer.chunk)
27                .unwrap();
28
29            let ChunkContent::Code(func) = chunk.content() else { unreachable!() };
30            let entry = func.cfg().entry();
31
32            func.cfg().basic_block(entry).unwrap().vaddr().unwrap()
33        },
34        Pointer::BasicBlock(pointer) => {
35            let chunk = image
36                .elf(pointer.elf)
37                .unwrap()
38                .section(pointer.section)
39                .unwrap()
40                .symbol(pointer.symbol)
41                .unwrap()
42                .chunk(pointer.chunk)
43                .unwrap();
44
45            let ChunkContent::Code(func) = chunk.content() else { unreachable!() };
46
47            func.cfg().basic_block(pointer.bb).unwrap().vaddr().unwrap()
48        },
49        Pointer::Global(pointer) => {
50            let addr = image
51                .elf(pointer.elf)
52                .unwrap()
53                .section(pointer.section)
54                .unwrap()
55                .symbol(pointer.symbol)
56                .unwrap()
57                .chunk(pointer.chunk)
58                .unwrap()
59                .vaddr();
60            addr + pointer.offset as VAddr
61        },
62        Pointer::Null => 0,
63    };
64
65    table.insert(pointer.clone(), addr);
66}
67
68pub(crate) fn concretize(image: &mut ProcessImage) {
69    let mut table = HashMap::<Pointer, VAddr>::new();
70
71    /* Build lookup table for all pointers */
72    for elf in image.iter_elfs() {
73        for section in elf.iter_sections() {
74            for symbol in section.iter_symbols() {
75                for chunk in symbol.iter_chunks() {
76                    match chunk.content() {
77                        ChunkContent::Pointer(pointer) => {
78                            lookup_pointer(image, pointer, &mut table);
79                        },
80                        ChunkContent::Code(func) => {
81                            for bb in func.cfg().iter_basic_blocks() {
82                                for op in bb.ops() {
83                                    if let Op::LoadPointer {
84                                        pointer,
85                                        ..
86                                    } = op
87                                    {
88                                        lookup_pointer(image, pointer, &mut table);
89                                    }
90                                }
91                            }
92                        },
93                        ChunkContent::Data {
94                            ..
95                        } => {},
96                    }
97                }
98            }
99        }
100    }
101
102    /* Resolve every pointer */
103    for elf in image.iter_elfs_mut() {
104        for section in elf.iter_sections_mut() {
105            let perms = section.perms();
106
107            for symbol in section.iter_symbols_mut() {
108                for chunk in symbol.iter_chunks_mut() {
109                    match chunk.content_mut() {
110                        ChunkContent::Pointer(pointer) => {
111                            let addr = *table.get(pointer).unwrap();
112                            let bytes = FixedVec::lock(addr.to_le_bytes());
113                            let perms = FixedVec::lock(vec![perms; bytes.len()]);
114                            chunk.set_content(ChunkContent::Data {
115                                bytes,
116                                perms,
117                            });
118                        },
119                        ChunkContent::Code(func) => {
120                            for bb in func.cfg_mut().iter_basic_blocks_mut() {
121                                bb.set_cursor(0);
122
123                                while let Some(op) = bb.cursor_op() {
124                                    if let Op::LoadPointer {
125                                        dst,
126                                        pointer,
127                                    } = op
128                                    {
129                                        let vaddr = *table.get(pointer).unwrap();
130                                        bb.replace_op(Op::LoadVirtAddr {
131                                            dst: *dst,
132                                            vaddr,
133                                        });
134                                    }
135
136                                    if !bb.move_cursor_forward() {
137                                        break;
138                                    }
139                                }
140                            }
141                        },
142                        ChunkContent::Data {
143                            ..
144                        } => {},
145                    }
146                }
147            }
148        }
149    }
150}