diff options
| author | James Johnson <jjohnsonjj1251@gmail.com> | 2025-11-02 14:02:19 -0500 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2025-11-17 17:55:09 -0500 |
| commit | 887fd85066bde0cc64d7c5c94ea09f056f163842 (patch) | |
| tree | 6d0ba9125547339e845c01505ebc285891a40f1f /rust/src/binary_view.rs | |
| parent | 89e76e22de16e873e676c93713866236035dc7fd (diff) | |
Add functions_by_name to rust implementation of BinaryViewExt
Python has the get_functions_by_name method on binary views that is
useful for finding a function by name. This adds that same method to
the rust implementation for binary views.
The implementation is essentially the same as the python version apart
from the ordering of the symbols. Python will order functions defined
in the binary before functions defined outside of the binary. The rust
implementation of `symbols_by_name` does not take an ordering for the
symbols so that is currently left out here.
Diffstat (limited to 'rust/src/binary_view.rs')
| -rw-r--r-- | rust/src/binary_view.rs | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs index 5d8f22cf..593c1c4b 100644 --- a/rust/src/binary_view.rs +++ b/rust/src/binary_view.rs @@ -1340,6 +1340,45 @@ pub trait BinaryViewExt: BinaryViewBase { } } + /// List of functions with the given name. + /// + /// There is one special case where if you pass a string of the form `sub_[0-9a-f]+` then it will lookup all + /// functions defined at the address matched by the regular expression if that symbol is not defined in the + /// database. + /// + /// # Params + /// - `name`: Name that the function should have + /// - `plat`: Optional platform that the function should be defined for. Defaults to all platforms if `None` passed. + fn functions_by_name( + &self, + name: impl IntoCStr, + plat: Option<&Platform>, + ) -> Vec<Ref<Function>> { + let name = name.to_cstr(); + let symbols = self.symbols_by_name(&*name); + let mut addresses: Vec<u64> = symbols.into_iter().map(|s| s.address()).collect(); + if addresses.is_empty() && name.to_bytes().starts_with(b"sub_") { + if let Ok(str) = name.to_str() { + if let Ok(address) = u64::from_str_radix(&str[4..], 16) { + addresses.push(address); + } + } + } + + let mut functions = Vec::new(); + + for address in addresses { + let funcs = self.functions_at(address); + for func in funcs.into_iter() { + if func.start() == address && plat.map_or(true, |p| p == func.platform().as_ref()) { + functions.push(func.clone()); + } + } + } + + functions + } + fn function_at(&self, platform: &Platform, addr: u64) -> Option<Ref<Function>> { unsafe { let raw_func_ptr = BNGetAnalysisFunction(self.as_ref().handle, platform.handle, addr); |
