diff --git a/Cargo.lock b/Cargo.lock index e2e4cb5906..947e5df4a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,6 +41,12 @@ version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +[[package]] +name = "apply" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f47b57fc4521e3cae26a4d45b5227f8fadee4c345be0fefd8d5d1711afb8aeb9" + [[package]] name = "arc-swap" version = "1.5.0" @@ -284,6 +290,7 @@ name = "c2rust-dynamic-instrumentation" version = "0.1.0" dependencies = [ "anyhow", + "apply", "bincode", "c2rust-analysis-rt", "cargo", diff --git a/dynamic_instrumentation/Cargo.toml b/dynamic_instrumentation/Cargo.toml index 323f93ad79..d63e270db9 100644 --- a/dynamic_instrumentation/Cargo.toml +++ b/dynamic_instrumentation/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] anyhow = "1.0" +apply = "0.3" bincode = "1.0.1" c2rust-analysis-rt = { path = "../analysis/runtime"} cargo = "0.62" diff --git a/dynamic_instrumentation/src/instrument.rs b/dynamic_instrumentation/src/instrument.rs index 793a480c4f..478a491175 100644 --- a/dynamic_instrumentation/src/instrument.rs +++ b/dynamic_instrumentation/src/instrument.rs @@ -1,4 +1,5 @@ use anyhow::Context; +use apply::Apply; use c2rust_analysis_rt::metadata::Metadata; use c2rust_analysis_rt::mir_loc::{self, EventMetadata, Func, MirLoc, MirLocId, TransferKind}; use c2rust_analysis_rt::HOOK_FUNCTIONS; @@ -20,7 +21,7 @@ use std::sync::Mutex; use crate::arg::{ArgKind, InstrumentationArg}; use crate::hooks::Hooks; -use crate::mir_utils::{has_outer_deref, remove_outer_deref, strip_all_deref}; +use crate::mir_utils::{remove_outer_deref, strip_all_deref, try_remove_outer_deref}; use crate::point::cast_ptr_to_usize; use crate::point::InstrumentationAdder; use crate::point::InstrumentationApplier; @@ -229,25 +230,21 @@ impl<'tcx> Visitor<'tcx> for InstrumentationAdder<'_, 'tcx> { } } _ if !is_region_or_unsafe_ptr(value_ty) => {} - Rvalue::AddressOf(_, p) - if has_outer_deref(p) - && place_ty(&remove_outer_deref(*p, self.tcx())).is_region_ptr() => - { - let source = remove_outer_deref(*p, self.tcx()); - // Instrument which local's address is taken - self.loc(location.successor_within_block(), copy_fn) - .arg_var(dest) - .source(&source) - .dest(&dest) - .debug_mir(location) - .add_to(self); - } Rvalue::AddressOf(_, p) => { // Instrument which local's address is taken - self.loc(location.successor_within_block(), addr_local_fn) + let source = try_remove_outer_deref(*p, self.tcx()) + .filter(|source| place_ty(source).is_region_ptr()); + let func = match source { + Some(_) => copy_fn, + None => addr_local_fn, + }; + self.loc(location.successor_within_block(), func) .arg_var(dest) - .arg_index_of(p.local) - .source(p) + .apply(|b| match source { + Some(_) => b, + None => b.arg_index_of(p.local), + }) + .source(source.as_ref().unwrap_or(p)) .dest(&dest) .debug_mir(location) .add_to(self); @@ -281,49 +278,30 @@ impl<'tcx> Visitor<'tcx> for InstrumentationAdder<'_, 'tcx> { .debug_mir(location) .add_to(self); } - Rvalue::Ref(_, bkind, p) if has_outer_deref(p) => { + Rvalue::Ref(_, bkind, p) => { // this is a reborrow or field reference, i.e. _2 = &(*_1) - let source = remove_outer_deref(*p, self.tcx()); - if let BorrowKind::Mut { .. } = bkind { + let source = try_remove_outer_deref(*p, self.tcx()); + let loc = if let BorrowKind::Mut { .. } = bkind { // Instrument which local's address is taken - self.loc(location, copy_fn) - .arg_addr_of(*p) - .source(&source) - .dest(&dest) - .debug_mir(location) - .add_to(self); + location } else { // Instrument immutable borrows by tracing the reference itself - self.loc(location.successor_within_block(), copy_fn) - .arg_var(dest) - .source(&source) - .dest(&dest) - .debug_mir(location) - .add_to(self); + location.successor_within_block() }; - } - Rvalue::Ref(_, bkind, p) if !p.is_indirect() => { - // this is a reborrow or field reference, i.e. _2 = &(*_1) - let source = remove_outer_deref(*p, self.tcx()); - if let BorrowKind::Mut { .. } = bkind { - // Instrument which local's address is taken - self.loc(location, addr_local_fn) - .arg_addr_of(*p) - .arg_index_of(p.local) - .source(&source) - .dest(&dest) - .debug_mir(location) - .add_to(self); - } else { - // Instrument immutable borrows by tracing the reference itself - self.loc(location.successor_within_block(), addr_local_fn) - .arg_var(dest) - .arg_index_of(p.local) - .source(&source) - .dest(&dest) - .debug_mir(location) - .add_to(self); + let func = match source { + Some(_) => copy_fn, + None => addr_local_fn, }; + self.loc(loc, func) + .arg_addr_of(*p) + .apply(|b| match source { + Some(_) => b, + None => b.arg_index_of(p.local), + }) + .source(source.as_ref().unwrap_or(p)) + .dest(&dest) + .debug_mir(location) + .add_to(self); } _ => (), } diff --git a/dynamic_instrumentation/src/mir_utils/deref.rs b/dynamic_instrumentation/src/mir_utils/deref.rs index 75418e7076..de5bcccc6a 100644 --- a/dynamic_instrumentation/src/mir_utils/deref.rs +++ b/dynamic_instrumentation/src/mir_utils/deref.rs @@ -3,13 +3,6 @@ use rustc_middle::{ ty::TyCtxt, }; -pub fn has_outer_deref(p: &Place) -> bool { - matches!( - p.iter_projections().last(), - Some((_, ProjectionElem::Deref)) - ) -} - /// Get the inner-most dereferenced [`Place`]. pub fn strip_all_deref<'tcx>(p: &Place<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> { let mut base_dest = p.as_ref(); @@ -27,18 +20,29 @@ pub fn strip_all_deref<'tcx>(p: &Place<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> } } -/// Strip the initital [`Deref`](ProjectionElem::Deref) -/// from a [`projection`](PlaceRef::projection) sequence. -pub fn remove_outer_deref<'tcx>(p: Place<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> { +fn try_remove_outer_deref_as_ref<'tcx>(p: &Place<'tcx>) -> Option> { // Remove outer deref if present match p.as_ref() { PlaceRef { local, - projection: &[ref base @ .., ProjectionElem::Deref], - } => Place { - local, - projection: tcx.intern_place_elems(base), - }, - _ => p, + projection: &[ref projection @ .., ProjectionElem::Deref], + } => Some(PlaceRef { local, projection }), + _ => None, } } + +/// Try to strip the initital [`Deref`](ProjectionElem::Deref) +/// from a [`projection`](PlaceRef::projection) sequence. +pub fn try_remove_outer_deref<'tcx>(p: Place<'tcx>, tcx: TyCtxt<'tcx>) -> Option> { + try_remove_outer_deref_as_ref(&p).map(|PlaceRef { local, projection }| Place { + local, + projection: tcx.intern_place_elems(projection), + }) +} + +/// Strip the initital [`Deref`](ProjectionElem::Deref) +/// from a [`projection`](PlaceRef::projection) sequence +/// if there is one. +pub fn remove_outer_deref<'tcx>(p: Place<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> { + try_remove_outer_deref(p, tcx).unwrap_or(p) +} diff --git a/dynamic_instrumentation/src/point/mod.rs b/dynamic_instrumentation/src/point/mod.rs index 136b29d2fb..c6b0a15a00 100644 --- a/dynamic_instrumentation/src/point/mod.rs +++ b/dynamic_instrumentation/src/point/mod.rs @@ -12,7 +12,7 @@ use rustc_span::def_id::DefId; use crate::{arg::InstrumentationArg, hooks::Hooks, util::Convert}; -pub use apply::InstrumentationApplier; +pub use self::apply::InstrumentationApplier; pub use cast::cast_ptr_to_usize; pub struct InstrumentationPoint<'tcx> {