Skip to main content

wasmtime/
profiling_agent.rs

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