diff options
Diffstat (limited to 'tools/profiler/rust-helper/src/lib.rs')
-rw-r--r-- | tools/profiler/rust-helper/src/lib.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/tools/profiler/rust-helper/src/lib.rs b/tools/profiler/rust-helper/src/lib.rs new file mode 100644 index 0000000000..a22e631852 --- /dev/null +++ b/tools/profiler/rust-helper/src/lib.rs @@ -0,0 +1,111 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +extern crate memmap; +extern crate rustc_demangle; +extern crate thin_vec; +extern crate uuid; + +#[cfg(feature = "parse_elf")] +extern crate goblin; +#[cfg(feature = "parse_elf")] +extern crate object; + +mod compact_symbol_table; + +#[cfg(feature = "parse_elf")] +mod elf; + +#[cfg(feature = "parse_elf")] +use memmap::MmapOptions; +#[cfg(feature = "parse_elf")] +use std::fs::File; + +use compact_symbol_table::CompactSymbolTable; +use rustc_demangle::try_demangle; +use std::ffi::CStr; +use std::mem; +use std::os::raw::c_char; +use std::ptr; + +#[cfg(feature = "parse_elf")] +pub fn get_compact_symbol_table_from_file( + debug_path: &str, + breakpad_id: Option<&str>, +) -> Option<CompactSymbolTable> { + let file = File::open(debug_path).ok()?; + let buffer = unsafe { MmapOptions::new().map(&file).ok()? }; + elf::get_compact_symbol_table(&buffer, breakpad_id) +} + +#[cfg(not(feature = "parse_elf"))] +pub fn get_compact_symbol_table_from_file( + _debug_path: &str, + _breakpad_id: Option<&str>, +) -> Option<CompactSymbolTable> { + None +} + +#[no_mangle] +pub extern "C" fn profiler_get_symbol_table( + debug_path: *const c_char, + breakpad_id: *const c_char, + symbol_table: &mut CompactSymbolTable, +) -> bool { + let debug_path = unsafe { CStr::from_ptr(debug_path).to_string_lossy() }; + let breakpad_id = if breakpad_id.is_null() { + None + } else { + match unsafe { CStr::from_ptr(breakpad_id).to_str() } { + Ok(s) => Some(s), + Err(_) => return false, + } + }; + + match get_compact_symbol_table_from_file(&debug_path, breakpad_id.map(|id| id.as_ref())) { + Some(mut st) => { + std::mem::swap(symbol_table, &mut st); + true + } + None => false, + } +} + +#[no_mangle] +pub extern "C" fn profiler_demangle_rust( + mangled: *const c_char, + buffer: *mut c_char, + buffer_len: usize, +) -> bool { + assert!(!mangled.is_null()); + assert!(!buffer.is_null()); + + if buffer_len == 0 { + return false; + } + + let buffer: *mut u8 = unsafe { mem::transmute(buffer) }; + let mangled = match unsafe { CStr::from_ptr(mangled).to_str() } { + Ok(s) => s, + Err(_) => return false, + }; + + match try_demangle(mangled) { + Ok(demangled) => { + let mut demangled = format!("{:#}", demangled); + if !demangled.is_ascii() { + return false; + } + demangled.truncate(buffer_len - 1); + + let bytes = demangled.as_bytes(); + unsafe { + ptr::copy(bytes.as_ptr(), buffer, bytes.len()); + ptr::write(buffer.offset(bytes.len() as isize), 0); + } + true + } + Err(_) => false, + } +} |