1 use crate::prelude::*; 2 3 cfg_if::cfg_if! { 4 if #[cfg(all(feature = "profiling", target_os = "linux"))] { 5 mod jitdump; 6 pub use jitdump::new as new_jitdump; 7 } else { 8 pub fn new_jitdump() -> Result<Box<dyn ProfilingAgent>> { 9 if cfg!(feature = "profiling") { 10 bail!("jitdump is not supported on this platform"); 11 } else { 12 bail!("jitdump support disabled at compile time"); 13 } 14 } 15 } 16 } 17 18 cfg_if::cfg_if! { 19 if #[cfg(all(unix, feature = "std"))] { 20 mod perfmap; 21 pub use perfmap::new as new_perfmap; 22 } else { 23 pub fn new_perfmap() -> Result<Box<dyn ProfilingAgent>> { 24 bail!("perfmap support not supported on this platform"); 25 } 26 } 27 } 28 29 cfg_if::cfg_if! { 30 // Note: VTune support is disabled on windows mingw because the ittapi crate doesn't compile 31 // there; see also https://github.com/bytecodealliance/wasmtime/pull/4003 for rationale. 32 if #[cfg(all(feature = "profiling", target_arch = "x86_64", not(any(target_os = "android", all(target_os = "windows", target_env = "gnu")))))] { 33 mod vtune; 34 pub use vtune::new as new_vtune; 35 } else { 36 pub fn new_vtune() -> Result<Box<dyn ProfilingAgent>> { 37 if cfg!(feature = "profiling") { 38 bail!("VTune is not supported on this platform."); 39 } else { 40 bail!("VTune support disabled at compile time."); 41 } 42 } 43 } 44 } 45 46 /// Common interface for profiling tools. 47 pub trait ProfilingAgent: Send + Sync + 'static { 48 fn register_function(&self, name: &str, code: &[u8]); 49 50 fn register_module(&self, code: &[u8], custom_name: &dyn Fn(usize) -> Option<String>) { 51 use object::{File, Object as _, ObjectSection, ObjectSymbol, SectionKind, SymbolKind}; 52 53 let image = match File::parse(code) { 54 Ok(image) => image, 55 Err(_) => return, 56 }; 57 58 let text = match image.sections().find(|s| s.kind() == SectionKind::Text) { 59 Some(section) => match section.data() { 60 Ok(data) => data, 61 Err(_) => return, 62 }, 63 None => return, 64 }; 65 66 for sym in image.symbols() { 67 if !sym.is_definition() { 68 continue; 69 } 70 if sym.kind() != SymbolKind::Text { 71 continue; 72 } 73 let address = sym.address(); 74 let size = sym.size(); 75 if size == 0 { 76 continue; 77 } 78 if let Ok(name) = sym.name() { 79 let owned; 80 let name = match custom_name(address as usize) { 81 Some(name) => { 82 owned = name; 83 &owned 84 } 85 None => name, 86 }; 87 let code = &text[address as usize..][..size as usize]; 88 self.register_function(name, code) 89 } 90 } 91 } 92 } 93 94 pub fn new_null() -> Box<dyn ProfilingAgent> { 95 Box::new(NullProfilerAgent) 96 } 97 98 #[derive(Debug, Default, Clone, Copy)] 99 struct NullProfilerAgent; 100 101 impl ProfilingAgent for NullProfilerAgent { 102 fn register_function(&self, _name: &str, _code: &[u8]) {} 103 fn register_module(&self, _code: &[u8], _custom_name: &dyn Fn(usize) -> Option<String>) {} 104 } 105