summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2024-06-17 15:05:35 -0400
committerJosh Ferrell <josh@vector35.com>2024-06-21 10:38:39 -0400
commit38e719b90b89aa45ebeda1c41dc9a9edd42cdc90 (patch)
treef1792ff8153b18da5a3e8bfeb6c98fcce9af7994 /rust
parentaa9c28e91b5c2ef6ab0e2aff7e44f8a16de998f7 (diff)
Demangle function names recovered from DWARF
Diffstat (limited to 'rust')
-rw-r--r--rust/Cargo.lock11
-rw-r--r--rust/examples/dwarf/dwarf_import/Cargo.toml2
-rw-r--r--rust/examples/dwarf/dwarf_import/src/functions.rs38
3 files changed, 50 insertions, 1 deletions
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index 7e03d311..8e18b38a 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -234,6 +234,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
+name = "cpp_demangle"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
name = "crc32fast"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -319,10 +328,12 @@ name = "dwarf_import"
version = "0.1.0"
dependencies = [
"binaryninja",
+ "cpp_demangle",
"dwarfreader",
"gimli",
"iset",
"log",
+ "regex",
]
[[package]]
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, &parameters, variable_arguments)
}