wasmtime_jit/profiling/
perfmap_linux.rs1use crate::{CompiledModule, ProfilingAgent};
2use anyhow::Result;
3use std::io::{self, BufWriter, Write};
4use std::process;
5use std::{fs::File, sync::Mutex};
6use wasmtime_environ::EntityRef as _;
7
8static PERFMAP_FILE: Mutex<Option<File>> = Mutex::new(None);
10
11pub struct PerfMapAgent;
13
14impl PerfMapAgent {
15 pub fn new() -> Result<Self> {
17 let mut file = PERFMAP_FILE.lock().unwrap();
18 if file.is_none() {
19 let filename = format!("/tmp/perf-{}.map", process::id());
20 *file = Some(File::create(filename)?);
21 }
22 Ok(PerfMapAgent)
23 }
24
25 fn make_line(
26 writer: &mut dyn Write,
27 name: &str,
28 addr: *const u8,
29 len: usize,
30 ) -> io::Result<()> {
31 let sanitized_name = name.replace('\n', "_").replace('\r', "_");
34 write!(writer, "{:x} {:x} {}\n", addr as usize, len, sanitized_name)?;
35 Ok(())
36 }
37}
38
39impl ProfilingAgent for PerfMapAgent {
40 fn module_load(&self, module: &CompiledModule, _dbg_image: Option<&[u8]>) {
42 let mut file = PERFMAP_FILE.lock().unwrap();
43 let file = file.as_mut().unwrap();
44 let mut file = BufWriter::new(file);
45
46 for (idx, func) in module.finished_functions() {
47 let addr = func.as_ptr();
48 let len = func.len();
49 let name = super::debug_name(module, idx);
50 if let Err(err) = Self::make_line(&mut file, &name, addr, len) {
51 eprintln!("Error when writing function info to the perf map file: {err}");
52 return;
53 }
54 }
55
56 for (idx, func, len) in module.trampolines() {
58 let (addr, len) = (func as usize as *const u8, len);
59 let name = format!("wasm::trampoline[{}]", idx.index());
60 if let Err(err) = Self::make_line(&mut file, &name, addr, len) {
61 eprintln!("Error when writing export trampoline info to the perf map file: {err}");
62 return;
63 }
64 }
65
66 if let Err(err) = file.flush() {
67 eprintln!("Error when flushing the perf map file buffer: {err}");
68 }
69 }
70
71 fn load_single_trampoline(
72 &self,
73 name: &str,
74 addr: *const u8,
75 size: usize,
76 _pid: u32,
77 _tid: u32,
78 ) {
79 let mut file = PERFMAP_FILE.lock().unwrap();
80 let file = file.as_mut().unwrap();
81 if let Err(err) = Self::make_line(file, name, addr, size) {
82 eprintln!("Error when writing import trampoline info to the perf map file: {err}");
83 }
84 }
85}