wasmtime/
profiling_agent.rs

1use crate::prelude::*;
2
3cfg_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
18cfg_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
29cfg_if::cfg_if! {
30    // Note that the `#[cfg]` here should be kept in sync with the
31    // corresponding dependency directive on `ittapi` in `Cargo.toml`.
32    if #[cfg(all(
33        feature = "profiling",
34        target_arch = "x86_64",
35        any(
36            target_os = "windows",
37            target_os = "macos",
38            target_os = "linux",
39        ),
40    ))] {
41        mod vtune;
42        pub use vtune::new as new_vtune;
43    } else {
44        pub fn new_vtune() -> Result<Box<dyn ProfilingAgent>> {
45            if cfg!(feature = "profiling") {
46                bail!("VTune is not supported on this platform.");
47            } else {
48                bail!("VTune support disabled at compile time.");
49            }
50        }
51    }
52}
53
54cfg_if::cfg_if! {
55    if #[cfg(feature = "profile-pulley")] {
56        mod pulley;
57        pub use pulley::new as new_pulley;
58    } else {
59        pub fn new_pulley() -> Result<Box<dyn ProfilingAgent>> {
60            bail!("pulley profiling support disabled at compile time.");
61        }
62    }
63}
64
65/// Common interface for profiling tools.
66pub trait ProfilingAgent: Send + Sync + 'static {
67    fn register_function(&self, name: &str, code: &[u8]);
68
69    #[cfg(all(feature = "runtime", feature = "pulley"))]
70    fn register_interpreter(&self, interp: &crate::vm::Interpreter) {
71        let _ = interp;
72    }
73
74    fn register_module(&self, code: &[u8], custom_name: &dyn Fn(usize) -> Option<String>) {
75        use object::{File, Object as _, ObjectSection, ObjectSymbol, SectionKind, SymbolKind};
76
77        let image = match File::parse(code) {
78            Ok(image) => image,
79            Err(_) => return,
80        };
81
82        let text = match image
83            .sections()
84            .find(|s| s.kind() == SectionKind::Text || s.name() == Ok(".text"))
85        {
86            Some(section) => match section.data() {
87                Ok(data) => data,
88                Err(_) => return,
89            },
90            None => return,
91        };
92
93        for sym in image.symbols() {
94            if !sym.is_definition() {
95                continue;
96            }
97            if sym.kind() != SymbolKind::Text {
98                continue;
99            }
100            let address = sym.address();
101            let size = sym.size();
102            if size == 0 {
103                continue;
104            }
105            if let Ok(name) = sym.name() {
106                let owned;
107                let name = match custom_name(address as usize) {
108                    Some(name) => {
109                        owned = name;
110                        &owned
111                    }
112                    None => name,
113                };
114                let code = &text[address as usize..][..size as usize];
115                self.register_function(name, code)
116            }
117        }
118    }
119}
120
121pub fn new_null() -> Box<dyn ProfilingAgent> {
122    Box::new(NullProfilerAgent)
123}
124
125#[derive(Debug, Default, Clone, Copy)]
126struct NullProfilerAgent;
127
128impl ProfilingAgent for NullProfilerAgent {
129    fn register_function(&self, _name: &str, _code: &[u8]) {}
130    fn register_module(&self, _code: &[u8], _custom_name: &dyn Fn(usize) -> Option<String>) {}
131}