(
&self,
function: &BNFunction,
filter: F,
)
| 265 | } |
| 266 | |
| 267 | pub fn adjacency_constraints<F>( |
| 268 | &self, |
| 269 | function: &BNFunction, |
| 270 | filter: F, |
| 271 | ) -> HashSet<FunctionConstraint> |
| 272 | where |
| 273 | F: Fn(&BNFunction) -> bool, |
| 274 | { |
| 275 | let view = function.view(); |
| 276 | let func_id = FunctionID::from(function); |
| 277 | let func_start = function.start(); |
| 278 | let mut constraints = HashSet::new(); |
| 279 | |
| 280 | let mut func_addr_constraint = |func_start_addr| { |
| 281 | // NOTE: We could potentially have dozens of functions all at the same start address. |
| 282 | for curr_func in &view.functions_at(func_start_addr) { |
| 283 | let curr_func_id = FunctionID::from(curr_func.as_ref()); |
| 284 | if curr_func_id != func_id && filter(curr_func.as_ref()) { |
| 285 | // NOTE: For this to work the GUID has to have already been cached. If not it will just be the symbol. |
| 286 | // Function adjacent to another function, constrain on the pattern. |
| 287 | let curr_addr_offset = (func_start_addr as i64) - func_start as i64; |
| 288 | constraints.insert(self.function_constraint(&curr_func, curr_addr_offset)); |
| 289 | } |
| 290 | } |
| 291 | }; |
| 292 | |
| 293 | let mut before_func_start = func_start; |
| 294 | for _ in 0..2 { |
| 295 | before_func_start = view.function_start_before(before_func_start); |
| 296 | func_addr_constraint(before_func_start); |
| 297 | } |
| 298 | |
| 299 | let mut after_func_start = func_start; |
| 300 | for _ in 0..2 { |
| 301 | after_func_start = view.function_start_after(after_func_start); |
| 302 | func_addr_constraint(after_func_start); |
| 303 | } |
| 304 | |
| 305 | constraints |
| 306 | } |
| 307 | |
| 308 | /// Construct a function constraint, must pass the offset at which it is located. |
| 309 | pub fn function_constraint(&self, function: &BNFunction, offset: i64) -> FunctionConstraint { |
no test coverage detected