wasmtime/
profiling_agent.rs1use 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 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
65pub 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}