1 // 2 // Copyright (C) 2021 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 //! Trace provider backed by ARM Coresight ETM, using simpleperf tool. 18 19 use anyhow::{anyhow, Result}; 20 use std::fs::{read_dir, remove_file}; 21 use std::path::{Path, PathBuf}; 22 use std::time::Duration; 23 use trace_provider::TraceProvider; 24 25 use crate::trace_provider; 26 27 static ETM_TRACEFILE_EXTENSION: &str = "etmtrace"; 28 static ETM_PROFILE_EXTENSION: &str = "data"; 29 30 pub struct SimpleperfEtmTraceProvider {} 31 32 impl TraceProvider for SimpleperfEtmTraceProvider { get_name(&self) -> &'static str33 fn get_name(&self) -> &'static str { 34 "simpleperf_etm" 35 } 36 trace(&self, trace_dir: &Path, tag: &str, sampling_period: &Duration)37 fn trace(&self, trace_dir: &Path, tag: &str, sampling_period: &Duration) { 38 let trace_file = trace_provider::get_path(trace_dir, tag, ETM_TRACEFILE_EXTENSION); 39 40 simpleperf_profcollect::record( 41 &*trace_file, 42 sampling_period, 43 simpleperf_profcollect::RecordScope::BOTH, 44 ); 45 } 46 process(&self, trace_dir: &Path, profile_dir: &Path) -> Result<()>47 fn process(&self, trace_dir: &Path, profile_dir: &Path) -> Result<()> { 48 read_dir(trace_dir)? 49 .filter_map(|e| e.ok()) 50 .map(|e| e.path()) 51 .filter(|e| { 52 e.is_file() 53 && e.extension() 54 .and_then(|f| f.to_str()) 55 .filter(|ext| ext == &ETM_TRACEFILE_EXTENSION) 56 .is_some() 57 }) 58 .try_for_each(|trace_file| -> Result<()> { 59 let mut profile_file = PathBuf::from(profile_dir); 60 profile_file.push( 61 trace_file 62 .file_name() 63 .ok_or_else(|| anyhow!("Malformed trace path: {}", trace_file.display()))?, 64 ); 65 profile_file.set_extension(ETM_PROFILE_EXTENSION); 66 simpleperf_profcollect::process(&trace_file, &profile_file); 67 remove_file(&trace_file)?; 68 Ok(()) 69 }) 70 } 71 } 72 73 impl SimpleperfEtmTraceProvider { supported() -> bool74 pub fn supported() -> bool { 75 simpleperf_profcollect::has_support() 76 } 77 } 78