Skip to content

Commit

Permalink
515.1606 support & minor fixes
Browse files Browse the repository at this point in the history
* 515.1606 support
* betterer assoc list rendering
* cargo fmt
* instruction hooking uses UnsafeCell instead of thread local
  • Loading branch information
willox authored May 18, 2023
1 parent a461a44 commit 46f4903
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 193 deletions.
105 changes: 61 additions & 44 deletions auxcov/src/codecov.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@ use std::panic::catch_unwind;
use std::path::{Path, PathBuf};
use std::rc::Rc;

use auxtools::*;
use auxtools::raw_types::strings::StringId;
use auxtools::*;
use dmasm::Instruction;

use grcov::{output_cobertura, CovResult, ResultTuple, FunctionMap};
use instruction_hooking::InstructionHook;
use grcov::{output_cobertura, CovResult, FunctionMap, ResultTuple};
use instruction_hooking::disassemble_env::DisassembleEnv;
use instruction_hooking::InstructionHook;

struct TrackerContext {
output_file_name: String,
proc_id_map: Vec<Option<Rc<RefCell<Vec<u64>>>>>,
filename_map: HashMap::<String, Rc<RefCell<Vec<u64>>>>
filename_map: HashMap<String, Rc<RefCell<Vec<u64>>>>,
}

pub struct Tracker {
hittable_lines: HashMap<String, HashSet<u32>>,
contexts: Vec<TrackerContext>,
total_procs: u32
total_procs: u32,
}

impl Tracker {
Expand Down Expand Up @@ -53,7 +53,7 @@ impl Tracker {
Ok(string_ref) => current_file_option = Some(string_ref),
Err(_) => current_file_option = None,
}
},
}
Instruction::DbgLine(line) => {
if let Some(current_file) = &current_file_option {
let mut file_name = current_file.to_string();
Expand All @@ -64,10 +64,13 @@ impl Tracker {
continue;
}

hittable_lines.entry(file_name).or_insert(HashSet::new()).insert(line);
hittable_lines
.entry(file_name)
.or_insert(HashSet::new())
.insert(line);
}
}
_ => { }
_ => {}
}
}
}
Expand All @@ -76,19 +79,23 @@ impl Tracker {
Tracker {
hittable_lines,
contexts: Vec::new(),
total_procs: i
total_procs: i,
}
}

