diff options
| author | Josh Ferrell <josh@vector35.com> | 2024-06-17 15:05:35 -0400 |
|---|---|---|
| committer | Josh Ferrell <josh@vector35.com> | 2024-06-21 10:38:39 -0400 |
| commit | 38e719b90b89aa45ebeda1c41dc9a9edd42cdc90 (patch) | |
| tree | f1792ff8153b18da5a3e8bfeb6c98fcce9af7994 /rust/examples | |
| parent | aa9c28e91b5c2ef6ab0e2aff7e44f8a16de998f7 (diff) | |
Demangle function names recovered from DWARF
Diffstat (limited to 'rust/examples')
| -rw-r--r-- | rust/examples/dwarf/dwarf_import/Cargo.toml | 2 | ||||
| -rw-r--r-- | rust/examples/dwarf/dwarf_import/src/functions.rs | 38 |
2 files changed, 39 insertions, 1 deletions
diff --git a/rust/examples/dwarf/dwarf_import/Cargo.toml b/rust/examples/dwarf/dwarf_import/Cargo.toml index 715838a7..1dfae181 100644 --- a/rust/examples/dwarf/dwarf_import/Cargo.toml +++ b/rust/examples/dwarf/dwarf_import/Cargo.toml @@ -13,3 +13,5 @@ binaryninja = { path = "../../../" } gimli = "0.28" log = "0.4.20" iset = "0.2.2" +cpp_demangle = "0.4.3" +regex = "1" diff --git a/rust/examples/dwarf/dwarf_import/src/functions.rs b/rust/examples/dwarf/dwarf_import/src/functions.rs index fabcc613..fa1755fa 100644 --- a/rust/examples/dwarf/dwarf_import/src/functions.rs +++ b/rust/examples/dwarf/dwarf_import/src/functions.rs @@ -12,11 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::OnceLock; + use crate::dwarfdebuginfo::{DebugInfoBuilder, DebugInfoBuilderContext, TypeUID}; use crate::helpers::*; use crate::types::get_type; +use binaryninja::templatesimplifier::simplify_str_to_str; +use cpp_demangle::DemangleOptions; use gimli::{constants, DebuggingInformationEntry, Reader, Unit}; +use regex::Regex; fn get_parameters<R: Reader<Offset = usize>>( unit: &Unit<R>, @@ -69,11 +74,42 @@ pub(crate) fn parse_function_entry<R: Reader<Offset = usize>>( debug_info_builder: &mut DebugInfoBuilder, ) -> Option<usize> { // Collect function properties (if they exist in this DIE) - let full_name = debug_info_builder_context.get_name(unit, entry); let raw_name = get_raw_name(unit, entry, debug_info_builder_context); let return_type = get_type(unit, entry, debug_info_builder_context, debug_info_builder); let address = get_start_address(unit, entry, debug_info_builder_context); let (parameters, variable_arguments) = get_parameters(unit, entry, debug_info_builder_context, debug_info_builder); + // If we have a raw name, it might be mangled, see if we can demangle it into full_name + // raw_name should contain a superset of the info we have in full_name + let mut full_name = None; + if let Some(possibly_mangled_name) = &raw_name { + if possibly_mangled_name.starts_with('_') { + static OPTIONS_MEM: OnceLock<DemangleOptions> = OnceLock::new(); + let demangle_options = OPTIONS_MEM.get_or_init(|| { + DemangleOptions::new() + .no_return_type() + .hide_expression_literal_types() + .no_params() + }); + + static ABI_REGEX_MEM: OnceLock<Regex> = OnceLock::new(); + let abi_regex = ABI_REGEX_MEM.get_or_init(|| { + Regex::new(r"\[abi:v\d+\]").unwrap() + }); + if let Ok(sym) = cpp_demangle::Symbol::new(possibly_mangled_name) { + if let Ok(demangled) = sym.demangle(demangle_options) { + let cleaned = abi_regex.replace_all(&demangled, ""); + let simplified = simplify_str_to_str(&cleaned); + full_name = Some(simplified.to_string()); + } + } + } + } + + // If we didn't demangle the raw name, fetch the name given + if full_name.is_none() { + full_name = debug_info_builder_context.get_name(unit, entry) + } + debug_info_builder.insert_function(full_name, raw_name, return_type, address, ¶meters, variable_arguments) } |
