Expose PCs table to map coverage bitmap entries to the corresponding code (#1812)
This table allows users to map between coverage bitmap entries and the corresponding code in memory.
This commit is contained in:
parent
59945fbcc9
commit
e6184936ce
@ -182,12 +182,6 @@ void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
|
||||
const uintptr_t *pcs_end) {
|
||||
// unused
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
|
||||
// unused
|
||||
// TODO implement
|
||||
|
@ -1,4 +1,10 @@
|
||||
//! Sanitizer Coverage comparison functions
|
||||
|
||||
use core::{mem, ptr, slice};
|
||||
|
||||
static mut PCS_BEG: *const usize = ptr::null();
|
||||
static mut PCS_END: *const usize = ptr::null();
|
||||
|
||||
extern "C" {
|
||||
|
||||
/// Trace an 8 bit `cmp`
|
||||
@ -23,3 +29,72 @@ extern "C" {
|
||||
pub fn __sanitizer_cov_trace_switch(val: u64, cases: *const u64);
|
||||
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn __sanitizer_cov_pcs_init(pcs_beg: *const usize, pcs_end: *const usize) {
|
||||
// "The Unsafe Code Guidelines also notably defines that usize and isize are respectively compatible with uintptr_t and intptr_t defined in C."
|
||||
assert!(
|
||||
PCS_BEG.is_null(),
|
||||
"__sanitizer_cov_pcs_init can be called only once."
|
||||
);
|
||||
assert!(
|
||||
PCS_END.is_null(),
|
||||
"__sanitizer_cov_pcs_init can be called only once."
|
||||
);
|
||||
|
||||
PCS_BEG = pcs_beg;
|
||||
PCS_END = pcs_end;
|
||||
}
|
||||
|
||||
/// An entry to the `sanitizer_cov` `pc_table`
|
||||
#[repr(C, packed)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PcTableEntry {
|
||||
addr: usize,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PcTableEntry {
|
||||
/// Returns whether the PC corresponds to a function entry point.
|
||||
#[must_use]
|
||||
pub fn is_function_entry(&self) -> bool {
|
||||
self.flags == 0x1
|
||||
}
|
||||
|
||||
/// Returns the address associated with this PC.
|
||||
#[must_use]
|
||||
pub fn addr(&self) -> usize {
|
||||
self.addr
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice containing the PC table.
|
||||
#[must_use]
|
||||
pub fn sanitizer_cov_pc_table() -> Option<&'static [PcTableEntry]> {
|
||||
// SAFETY: Once PCS_BEG and PCS_END have been initialized, will not be written to again. So
|
||||
// there's no TOCTOU issue.
|
||||
unsafe {
|
||||
if PCS_BEG.is_null() || PCS_END.is_null() {
|
||||
return None;
|
||||
}
|
||||
let len = PCS_END.offset_from(PCS_BEG);
|
||||
assert!(
|
||||
len > 0,
|
||||
"Invalid PC Table bounds - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
assert_eq!(
|
||||
len % 2,
|
||||
0,
|
||||
"PC Table size is not evens - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
assert_eq!(
|
||||
(PCS_BEG as usize) % mem::align_of::<PcTableEntry>(),
|
||||
0,
|
||||
"Unaligned PC Table - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||
);
|
||||
Some(slice::from_raw_parts(
|
||||
PCS_BEG as *const PcTableEntry,
|
||||
(len / 2).try_into().unwrap(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user