pub fn init_context(&mut self, output_file_name: String) -> bool {
if self.contexts.iter().any(|context| context.output_file_name == *output_file_name) {
if self
.contexts
.iter()
.any(|context| context.output_file_name == *output_file_name)
{
return false;
}

let mut context: TrackerContext = TrackerContext {
output_file_name,
proc_id_map: Vec::new(),
filename_map: HashMap::new()
filename_map: HashMap::new(),
};

context.proc_id_map.reserve(self.total_procs as usize);
Expand Down Expand Up @@ -119,7 +126,11 @@ impl Tracker {
}

// returns true if we need to pause
pub fn process_dbg_line(&mut self, ctx: &raw_types::procs::ExecutionContext, proc_instance: &raw_types::procs::ProcInstance) {
pub fn process_dbg_line(
&mut self,
ctx: &raw_types::procs::ExecutionContext,
proc_instance: &raw_types::procs::ProcInstance,
) {
if ctx.line == 0 || !ctx.filename.valid() {
return;
}
Expand All @@ -133,9 +144,10 @@ impl Tracker {
match &known_file_name {
Some(file_name) => {
context.process_dbg_line(filename_id, proc_map_index, line, Some(file_name));
},
}
None => {
let processed_file_name = context.process_dbg_line(filename_id, proc_map_index, line, None);
let processed_file_name =
context.process_dbg_line(filename_id, proc_map_index, line, None);
if let Some((file_name, valid)) = processed_file_name {
if !valid {
break;
Expand Down Expand Up @@ -174,14 +186,14 @@ impl Tracker {
fn finalize(&mut self) -> Result<(), Vec<Error>> {
let mut errors_option = None;
for context in &self.contexts {
let result = context.finalize(); // dropping the results because what can ya do?
let result = context.finalize(); // dropping the results because what can ya do?
if let Err(error) = result {
match &mut errors_option {
None => {
let mut new_error_vec = Vec::new();
new_error_vec.push(error);
errors_option = Some(new_error_vec);
},
}
Some(existing_vec) => {
existing_vec.push(error);
}
Expand All @@ -200,22 +212,22 @@ impl Tracker {
}

impl Drop for Tracker {
fn drop(&mut self) {
fn drop(&mut self) {
let _result = self.finalize(); // dropping the result here because what can ya do?
}
}
}

impl InstructionHook for Tracker {
fn handle_instruction(&mut self, ctx: *mut raw_types::procs::ExecutionContext) {
let ctx_ref;
fn handle_instruction(&mut self, ctx: *mut raw_types::procs::ExecutionContext) {
let ctx_ref;
let proc_instance_ref;
unsafe {
ctx_ref = &*ctx;
proc_instance_ref = &*ctx_ref.proc_instance;
}

self.process_dbg_line(ctx_ref, proc_instance_ref);
}
}
}

impl TrackerContext {
Expand All @@ -224,7 +236,8 @@ impl TrackerContext {
filename_id: StringId,
proc_map_index: usize,
line: usize,
known_file_name: Option<&String>) -> Option<(String, bool)> {
known_file_name: Option<&String>,
) -> Option<(String, bool)> {
let needs_extending = self.proc_id_map.len() < proc_map_index + 1;

if !needs_extending {
Expand Down Expand Up @@ -293,7 +306,7 @@ impl TrackerContext {
hit_map[i] = current_hits + 1;

self.proc_id_map[proc_map_index] = Some(hit_map_cell.clone());
},
}
None => {
// Slower: Need to insert both file and proc
let mut hit_map = Vec::<u64>::new();
Expand All @@ -311,7 +324,8 @@ impl TrackerContext {
hit_map[i] = current_hits + 1;

let hit_map_rc = Rc::new(RefCell::new(hit_map));
self.filename_map.insert(file_name.clone(), hit_map_rc.clone());
self.filename_map
.insert(file_name.clone(), hit_map_rc.clone());
self.proc_id_map[proc_map_index] = Some(hit_map_rc);
}
}
Expand All @@ -320,28 +334,31 @@ impl TrackerContext {
}

fn finalize(&self) -> Result<(), Error> {
let result_tuples: Vec<ResultTuple> = self.filename_map.iter().map(|(file_name, hit_map)|{
let mut new_map = BTreeMap::<u32, u64>::new();
for (line_minus_one, hits) in hit_map.borrow().iter().enumerate() {
if *hits == 0 {
continue;
}

new_map.insert((line_minus_one + 1).try_into().unwrap(), *hits - 1);
}
let result_tuples: Vec<ResultTuple> = self
.filename_map
.iter()
.map(|(file_name, hit_map)| {
let mut new_map = BTreeMap::<u32, u64>::new();
for (line_minus_one, hits) in hit_map.borrow().iter().enumerate() {
if *hits == 0 {
continue;
}

let path = PathBuf::from(file_name);
(
path.clone(),
path,
CovResult {
lines: new_map,
branches: BTreeMap::default(),
functions: FunctionMap::default(),
new_map.insert((line_minus_one + 1).try_into().unwrap(), *hits - 1);
}
)
})
.collect();

let path = PathBuf::from(file_name);
(
path.clone(),
path,
CovResult {
lines: new_map,
branches: BTreeMap::default(),
functions: FunctionMap::default(),
},
)
})
.collect();

let output_path = Path::new(&self.output_file_name);
let mut path_buf = output_path.to_path_buf();
Expand Down
68 changes: 38 additions & 30 deletions auxcov/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
mod codecov;

use codecov::Tracker;
use instruction_hooking::{InstructionHook, INSTRUCTION_HOOKS};
use instruction_hooking::INSTRUCTION_HOOKS;

use std::any::{Any, TypeId};

use auxtools::*;

fn with_tracker_option<F>(f: F, create: bool)
where
F: FnOnce(&mut Tracker) {
INSTRUCTION_HOOKS.with(|hooks|{
let mut hooks_ref: std::cell::RefMut<Vec<Box<dyn InstructionHook>>> = hooks.borrow_mut();
F: FnOnce(&mut Tracker),
{
unsafe {
let hooks = INSTRUCTION_HOOKS.get_mut();

let tracker_tid = TypeId::of::<Tracker>();
let tracker_option = hooks_ref
let tracker_option = hooks
.iter_mut()
.find(|hook|(*hook).as_ref().type_id() == tracker_tid);
.find(|hook| (*hook).as_ref().type_id() == tracker_tid);

match tracker_option {
Some(existing_hook) => {
let mut_hook = existing_hook.as_mut();
let any_hook = mut_hook.as_any();
let existing_tracker = any_hook.downcast_mut::<Tracker>().unwrap();
f(existing_tracker);
},
}
None => {
if create {
let mut created_tracker = Tracker::new();
f(&mut created_tracker);
hooks_ref.push(Box::new(created_tracker));
hooks.push(Box::new(created_tracker));
}
}
}
});
}
}

// INSTRUCTION_HOOKS are cleared on shutdown so we don't need to worry about that.
Expand All @@ -46,9 +48,12 @@ fn start_code_coverage(coverage_file: Value) {
let coverage_file_string = coverage_file_string_result.unwrap();

let mut init_result = false;
with_tracker_option(|tracker|{
init_result = tracker.init_context(coverage_file_string.clone());
}, true);
with_tracker_option(
|tracker| {
init_result = tracker.init_context(coverage_file_string.clone());
},
true,
);

if !init_result {
return Err(runtime!(
Expand All @@ -70,25 +75,28 @@ fn stop_code_coverage(coverage_file: Value) {
let coverage_file_string = coverage_file_string_result.unwrap();

let mut result = Ok(Value::null());
with_tracker_option(|tracker|{
let inner_result = tracker.finalize_context(&coverage_file_string);
result = match inner_result {
Ok(had_entry) => {
if !had_entry {
Err(runtime!(
"A code coverage context for {} does not exist!",
coverage_file_string
))
} else {
Ok(Value::null())
with_tracker_option(
|tracker| {
let inner_result = tracker.finalize_context(&coverage_file_string);
result = match inner_result {
Ok(had_entry) => {
if !had_entry {
Err(runtime!(
"A code coverage context for {} does not exist!",
coverage_file_string
))
} else {
Ok(Value::null())
}
}
},
Err(error) => Err(runtime!(
"A error occurred while trying to save the coverage file: {}",
error
))
}
}, false);
Err(error) => Err(runtime!(
"A error occurred while trying to save the coverage file: {}",
error
)),
}
},
false,
);

result
}
9 changes: 6 additions & 3 deletions auxtools/src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ extern "C" {

struct Detours {
pub runtime_detour: Option<RawDetour>,
pub call_proc_detour: Option<RawDetour>
pub call_proc_detour: Option<RawDetour>,
}

impl Detours {
pub fn new() -> Self {
Self{ runtime_detour: None, call_proc_detour: None }
Self {
runtime_detour: None,
call_proc_detour: None,
}
}
}

Expand Down Expand Up @@ -99,7 +102,7 @@ pub fn init() -> Result<(), String> {
Ok(())
}

pub fn shutdown(){
pub fn shutdown() {
unsafe {
DETOURS.with(|detours_cell| {
let detours = detours_cell.borrow();
Expand Down
Loading

0 comments on commit 46f4903

Please sign in to comment.