wasmtime_jit/
profiling.rs

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