wasmtime_jit/
profiling.rs1#![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 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
50pub 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}