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