This is an automated email from the ASF dual-hosted git repository. dingyu pushed a commit to branch fix-sgx-cov in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git
commit 9524c741deac7fc0ff58441f63645fecbb7f0325 Author: Yu Ding <[email protected]> AuthorDate: Mon Dec 28 21:14:55 2020 -0800 fix sgx-cov to be compatible with LLVM 10 profiler API --- samplecode/sgx-cov/Makefile | 4 +- samplecode/sgx-cov/enclave/enclave-cov-rustc | 0 samplecode/sgx-cov/enclave/llvm-gcov | 2 +- samplecode/sgx-cov/enclave/src/lib.rs | 3 + sgx_cov/lib.rs | 233 ++++++++++++++++----------- 5 files changed, 141 insertions(+), 101 deletions(-) diff --git a/samplecode/sgx-cov/Makefile b/samplecode/sgx-cov/Makefile index f6aa06b..e5b9f63 100644 --- a/samplecode/sgx-cov/Makefile +++ b/samplecode/sgx-cov/Makefile @@ -160,8 +160,8 @@ enclave: .PHONY: gen_cov_html gen_cov_html: - lcov --gcov-tool $(PWD)/enclave/llvm-gcov --rc lcov_branch_coverage=1 --rc lcov_excl_line=assert --capture --directory ${Target_Dir} -o ./all.tag.info - lcov --gcov-tool $(PWD)/enclave/llvm-gcov --rc lcov_branch_coverage=1 --rc lcov_excl_line=assert --extract all.tag.info `find "$$(cd enclave/src; pwd)" -name "*.rs"` -o final.info + lcov --gcov-tool gcov --rc lcov_branch_coverage=1 --rc lcov_excl_line=assert --capture --directory ${Target_Dir} -o ./all.tag.info + lcov --gcov-tool gcov --rc lcov_branch_coverage=1 --rc lcov_excl_line=assert --extract all.tag.info `find "$$(cd enclave/src; pwd)" -name "*.rs"` -o final.info genhtml --branch-coverage --demangle-cpp --legend ./final.info -o ./html/ --ignore-errors source .PHONY: clean diff --git a/samplecode/sgx-cov/enclave/enclave-cov-rustc b/samplecode/sgx-cov/enclave/enclave-cov-rustc old mode 100644 new mode 100755 diff --git a/samplecode/sgx-cov/enclave/llvm-gcov b/samplecode/sgx-cov/enclave/llvm-gcov old mode 100644 new mode 100755 index 0191fd3..d5923e4 --- a/samplecode/sgx-cov/enclave/llvm-gcov +++ b/samplecode/sgx-cov/enclave/llvm-gcov @@ -1,2 +1,2 @@ #!/bin/sh -e -llvm-cov gcov $* \ No newline at end of file +llvm-cov gcov $* diff --git a/samplecode/sgx-cov/enclave/src/lib.rs b/samplecode/sgx-cov/enclave/src/lib.rs index 420a505..5af1431 100644 --- a/samplecode/sgx-cov/enclave/src/lib.rs +++ b/samplecode/sgx-cov/enclave/src/lib.rs @@ -99,5 +99,8 @@ pub extern "C" fn say_something(some_string: *const u8, some_len: usize) -> sgx_ // Ocall to normal world for output println!("{}", &hello_string); + #[cfg(feature = "cov")] + sgx_cov::cov_writeout(); + sgx_status_t::SGX_SUCCESS } diff --git a/sgx_cov/lib.rs b/sgx_cov/lib.rs index 34b7dd0..5a21b51 100644 --- a/sgx_cov/lib.rs +++ b/sgx_cov/lib.rs @@ -45,9 +45,14 @@ use std::sync::{Once, SgxMutex}; use std::untrusted::fs::{copy, File, OpenOptions}; static INIT: Once = Once::new(); +const GCOV_DATA_MAGIC: u32 = 0x6763_6461; +const GCOV_TAG_FUNCTION: u32 = 0x0100_0000; +const GCOV_TAG_COUNTER_ARCS: u32 = 0x01a1_0000; +const GCOV_TAG_OBJECT_SUMMARY: u32 = 0xa100_0000; +const GCOV_TAG_PROGRAM_SUMMARY: u32 = 0xa300_0000; lazy_static! { - static ref GCDA_FILE: SgxMutex<c_int> = SgxMutex::new(-1); + static ref GCDA_FILE: SgxMutex<(c_int, c_int)> = SgxMutex::new((-1, -1)); static ref WROUT_FNS: SgxMutex<Vec<extern "C" fn()>> = SgxMutex::new(Vec::new()); static ref RND: SgxMutex<u32> = SgxMutex::new(0); } @@ -59,7 +64,11 @@ pub fn cov_writeout() { } #[no_mangle] -pub extern "C" fn llvm_gcov_init(writeout: extern "C" fn(), _flush: extern "C" fn()) { +pub extern "C" fn llvm_gcov_init( + writeout: extern "C" fn(), + _flush: extern "C" fn(), + _reset: extern "C" fn(), +) { INIT.call_once(|| { let mut rng = sgx_rand::thread_rng(); let mut rnd = RND.lock().unwrap(); @@ -71,109 +80,89 @@ pub extern "C" fn llvm_gcov_init(writeout: extern "C" fn(), _flush: extern "C" f #[no_mangle] pub extern "C" fn llvm_gcda_summary_info() { - match GCDA_FILE.lock() { - Ok(fd) => { - let mut file = unsafe { File::from_raw_fd(*fd) }; - - let summary_tag: u32 = 0xa1; - file.write_all(&summary_tag.to_be_bytes()).unwrap(); - let len: u32 = 9; - file.write_all(&len.to_le_bytes()).unwrap(); - let zero: u32 = 0; - let one: u32 = 1; - file.write_all(&zero.to_le_bytes()).unwrap(); - file.write_all(&zero.to_le_bytes()).unwrap(); - file.write_all(&one.to_le_bytes()).unwrap(); - for _ in 0..(len - 3) { - file.write_all(&zero.to_le_bytes()).unwrap(); + GCDA_FILE + .lock() + .map_or_else( + |e| panic!("llvm_gcda_summary_info failed {:?}", e), + |tup| Ok((unsafe { File::from_raw_fd(tup.0) }, tup.1)), + ) + .and_then(|(mut file, gcov_version)| { + if gcov_version >= 90 { + file.write_all(&GCOV_TAG_OBJECT_SUMMARY.to_le_bytes())?; + file.write_all(&(2 as u32).to_le_bytes())?; + file.write_all(&(1 as u32).to_le_bytes())?; // runs. we never merge so it's always 1 + file.write_all(&(0 as u32).to_le_bytes())?; // sum_max + } else { + file.write_all(&GCOV_TAG_PROGRAM_SUMMARY.to_le_bytes())?; + file.write_all(&(3 as u32).to_le_bytes())?; + file.write_all(&(0 as u32).to_le_bytes())?; + file.write_all(&(0 as u32).to_le_bytes())?; + file.write_all(&(1 as u32).to_le_bytes())?; // runs. we never merge so it's always 1 } - let prog_tag: u32 = 0xa3; - file.write_all(&prog_tag.to_be_bytes()).unwrap(); - file.write_all(&zero.to_le_bytes()).unwrap(); - - // Prevent it from drop let _ = file.into_raw_fd(); - } - Err(_) => panic!("llvm_gcda_emit_arcs failed"), - } + Ok(()) + }) + .unwrap_or_else(|e: std::io::Error| panic!("llvm_gcda_summary_info failed {:?}", e)) } #[no_mangle] pub extern "C" fn llvm_gcda_emit_arcs(num_counters: u32, counters: *const u64) { + // we never merge + // so `counters` is no longer * mut u64 let cnts = unsafe { slice::from_raw_parts(counters, num_counters as usize) }; - match GCDA_FILE.lock() { - Ok(fd) => { - let mut file = unsafe { File::from_raw_fd(*fd) }; - let arcs_tag: u32 = 0xa101; - file.write_all(&arcs_tag.to_be_bytes()).unwrap(); + GCDA_FILE + .lock() + .map_or_else( + |e| panic!("llvm_gcda_emit_arcs failed {:?}", e), + |tup| Ok(unsafe { File::from_raw_fd(tup.0) }), + ) + .and_then(|mut file| { + file.write_all(&GCOV_TAG_COUNTER_ARCS.to_le_bytes())?; let len: u32 = num_counters * 2; - file.write_all(&len.to_le_bytes()).unwrap(); - for i in 0..num_counters { - file.write_all(&cnts[i as usize].to_le_bytes()).unwrap(); + file.write_all(&len.to_le_bytes())?; + for c in cnts { + file.write_all(&c.to_le_bytes())?; } - - // Prevent it from drop let _ = file.into_raw_fd(); - } - Err(_) => panic!("llvm_gcda_emit_arcs failed"), - } + Ok(()) + }) + .unwrap_or_else(|e: std::io::Error| panic!("llvm_gcda_emit_arcs failed {:?}", e)) } #[no_mangle] -pub extern "C" fn llvm_gcda_emit_function( - ident: u32, - raw_func_name: *const c_char, - fchecksum: u32, - use_extra_checksum: u8, - cfg_checksum: u32, -) { - let func_name_str: &CStr = unsafe { CStr::from_ptr(raw_func_name) }; - let func_name = func_name_str.to_str().unwrap(); +pub extern "C" fn llvm_gcda_emit_function(ident: u32, func_checksum: u32, cfg_checksum: u32) { let mut len: u32 = 2; - if use_extra_checksum != 0 { + let use_extra_checksum: bool = GCDA_FILE.lock().map(|tup| tup.1 >= 47).unwrap(); + + if use_extra_checksum { len += 1; } - let str_len = (1 + func_name.len() / 4) as u32; - len += str_len; - - match GCDA_FILE.lock() { - Ok(fd) => { - let mut file = unsafe { File::from_raw_fd(*fd) }; - - let func_tag: u32 = 1; - file.write_all(&func_tag.to_be_bytes()).unwrap(); - file.write_all(&len.to_le_bytes()).unwrap(); - file.write_all(&ident.to_le_bytes()).unwrap(); - file.write_all(&fchecksum.to_le_bytes()).unwrap(); - if use_extra_checksum != 0 { - file.write_all(&cfg_checksum.to_le_bytes()).unwrap(); - } - file.write_all(&str_len.to_le_bytes()).unwrap(); - file.write_all(func_name.as_bytes()).unwrap(); - let zero: u8 = 0; - let padding_size = 4 - func_name.len() % 4; - for _ in 0..padding_size { - file.write_all(&zero.to_le_bytes()).unwrap(); + GCDA_FILE + .lock() + .map_or_else( + |e| panic!("llvm_gcda_emit_function failed {:?}", e), + |tup| Ok(unsafe { File::from_raw_fd(tup.0) }), + ) + .and_then(|mut file| { + file.write_all(&GCOV_TAG_FUNCTION.to_le_bytes())?; + file.write_all(&len.to_le_bytes())?; + file.write_all(&ident.to_le_bytes())?; + file.write_all(&func_checksum.to_le_bytes())?; + if use_extra_checksum { + file.write_all(&cfg_checksum.to_le_bytes())?; } - - // Prevent it from drop let _ = file.into_raw_fd(); - } - Err(_) => panic!("llvm_gcda_emit_function failed"), - } + Ok(()) + }) + .unwrap_or_else(|e: std::io::Error| panic!("llvm_gcda_emit_function failed {:?}", e)) } #[no_mangle] -pub extern "C" fn llvm_gcda_start_file( - raw_file_name: *const c_char, - ver: *const u8, - checksum: u32, -) { - let file_name_str: &CStr = unsafe { CStr::from_ptr(raw_file_name) }; +pub extern "C" fn llvm_gcda_start_file(orig_filename: *const c_char, version: u32, checksum: u32) { + let file_name_str: &CStr = unsafe { CStr::from_ptr(orig_filename) }; let file_name = file_name_str.to_str().unwrap(); - let version = unsafe { slice::from_raw_parts(ver, 4) }; let mut prefix = String::from(file_name); prefix.truncate(file_name.len() - 5); @@ -182,35 +171,83 @@ pub extern "C" fn llvm_gcda_start_file( let new_gcno_name = format!("{}.{:08x}.gcno", prefix, *rnd); let new_gcda_name = format!("{}.{:08x}.gcda", prefix, *rnd); - match GCDA_FILE.lock() { - Ok(mut fd) => { - copy(orig_gcno_name, new_gcno_name).unwrap(); + GCDA_FILE + .lock() + .map_or_else( + |e| panic!("llvm_gcda_emit_function failed {:?}", e), + |tup| Ok(tup), + ) + .and_then(|mut tup| { + copy(orig_gcno_name, new_gcno_name)?; let mut file = match OpenOptions::new() .write(true) .append(false) .open(&new_gcda_name) { Ok(file) => file, - Err(_) => File::create(&new_gcda_name).unwrap(), + Err(_) => File::create(&new_gcda_name)?, + }; + + let c3: u8 = ((version >> 24) & 0x000000FF) as u8; + let c2: u8 = ((version >> 16) & 0x000000FF) as u8; + let c1: u8 = ((version >> 8) & 0x000000FF) as u8; + let parsed_gcov_version: i32 = if c3 >= 'A' as u8 { + ((c3 - 'A' as u8) as i32) * 100 + + ((c2 - '0' as u8) as i32) * 10 + + (c1 - '0' as u8) as i32 + } else { + ((c3 - '0' as u8) as i32) * 10 + (c1 - '0' as u8) as i32 }; - file.write_all(b"adcg").unwrap(); - file.write_all(version).unwrap(); + + tup.1 = parsed_gcov_version; + + file.write_all(&GCOV_DATA_MAGIC.to_le_bytes()).unwrap(); + file.write_all(&parsed_gcov_version.to_le_bytes()).unwrap(); file.write_all(&checksum.to_le_bytes()).unwrap(); - *fd = file.into_raw_fd(); - } - Err(_) => panic!("llvm_gcda_start_file failed!"), - } + + tup.0 = file.into_raw_fd(); + + Ok(()) + }) + .unwrap_or_else(|e: std::io::Error| panic!("llvm_gcda_start_file failed {:?}", e)) } #[no_mangle] pub extern "C" fn llvm_gcda_end_file() { - match GCDA_FILE.lock() { - Ok(fd) => { - let mut file = unsafe { File::from_raw_fd(*fd) }; - let eof: u64 = 0; - file.write_all(&eof.to_be_bytes()).unwrap(); - // Let it drop + if let Ok(ref tup) = GCDA_FILE.lock() { + let fd = &tup.0; + let mut file = unsafe { File::from_raw_fd(*fd) }; + let eof: u64 = 0; + file.write_all(&eof.to_be_bytes()).unwrap(); + // Let it drop + } else { + panic!("llvm_gcda_end_file failed!"); + } +} + +#[no_mangle] +pub extern "C" fn llvm_gcda_increment_indirect_counter( + predecessor: *mut u32, + counters: *mut *mut u64, +) { + let counter: *mut u64; + let pred: u32; + + if predecessor.is_null() || counters.is_null() { + return; + } + + pred = unsafe { *predecessor }; + + if pred == 0xFFFF_FFFF { + return; + } + + counter = unsafe { *counters.offset(pred as isize) }; + + if !counter.is_null() { + unsafe { + *counter = *counter + 1; } - Err(_) => panic!("llvm_gcda_end_file failed!"), } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
