mirror of
https://github.com/radareorg/radeco.git
synced 2026-11-07 06:36:01 -10:00
fixup: compiler error fixes
This commit is contained in:
1 parent
7ada2d24fd
commit
08e8bf8ac0
30 files changed
+194
-152
No files matched your search
@@ -4,3 +4,4 @@ Cargo.lock
|
||||
outputs
|
||||
*.dot
|
||||
*.orig
|
||||
radare2-r2pipe-api
|
||||
@@ -7,6 +7,7 @@ edition = "2018"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[dependencies.r2api]
|
||||
package = "r2papi"
|
||||
git = "https://github.com/radare/radare2-r2pipe-api"
|
||||
|
||||
[dependencies.r2pipe]
|
||||
|
||||
@@ -15,6 +15,7 @@ path = "src/lib.rs"
|
||||
[features]
|
||||
default = []
|
||||
trace_log = ["log", "env_logger"]
|
||||
profile = []
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.9.2"
|
||||
@@ -48,6 +49,7 @@ env_logger = { version = "0.7", optional = true }
|
||||
git = "https://github.com/radareorg/r2pipe.rs"
|
||||
|
||||
[dependencies.r2api]
|
||||
package = "r2papi"
|
||||
git = "https://github.com/radare/radare2-r2pipe-api"
|
||||
#path = "../radare2-r2pipe-api/rust/"
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ impl<T: Clone + Debug + Hash + Eq + Copy> ConstraintSet<T> {
|
||||
let constraint = self.set.pop_front().expect("Cannot be `None`");
|
||||
// Match to see if this is an Eq constraint or an assert
|
||||
let res = match constraint {
|
||||
Constraint::Equality(_, box _) => self.solve_eq(&constraint),
|
||||
Constraint::Equality(_, _) => self.solve_eq(&constraint),
|
||||
Constraint::Assertion(_) => self.solve_assert(&constraint),
|
||||
Constraint::AssertEquivalence(_) => self.solve_equivalence(&constraint),
|
||||
_ => false,
|
||||
@@ -131,18 +131,18 @@ impl<T: Clone + Debug + Hash + Eq + Copy> ConstraintSet<T> {
|
||||
|
||||
fn solve_eq(&mut self, constraint: &Constraint<T>) -> bool {
|
||||
match *constraint {
|
||||
Constraint::Equality(ni, box ref cs) => {
|
||||
match *cs {
|
||||
Constraint::Equality(ni, ref cs) => {
|
||||
match **cs {
|
||||
Constraint::Value(vt) => {
|
||||
self.bindings.insert(ni, vt);
|
||||
true
|
||||
}
|
||||
Constraint::Union(op1, op2) => {
|
||||
Constraint::Union(op1, ref op2) => {
|
||||
match self.bvalue(ni) {
|
||||
ValueType::Scalar => {
|
||||
// Both, op1 and op2, are scalars
|
||||
self.bindings.insert(op1, ValueType::Scalar);
|
||||
self.bindings.insert(op2, ValueType::Scalar);
|
||||
self.bindings.insert(*op2, ValueType::Scalar);
|
||||
true
|
||||
}
|
||||
ValueType::Reference => {
|
||||
@@ -154,13 +154,13 @@ impl<T: Clone + Debug + Hash + Eq + Copy> ConstraintSet<T> {
|
||||
Box::new(Constraint::Value(ValueType::Reference)),
|
||||
)),
|
||||
Box::new(Constraint::Equality(
|
||||
op2,
|
||||
*op2,
|
||||
Box::new(Constraint::Value(ValueType::Scalar)),
|
||||
)),
|
||||
)),
|
||||
Box::new(Constraint::And(
|
||||
Box::new(Constraint::Equality(
|
||||
op2,
|
||||
*op2,
|
||||
Box::new(Constraint::Value(ValueType::Reference)),
|
||||
)),
|
||||
Box::new(Constraint::Equality(
|
||||
@@ -175,7 +175,7 @@ impl<T: Clone + Debug + Hash + Eq + Copy> ConstraintSet<T> {
|
||||
ValueType::Unresolved => {
|
||||
// Look at the Union
|
||||
let op1_vt = self.bvalue(op1);
|
||||
let op2_vt = self.bvalue(op2);
|
||||
let op2_vt = self.bvalue(*op2);
|
||||
let (vt, retval) = match (op1_vt, op2_vt) {
|
||||
(ValueType::Invalid, _)
|
||||
| (_, ValueType::Invalid)
|
||||
@@ -184,7 +184,7 @@ impl<T: Clone + Debug + Hash + Eq + Copy> ConstraintSet<T> {
|
||||
}
|
||||
|
||||
(ValueType::Reference, _) => {
|
||||
self.bindings.insert(op2, ValueType::Scalar);
|
||||
self.bindings.insert(*op2, ValueType::Scalar);
|
||||
(ValueType::Reference, true)
|
||||
}
|
||||
|
||||
@@ -214,29 +214,37 @@ impl<T: Clone + Debug + Hash + Eq + Copy> ConstraintSet<T> {
|
||||
fn solve_assert(&mut self, constraint: &Constraint<T>) -> bool {
|
||||
// Will be of the form, Assertion(<inner>)
|
||||
// inner will be of the form Or(<c1>, <c2>)
|
||||
if let &Constraint::Assertion(box Constraint::Or(box ref c1, box ref c2)) = constraint {
|
||||
// c1, c2 will be of the form And(Eq(ci1), Eq(ci2))
|
||||
[c1, c2].iter().any(|&ci| {
|
||||
if let Constraint::And(
|
||||
box Constraint::Equality(op1, box Constraint::Value(vt1)),
|
||||
box Constraint::Equality(op2, box Constraint::Value(vt2)),
|
||||
) = *ci
|
||||
{
|
||||
if self.bvalue(op1) == vt1 {
|
||||
self.bindings.insert(op2, vt2);
|
||||
true
|
||||
} else if self.bvalue(op2) == vt2 {
|
||||
self.bindings.insert(op1, vt1);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
match constraint {
|
||||
&Constraint::Assertion(ref c) => match **c {
|
||||
Constraint::Or(ref c1, ref c2) => {
|
||||
// c1, c2 will be of the form And(Eq(ci1), Eq(ci2))
|
||||
[c1, c2].iter().any(|&ci| {
|
||||
match **ci {
|
||||
Constraint::And(ref bc1, ref bc2) => match (&**bc1, &**bc2) {
|
||||
(Constraint::Equality(op1, bvt1), Constraint::Equality(op2, bvt2)) => match (&**bvt1, &**bvt2) {
|
||||
(Constraint::Value(vt1), Constraint::Value(vt2)) => {
|
||||
if &self.bvalue(*op1) == vt1 {
|
||||
self.bindings.insert(*op2, *vt2);
|
||||
true
|
||||
} else if &self.bvalue(*op2) == vt2 {
|
||||
self.bindings.insert(*op1, *vt1);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
_ => false,
|
||||
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
false
|
||||
_ => false,
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,17 +256,17 @@ impl<T: Clone + Debug + Hash + Eq + Copy> ConstraintSet<T> {
|
||||
impl<T: Debug + Clone + Copy> Display for Constraint<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
let s = match *self {
|
||||
Constraint::Union(op1, op2) => format!("{:?} U {:?}", op1, op2),
|
||||
Constraint::Equality(op1, box ref op2) => format!("{:?} = {}", op1, op2),
|
||||
Constraint::Union(op1, ref op2) => format!("{:?} U {:?}", op1, op2),
|
||||
Constraint::Equality(op1, ref op2) => format!("{:?} = {}", op1, *op2),
|
||||
Constraint::AssertEquivalence(ref ops) => {
|
||||
ops.iter().fold("Assert ".to_owned(), |mut acc, s| {
|
||||
acc.push_str(&format!("{:?} = ", s));
|
||||
acc
|
||||
})
|
||||
}
|
||||
Constraint::Assertion(box ref op) => format!("Assert {}", op),
|
||||
Constraint::Or(box ref op1, box ref op2) => format!("{} \\/ {}", op1, op2),
|
||||
Constraint::And(box ref op1, box ref op2) => format!("{} /\\ {}", op1, op2),
|
||||
Constraint::Assertion(ref op) => format!("Assert {}", *op),
|
||||
Constraint::Or(ref op1, ref op2) => format!("{} \\/ {}", *op1, *op2),
|
||||
Constraint::And(ref op1, ref op2) => format!("{} /\\ {}", *op1, *op2),
|
||||
Constraint::Value(ref vt) => format!("{:?}", vt),
|
||||
};
|
||||
write!(f, "{}", s)
|
||||
|
||||
@@ -49,6 +49,21 @@ pub struct CombineChange {
|
||||
res: Either<(Option<CombinableOpInfo>, SSAValue), u64>,
|
||||
}
|
||||
|
||||
impl CombineChange {
|
||||
/// Gets the combine change SSA node.
|
||||
pub const fn node(&self) -> SSAValue {
|
||||
self.node
|
||||
}
|
||||
|
||||
/// Left: The node and one of its args were combined. The tuple contains: the
|
||||
/// structure of the combined node (if the node is a no-op then `None` is present)
|
||||
/// and the index of the non-const operand of the combined node.
|
||||
/// Right: The node and its args were combined into a constant value.
|
||||
pub const fn res(&self) -> &Either<(Option<CombinableOpInfo>, SSAValue), u64> {
|
||||
&self.res
|
||||
}
|
||||
}
|
||||
|
||||
impl Change for CombineChange {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
|
||||
@@ -40,7 +40,7 @@ impl<Ix: IndexLike> IxBitSet<Ix> {
|
||||
IxBitSet(BitSet::with_capacity(nbits), PhantomData)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<Ix> {
|
||||
pub fn iter(&self) -> Iter<'_, Ix> {
|
||||
Iter(self.0.iter(), PhantomData)
|
||||
}
|
||||
|
||||
|
||||
@@ -497,11 +497,12 @@ impl<'cd, A: AstContext> LoopRefiner<'cd, A> {
|
||||
|
||||
gen_rule! {rule_While, |self, body| {
|
||||
if let Seq(mut seq) = body {
|
||||
if let Some(&Cond(c, box Break, None)) = seq.first() {
|
||||
seq.remove(0);
|
||||
Ok(Loop(PreChecked(self.cctx.mk_not(c)), Box::new(mk_seq_vec(seq))))
|
||||
} else {
|
||||
Err(Seq(seq))
|
||||
match seq.first() {
|
||||
Some(&Cond(c, ref b, None)) if matches!(**b, Break) => {
|
||||
seq.remove(0);
|
||||
Ok(Loop(PreChecked(self.cctx.mk_not(c)), Box::new(mk_seq_vec(seq))))
|
||||
}
|
||||
_ => Err(Seq(seq)),
|
||||
}
|
||||
} else {
|
||||
Err(body)
|
||||
@@ -510,11 +511,12 @@ impl<'cd, A: AstContext> LoopRefiner<'cd, A> {
|
||||
|
||||
gen_rule! {rule_DoWhile, |self, body| {
|
||||
if let Seq(mut seq) = body {
|
||||
if let Some(&Cond(c, box Break, None)) = seq.last() {
|
||||
seq.pop();
|
||||
Ok(Loop(PostChecked(self.cctx.mk_not(c)), Box::new(mk_seq_vec(seq))))
|
||||
} else {
|
||||
Err(Seq(seq))
|
||||
match seq.last() {
|
||||
Some(&Cond(c, ref b, None)) if matches!(**b, Break) => {
|
||||
seq.pop();
|
||||
Ok(Loop(PostChecked(self.cctx.mk_not(c)), Box::new(mk_seq_vec(seq))))
|
||||
}
|
||||
_ => Err(Seq(seq)),
|
||||
}
|
||||
} else {
|
||||
Err(body)
|
||||
|
||||
@@ -789,7 +789,7 @@ pub struct CASTConverter<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CASTConverter<'a> {
|
||||
pub fn new(cfg: &CCFG) -> CASTConverter {
|
||||
pub fn new(cfg: &CCFG) -> CASTConverter<'_> {
|
||||
CASTConverter {
|
||||
ast: CAST::new(&cfg.fname),
|
||||
cfg: cfg,
|
||||
|
||||
@@ -45,7 +45,7 @@ pub trait RBind {
|
||||
fn is_unknown(&self) -> bool;
|
||||
|
||||
fn add_refs(&mut self, _: Vec<Self::SSARef>);
|
||||
fn refs(&self) -> ::std::slice::Iter<Self::SSARef>;
|
||||
fn refs(&self) -> ::std::slice::Iter<'_, Self::SSARef>;
|
||||
}
|
||||
|
||||
/// Trait that describes variable bindings for a function.
|
||||
@@ -59,8 +59,8 @@ pub trait RBindings {
|
||||
fn binding(&self, _: &Self::Idx) -> Option<&Self::BTy>;
|
||||
fn binding_mut(&mut self, _: &Self::Idx) -> Option<&mut Self::BTy>;
|
||||
|
||||
fn bindings(&self) -> RBinds<Self::BTy>;
|
||||
fn bindings_mut(&mut self) -> RBindsMut<Self::BTy>;
|
||||
fn bindings(&self) -> RBinds<'_, Self::BTy>;
|
||||
fn bindings_mut(&mut self) -> RBindsMut<'_, Self::BTy>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -125,13 +125,13 @@ impl<BTy: RBind> RBindings for RadecoBindings<BTy> {
|
||||
self.binds.get_mut(*idx)
|
||||
}
|
||||
|
||||
fn bindings(&self) -> RBinds<BTy> {
|
||||
fn bindings(&self) -> RBinds<'_, BTy> {
|
||||
RBinds {
|
||||
binds: self.binds.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bindings_mut(&mut self) -> RBindsMut<BTy> {
|
||||
fn bindings_mut(&mut self) -> RBindsMut<'_, BTy> {
|
||||
RBindsMut {
|
||||
binds: self.binds.iter_mut(),
|
||||
}
|
||||
@@ -150,6 +150,13 @@ pub struct Binding<T: fmt::Debug + Clone> {
|
||||
set: HashSet<VarSet>,
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug + Clone> Binding<T> {
|
||||
/// Gets the dynamic data type of the binding.
|
||||
pub fn dty(&self) -> VarDataType {
|
||||
self.dty
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + RBind> Iterator for RBindsMut<'a, T> {
|
||||
type Item = &'a mut T;
|
||||
fn next(&mut self) -> Option<&'a mut T> {
|
||||
@@ -345,7 +352,7 @@ impl<T: Clone + fmt::Debug> RBind for Binding<T> {
|
||||
self.ssa_refs.extend(refs);
|
||||
}
|
||||
|
||||
fn refs(&self) -> ::std::slice::Iter<T> {
|
||||
fn refs(&self) -> ::std::slice::Iter<'_, T> {
|
||||
self.ssa_refs.iter()
|
||||
}
|
||||
}
|
||||
@@ -535,7 +535,7 @@ pub trait RModule<'b> {
|
||||
fn function_by_ref_mut(&mut self, _: &Self::FnRef) -> Option<&mut Self::RFn>;
|
||||
|
||||
// Expose raw `Source`
|
||||
fn source(&'b mut self) -> &Option<&'b mut dyn Source>;
|
||||
fn source(&'b mut self) -> &'b Option<&'b mut dyn Source>;
|
||||
}
|
||||
|
||||
impl<'a, F: RFunction> RModule<'a> for RadecoModule<'a, F> {
|
||||
@@ -570,7 +570,7 @@ impl<'a, F: RFunction> RModule<'a> for RadecoModule<'a, F> {
|
||||
self.functions.get_mut(fref)
|
||||
}
|
||||
|
||||
fn source(&'a mut self) -> &Option<&'a mut dyn Source> {
|
||||
fn source(&'a mut self) -> &'a Option<&'a mut dyn Source> {
|
||||
&self.src
|
||||
}
|
||||
}
|
||||
@@ -588,7 +588,7 @@ impl<B: RBindings> RFunction for RadecoFunction<B> {
|
||||
self.bindings
|
||||
.bindings()
|
||||
.enumerate()
|
||||
.filter({ |x| x.1.is_argument() })
|
||||
.filter(|x| x.1.is_argument())
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -596,7 +596,7 @@ impl<B: RBindings> RFunction for RadecoFunction<B> {
|
||||
self.bindings
|
||||
.bindings()
|
||||
.enumerate()
|
||||
.filter({ |x| x.1.is_local() })
|
||||
.filter(|x| x.1.is_local())
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -604,7 +604,7 @@ impl<B: RBindings> RFunction for RadecoFunction<B> {
|
||||
self.bindings
|
||||
.bindings()
|
||||
.enumerate()
|
||||
.filter({ |x| x.1.is_return() })
|
||||
.filter(|x| x.1.is_return())
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ impl<B: RBindings> RFunction for RadecoFunction<B> {
|
||||
self.bindings
|
||||
.bindings()
|
||||
.enumerate()
|
||||
.filter({ |x| x.1.is_modified() })
|
||||
.filter(|x| x.1.is_modified())
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ pub fn init_call_ctx(rmod: &mut RadecoModule) {
|
||||
.callgraph
|
||||
.neighbors_directed(rfn.cgid(), Direction::Outgoing)
|
||||
.detach();
|
||||
for (csi, callee) in cgwalker.next(&rmod.callgraph) {
|
||||
while let Some((csi, callee)) = cgwalker.next(&rmod.callgraph) {
|
||||
let csite = rmod.callgraph[csi].csite;
|
||||
// Get args of callee
|
||||
let callee_off = rmod.callgraph[callee];
|
||||
|
||||
@@ -43,9 +43,9 @@ use petgraph::Direction;
|
||||
|
||||
use petgraph::graph::{Graph, NodeIndex};
|
||||
use petgraph::visit::EdgeRef;
|
||||
use r2api::api_trait::R2Api;
|
||||
use r2api::api_trait::R2PApi;
|
||||
use r2api::structs::{
|
||||
LCCInfo, LEntryInfo, LExportInfo, LOpInfo, LRelocInfo, LSectionInfo, LStringInfo, LSymbolInfo,
|
||||
LCCInfo, LEntry, LExportInfo, LOpInfo, LRelocInfo, LSectionInfo, LStringInfo, LSymbolInfo,
|
||||
LSymbolType, LVarInfo,
|
||||
};
|
||||
|
||||
@@ -176,16 +176,16 @@ pub trait CGInfo {
|
||||
impl CGInfo for CallGraph {
|
||||
// Return a list of callers to function at offset, along with their callsites
|
||||
fn callers<'a>(&'a self, idx: NodeIndex) -> Box<dyn Iterator<Item = (u64, NodeIndex)> + 'a> {
|
||||
box self
|
||||
Box::new(self
|
||||
.edges_directed(idx, Direction::Incoming)
|
||||
.map(|er| (er.weight().csite, er.target()))
|
||||
.map(|er| (er.weight().csite, er.target())))
|
||||
}
|
||||
|
||||
// Return (callsite, call target)
|
||||
fn callees<'a>(&'a self, idx: NodeIndex) -> Box<dyn Iterator<Item = (u64, NodeIndex)> + 'a> {
|
||||
box self
|
||||
Box::new(self
|
||||
.edges_directed(idx, Direction::Outgoing)
|
||||
.map(|er| (er.weight().csite, er.target()))
|
||||
.map(|er| (er.weight().csite, er.target())))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ pub struct RadecoModule {
|
||||
exports: Vec<LExportInfo>,
|
||||
relocs: Vec<LRelocInfo>,
|
||||
libs: Vec<String>,
|
||||
entrypoint: Vec<LEntryInfo>,
|
||||
entrypoint: Vec<LEntry>,
|
||||
// Information from early/low-level analysis
|
||||
/// Call graph for current module
|
||||
pub callgraph: CallGraph,
|
||||
@@ -404,6 +404,16 @@ pub struct RadecoFunction {
|
||||
pub kind: FunctionKind,
|
||||
}
|
||||
|
||||
impl RadecoFunction {
|
||||
// Gets whether the Radeco function is recursive.
|
||||
pub const fn is_recursive(&self) -> bool {
|
||||
match self.is_recursive {
|
||||
Some(true) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
/// Top-level loader used to initialize a `RadecoProject`
|
||||
pub struct ProjectLoader<'a> {
|
||||
@@ -478,7 +488,7 @@ impl<'a> ProjectLoader<'a> {
|
||||
let mut r2 = R2::new(Some(&self.path)).expect("Unable to open r2");
|
||||
let _ = r2.raw("e bin.minstr=1".to_string());
|
||||
//New r2 process is launched thus it needs to analyze
|
||||
r2.analyze_all();
|
||||
r2.analyze_all().expect("analysis error");
|
||||
let r2w = Rc::new(RefCell::new(r2));
|
||||
self.source = Some(Rc::new(r2w));
|
||||
};
|
||||
@@ -948,7 +958,7 @@ impl<'a> ModuleLoader<'a> {
|
||||
|
||||
if self.load_datarefs {
|
||||
for info in &aux_info {
|
||||
if let Some(mut rfn) = rmod.functions.get_mut(&info.offset.unwrap()) {
|
||||
if let Some(rfn) = rmod.functions.get_mut(&info.offset.unwrap()) {
|
||||
rfn.datarefs = info.datarefs.clone().unwrap_or_default();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
use r2api::api_trait::R2Api;
|
||||
use r2api::api_trait::R2PApi;
|
||||
use r2api::structs::{
|
||||
FunctionInfo, LCCInfo, LEntryInfo, LExportInfo, LFlagInfo, LFunctionInfo, LImportInfo, LOpInfo,
|
||||
FunctionInfo, LCCInfo, LEntry, LExportInfo, LFlagInfo, LFunctionInfo, LImportInfo, LOpInfo,
|
||||
LRegInfo, LRelocInfo, LSectionInfo, LStringInfo, LSymbolInfo, LVarInfo,
|
||||
};
|
||||
|
||||
@@ -60,7 +60,7 @@ pub trait Source {
|
||||
fn libraries(&self) -> Result<Vec<String>, SourceErr> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn entrypoint(&self) -> Result<Vec<LEntryInfo>, SourceErr> {
|
||||
fn entrypoint(&self) -> Result<Vec<LEntry>, SourceErr> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn disassemble_function(&self, _name: &str) -> Result<Vec<LOpInfo>, SourceErr> {
|
||||
@@ -140,7 +140,7 @@ pub trait Source {
|
||||
}
|
||||
}
|
||||
|
||||
// Cause R2Api requires borrowing mutably, while `Source` takes self which
|
||||
// Cause R2PApi requires borrowing mutably, while `Source` takes self which
|
||||
// is immutable.
|
||||
// The only problem with this is that r2pipe is not thread safe, therefore
|
||||
// using `r2` from multiple threads will cause results to be inconsistent.
|
||||
@@ -155,10 +155,10 @@ pub trait Source {
|
||||
// sense to have some sort of cached information so that concurrent reads can occur. This should
|
||||
// be invalidated whenever some information is exported back to radare or some analysis is run on
|
||||
// r2.
|
||||
pub type WrappedR2Api<R> = Rc<RefCell<R>>;
|
||||
pub type WrappedR2PApi<R> = Rc<RefCell<R>>;
|
||||
|
||||
// Implementation of `Source` trait for R2.
|
||||
impl<R: R2Api> Source for WrappedR2Api<R> {
|
||||
impl<R: R2PApi> Source for WrappedR2PApi<R> {
|
||||
fn functions(&self) -> Result<Vec<FunctionInfo>, SourceErr> {
|
||||
Ok(self.try_borrow_mut()?.fn_list()?)
|
||||
}
|
||||
@@ -205,8 +205,10 @@ impl<R: R2Api> Source for WrappedR2Api<R> {
|
||||
Ok(self.try_borrow_mut()?.libraries()?)
|
||||
}
|
||||
|
||||
fn entrypoint(&self) -> Result<Vec<LEntryInfo>, SourceErr> {
|
||||
Ok(self.try_borrow_mut()?.entrypoint()?)
|
||||
fn entrypoint(&self) -> Result<Vec<LEntry>, SourceErr> {
|
||||
self.try_borrow_mut()
|
||||
.map_err(SourceErr::from)
|
||||
.and_then(|mut s| s.entry().map_err(SourceErr::from))
|
||||
}
|
||||
|
||||
fn disassemble_n_bytes(&self, n: u64, at: u64) -> Result<Vec<LOpInfo>, SourceErr> {
|
||||
@@ -238,7 +240,9 @@ impl<R: R2Api> Source for WrappedR2Api<R> {
|
||||
}
|
||||
|
||||
fn raw(&self, cmd: String) -> Result<String, SourceErr> {
|
||||
Ok(self.try_borrow_mut()?.raw(cmd))
|
||||
self.try_borrow_mut()
|
||||
.map_err(SourceErr::from)
|
||||
.and_then(|mut s| s.raw(cmd).map_err(SourceErr::from))
|
||||
}
|
||||
|
||||
fn send(&self, s: String) -> Result<(), SourceErr> {
|
||||
@@ -355,7 +359,7 @@ impl Source for FileSource {
|
||||
Ok(serde_json::from_str(&self.read_file(suffix::LIBRARY)?)?)
|
||||
}
|
||||
|
||||
fn entrypoint(&self) -> Result<Vec<LEntryInfo>, SourceErr> {
|
||||
fn entrypoint(&self) -> Result<Vec<LEntry>, SourceErr> {
|
||||
Ok(serde_json::from_str(&self.read_file(suffix::ENTRY)?)?)
|
||||
}
|
||||
|
||||
@@ -398,8 +402,8 @@ impl Source for FileSource {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: R2Api> From<WrappedR2Api<R>> for FileSource {
|
||||
fn from(r2: WrappedR2Api<R>) -> FileSource {
|
||||
impl<R: R2PApi> From<WrappedR2PApi<R>> for FileSource {
|
||||
fn from(r2: WrappedR2PApi<R>) -> FileSource {
|
||||
let bin_info = r2.borrow_mut().bin_info().expect("Failed to load bin_info");
|
||||
let fname = bin_info.core.unwrap().file.unwrap();
|
||||
let fname = Path::new(&fname).file_stem().unwrap();
|
||||
@@ -531,7 +535,7 @@ impl<R: R2Api> From<WrappedR2Api<R>> for FileSource {
|
||||
{
|
||||
let entry = r2
|
||||
.borrow_mut()
|
||||
.entrypoint()
|
||||
.entry()
|
||||
.expect("Unable to load entry info from r2");
|
||||
let json_str = serde_json::to_string(&entry).expect("Failed to encode to json");
|
||||
fsource.write_file(suffix::ENTRY, &json_str);
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::process;
|
||||
|
||||
use serde_json;
|
||||
|
||||
use r2api::api_trait::R2Api;
|
||||
use r2api::api_trait::R2PApi;
|
||||
use r2api::structs::{FunctionInfo, LFlagInfo, LOpInfo, LRegInfo, LSectionInfo, LStringInfo};
|
||||
use r2pipe::r2::R2;
|
||||
|
||||
@@ -98,7 +98,7 @@ pub trait Source {
|
||||
// Implementation of `Source` trait for R2.
|
||||
impl Source for R2
|
||||
where
|
||||
R2: R2Api,
|
||||
R2: R2PApi,
|
||||
{
|
||||
fn functions(&mut self) -> Result<Vec<FunctionInfo>, &'static str> {
|
||||
match self.fn_list() {
|
||||
@@ -149,7 +149,8 @@ where
|
||||
}
|
||||
|
||||
fn send(&mut self, s: &str) {
|
||||
self.send(s);
|
||||
// FIXME: this function should bubble-up the error
|
||||
let _ = self.send(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
|
||||
#![doc(html_root_url = "https://radare.github.io/radeco-lib/")]
|
||||
#![doc(html_logo_url = "http://rada.re/r/img/r2logo3.png")]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(try_trait)]
|
||||
//#[cfg(test)] #[macro_use] extern crate quickcheck_macros;
|
||||
|
||||
extern crate petgraph;
|
||||
extern crate regex;
|
||||
|
||||
@@ -153,7 +153,7 @@ impl MOpcode {
|
||||
self.info().1
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> Cow<str> {
|
||||
pub fn to_string(&self) -> Cow<'_, str> {
|
||||
self.info().0
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ impl MOpcode {
|
||||
}
|
||||
}
|
||||
|
||||
fn info(&self) -> (Cow<str>, MArity) {
|
||||
fn info(&self) -> (Cow<'_, str>, MArity) {
|
||||
match *self {
|
||||
MOpcode::OpAdd => (Cow::from("OpAdd"), MArity::Binary),
|
||||
MOpcode::OpAnd => (Cow::from("OpAnd"), MArity::Binary),
|
||||
|
||||
@@ -52,14 +52,14 @@ impl<'a> LowerSsa<'a> {
|
||||
let entry_node = if let Some(en) = ssa.entry_node() {
|
||||
en
|
||||
} else {
|
||||
let entry_node = ssa.insert_block(ir::MAddress::new(0, 0))?;
|
||||
let entry_node = ssa.insert_block(ir::MAddress::new(0, 0)).ok_or(LoweringError::SsaError)?;
|
||||
ssa.set_entry_node(entry_node);
|
||||
entry_node
|
||||
};
|
||||
let exit_node = if let Some(en) = ssa.exit_node() {
|
||||
en
|
||||
} else {
|
||||
let exit_node = ssa.insert_dynamic()?;
|
||||
let exit_node = ssa.insert_dynamic().ok_or(LoweringError::SsaError)?;
|
||||
ssa.set_exit_node(exit_node);
|
||||
exit_node
|
||||
};
|
||||
@@ -103,8 +103,8 @@ impl<'a> LowerSsa<'a> {
|
||||
if !self.fw_ref_values.is_empty() {
|
||||
let undefined_values: Vec<_> = self.fw_ref_values.keys().collect();
|
||||
return Err(LoweringError::InvalidAst(format!(
|
||||
"values were used but not defined: {:?}",
|
||||
undefined_values
|
||||
"function {} values were used but not defined: {undefined_values:?}",
|
||||
sfn.name,
|
||||
)));
|
||||
}
|
||||
|
||||
@@ -115,10 +115,10 @@ impl<'a> LowerSsa<'a> {
|
||||
&mut self,
|
||||
sregstate: Vec<(sast::NewValue, sast::PhysReg)>,
|
||||
) -> Result<()> {
|
||||
let regstate = self.ssa.registers_in(self.entry_node)?;
|
||||
let regstate = self.ssa.registers_in(self.entry_node).ok_or(LoweringError::SsaError)?;
|
||||
for (sast::NewValue(vr, ty), sreg) in sregstate {
|
||||
let regid = self.index_of_reg(&sreg)?;
|
||||
let val = self.ssa.insert_comment(lower_valueinfo(ty), sreg.0)?;
|
||||
let val = self.ssa.insert_comment(lower_valueinfo(ty), sreg.0).ok_or(LoweringError::SsaError)?;
|
||||
self.ssa.op_use(regstate, regid.to_u8(), val);
|
||||
self.insert_new_value(vr, val)?;
|
||||
}
|
||||
@@ -129,7 +129,7 @@ impl<'a> LowerSsa<'a> {
|
||||
&mut self,
|
||||
sregstate: Vec<(sast::PhysReg, sast::Operand)>,
|
||||
) -> Result<()> {
|
||||
let regstate = self.ssa.registers_in(self.exit_node)?;
|
||||
let regstate = self.ssa.registers_in(self.exit_node).ok_or(LoweringError::SsaError)?;
|
||||
for (sreg, sop) in sregstate {
|
||||
let regid = self.index_of_reg(&sreg)?;
|
||||
let op = self.lower_operand(sop)?;
|
||||
@@ -180,7 +180,7 @@ impl<'a> LowerSsa<'a> {
|
||||
}
|
||||
|
||||
fn lower_exit_node(&mut self, sen: sast::ExitNode) -> Result<()> {
|
||||
let node_addr = self.ssa.starting_address(self.exit_node)?;
|
||||
let node_addr = self.ssa.starting_address(self.exit_node).ok_or(LoweringError::SsaError)?;
|
||||
for sop in sen.ops {
|
||||
let (res, opt_op_addr) = self.lower_operation(sop)?;
|
||||
let op_addr = opt_op_addr.unwrap_or(node_addr);
|
||||
@@ -197,7 +197,7 @@ impl<'a> LowerSsa<'a> {
|
||||
Ok(match sopn {
|
||||
sast::Operation::Phi(sast::NewValue(vr, ty), sops) => {
|
||||
let vi = lower_valueinfo(ty);
|
||||
let res = self.ssa.insert_phi(vi)?;
|
||||
let res = self.ssa.insert_phi(vi).ok_or(LoweringError::SsaError)?;
|
||||
// replacing forward refs with their values changes the order of
|
||||
// phi node operands, so we wait until forward refs have been
|
||||
// resolved before adding operands
|
||||
@@ -220,7 +220,7 @@ impl<'a> LowerSsa<'a> {
|
||||
}
|
||||
sast::Expr::Resize(rst, ws, sop0) => (lower_resize_op(rst, ws), vec![sop0]),
|
||||
};
|
||||
let res = self.ssa.insert_op(opcode, vi, None)?;
|
||||
let res = self.ssa.insert_op(opcode, vi, None).ok_or(LoweringError::SsaError)?;
|
||||
for (i, sop) in sops.into_iter().enumerate() {
|
||||
let op = self.lower_operand(sop)?;
|
||||
self.ssa.op_use(res, i as u8, op);
|
||||
@@ -230,7 +230,7 @@ impl<'a> LowerSsa<'a> {
|
||||
}
|
||||
|
||||
sast::Operation::Call(opt_addr, srets, tgt, sargs) => {
|
||||
let res = self.ssa.insert_op(IrOpcode::OpCall, scalar!(0), None)?;
|
||||
let res = self.ssa.insert_op(IrOpcode::OpCall, scalar!(0), None).ok_or(LoweringError::SsaError)?;
|
||||
let tgt_op = self.lower_operand(tgt)?;
|
||||
self.ssa.op_use(res, 0, tgt_op);
|
||||
for sarg in sargs {
|
||||
@@ -246,7 +246,8 @@ impl<'a> LowerSsa<'a> {
|
||||
}
|
||||
let val = self
|
||||
.ssa
|
||||
.insert_comment(lower_valueinfo(sret.value.1), comment)?;
|
||||
.insert_comment(lower_valueinfo(sret.value.1), comment)
|
||||
.ok_or(LoweringError::SsaError)?;
|
||||
self.ssa.op_use(val, regid.to_u8(), res);
|
||||
self.insert_new_value(sret.value.0, val)?;
|
||||
}
|
||||
@@ -257,23 +258,23 @@ impl<'a> LowerSsa<'a> {
|
||||
|
||||
fn lower_operand(&mut self, sop: sast::Operand) -> Result<SSAValue> {
|
||||
use std::collections::hash_map::Entry;
|
||||
Ok(match sop {
|
||||
match sop {
|
||||
sast::Operand::ValueRef(r) => {
|
||||
if let Some(x) = self.values.get(&r).cloned() {
|
||||
x
|
||||
Ok(x)
|
||||
} else {
|
||||
match self.fw_ref_values.entry(r) {
|
||||
Entry::Occupied(o) => *o.get(),
|
||||
Entry::Occupied(o) => Ok(*o.get()),
|
||||
Entry::Vacant(v) => {
|
||||
*v.insert(self.ssa.insert_undefined(ValueInfo::new_unresolved(
|
||||
self.ssa.insert_undefined(ValueInfo::new_unresolved(
|
||||
ir::WidthSpec::Unknown,
|
||||
))?)
|
||||
)).ok_or(LoweringError::SsaError).map(|b| *v.insert(b))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sast::Operand::Const(v) => self.ssa.insert_const(v, None)?,
|
||||
})
|
||||
sast::Operand::Const(v) => self.ssa.insert_const(v, None).ok_or(LoweringError::SsaError)
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_new_value(&mut self, vr: sast::ValueRef, val: SSAValue) -> Result<()> {
|
||||
@@ -300,10 +301,10 @@ impl<'a> LowerSsa<'a> {
|
||||
fn block_at(&mut self, at: ir::MAddress) -> Result<SSABlock> {
|
||||
use std::collections::hash_map::Entry;
|
||||
// can't use `or_insert_with` because `ssa.insert_block` may fail
|
||||
Ok(*match self.blocks.entry(at) {
|
||||
Entry::Occupied(o) => o.into_mut(),
|
||||
Entry::Vacant(v) => v.insert(self.ssa.insert_block(at)?),
|
||||
})
|
||||
match self.blocks.entry(at) {
|
||||
Entry::Occupied(o) => Ok(*o.into_mut()),
|
||||
Entry::Vacant(v) => self.ssa.insert_block(at).map(|b| *v.insert(b)).ok_or(LoweringError::SsaError),
|
||||
}
|
||||
}
|
||||
|
||||
fn index_of_reg(&self, sreg: &sast::PhysReg) -> Result<RegisterId> {
|
||||
@@ -361,14 +362,6 @@ fn lower_valueinfo(sty: sast::Type) -> ValueInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// [`SSAStorage`][SSAStorage] methods return `Option`,
|
||||
/// so we convert `None`s into [`SsaError`][LoweringError::SsaError]
|
||||
impl From<::std::option::NoneError> for LoweringError {
|
||||
fn from(_: ::std::option::NoneError) -> Self {
|
||||
LoweringError::SsaError
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for LoweringError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
|
||||
@@ -33,10 +33,10 @@ impl<V> RegisterMap<V> {
|
||||
pub fn remove(&mut self, key: RegisterId) -> Option<V> {
|
||||
self.map.remove(key.to_usize())
|
||||
}
|
||||
pub fn iter(&self) -> Iter<V> {
|
||||
pub fn iter(&self) -> Iter<'_, V> {
|
||||
self.into_iter()
|
||||
}
|
||||
pub fn iter_mut(&mut self) -> IterMut<V> {
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, V> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ where
|
||||
if comment.len() < reg_len {
|
||||
return false;
|
||||
}
|
||||
comment.split_off(reg_len);
|
||||
let _ = comment.split_off(reg_len);
|
||||
// Attition: Comment may be in format as: [email protected]
|
||||
|
||||
if comment == reg {
|
||||
|
||||
@@ -31,6 +31,7 @@ env_logger = { version = "0.7", optional = true }
|
||||
git = "https://github.com/radareorg/r2pipe.rs"
|
||||
|
||||
[dependencies.r2api]
|
||||
package = "r2papi"
|
||||
git = "https://github.com/radare/radare2-r2pipe-api"
|
||||
|
||||
[dependencies.radeco-lib]
|
||||
|
||||
+2
-2
@@ -167,12 +167,12 @@ pub fn load_proj_by_path(path: &str, max_it: u32) -> RadecoProject {
|
||||
}
|
||||
|
||||
pub fn load_proj_tcp(url: &str, max_it: u32) -> Result<RadecoProject, &'static str> {
|
||||
let r2p = R2Pipe::tcp(url)?;
|
||||
let r2p = R2Pipe::tcp(url).map_err(|_| "error creating project from TCP URL")?;
|
||||
Ok(load_project_by_r2pipe(r2p, max_it))
|
||||
}
|
||||
|
||||
pub fn load_proj_http(url: &str, max_it: u32) -> Result<RadecoProject, &'static str> {
|
||||
let r2p = R2Pipe::http(url)?;
|
||||
let r2p = R2Pipe::http(url);
|
||||
Ok(load_project_by_r2pipe(r2p, max_it))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ use syntect::parsing::SyntaxSet;
|
||||
use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};
|
||||
|
||||
lazy_static! {
|
||||
static ref SYNTAX_SET: SyntaxSet = { SyntaxSet::load_defaults_newlines() };
|
||||
static ref THEME_SET: ThemeSet = { ThemeSet::load_defaults() };
|
||||
static ref SYNTAX_SET: SyntaxSet = SyntaxSet::load_defaults_newlines();
|
||||
static ref THEME_SET: ThemeSet = ThemeSet::load_defaults();
|
||||
}
|
||||
|
||||
pub fn print_highlighted(code: &str) {
|
||||
@@ -14,6 +14,6 @@ pub fn print_highlighted(code: &str) {
|
||||
for line in LinesWithEndings::from(code) {
|
||||
let ranges: Vec<(Style, &str)> = h.highlight(line, &SYNTAX_SET);
|
||||
let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
|
||||
print!("{}", escaped);
|
||||
print!("{escaped}");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
#![feature(box_patterns)]
|
||||
#[cfg(feature = "trace_log")]
|
||||
extern crate env_logger;
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,6 @@ path = "runec/main.rs"
|
||||
|
||||
[dependencies]
|
||||
petgraph = "*"
|
||||
rustc-serialize = "*"
|
||||
clippy = {version = "*", optional = true}
|
||||
regex = "*"
|
||||
docopt = "*"
|
||||
@@ -37,4 +36,5 @@ path = "../esil-rs"
|
||||
git = "https://github.com/radareorg/r2pipe.rs"
|
||||
|
||||
[dependencies.r2api]
|
||||
package = "r2papi"
|
||||
git = "https://github.com/radare/radare2-r2pipe-api"
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
extern crate rustyline;
|
||||
use self::rustyline::error::ReadlineError;
|
||||
use self::rustyline::history::FileHistory;
|
||||
use self::rustyline::Editor;
|
||||
|
||||
use std::io::{self, Write};
|
||||
@@ -67,7 +68,7 @@ impl Console {
|
||||
pub fn read_command(&self) -> Vec<Command> {
|
||||
let mut repeat: u32 = 1;
|
||||
let mut cmd: Command;
|
||||
let mut r = Editor::<()>::new();
|
||||
let mut r = Editor::<(), FileHistory>::new().expect("unable to create rustyline Editor");
|
||||
|
||||
if let Err(_) = r.load_history("history.txt") {
|
||||
self.print_info("No history found.");
|
||||
@@ -79,7 +80,10 @@ impl Console {
|
||||
|
||||
match readline {
|
||||
Ok(buffer) => {
|
||||
r.add_history_entry(buffer.clone());
|
||||
if let Err(err) = r.add_history_entry(buffer.clone()) {
|
||||
println!("(!) Error adding history entry: {err}");
|
||||
continue;
|
||||
}
|
||||
cmd = From::from(buffer.to_owned());
|
||||
|
||||
if cmd.is_chainable() {
|
||||
|
||||
+5
-4
@@ -6,7 +6,6 @@
|
||||
extern crate rune;
|
||||
extern crate libsmt;
|
||||
extern crate docopt;
|
||||
extern crate rustc_serialize;
|
||||
extern crate r2pipe;
|
||||
extern crate r2api;
|
||||
|
||||
@@ -16,6 +15,8 @@ mod console;
|
||||
use std::process::exit;
|
||||
use docopt::Docopt;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use rune::utils::utils::{Key, ValType, SAssignment};
|
||||
use rune::utils::state::RInitialState;
|
||||
use rune::explorer::explorer::PathExplorer;
|
||||
@@ -27,7 +28,7 @@ use crate::interact::InteractiveExplorer;
|
||||
use crate::console::Console;
|
||||
|
||||
use r2pipe::r2::R2;
|
||||
use r2api::api_trait::R2Api;
|
||||
use r2api::api_trait::R2PApi;
|
||||
|
||||
static USAGE: &'static str = "
|
||||
runec. Interactive console for rune.
|
||||
@@ -41,7 +42,7 @@ Options:
|
||||
-p Load a previous configuration of state
|
||||
";
|
||||
|
||||
#[derive(Debug, Clone, RustcDecodable)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
struct Args {
|
||||
flag_help: bool,
|
||||
flag_project: bool,
|
||||
@@ -60,7 +61,7 @@ fn main() {
|
||||
}
|
||||
|
||||
let mut stream = R2::new(Some(args.get_str("<file>"))).expect("Unable to spawn r2");
|
||||
stream.init();
|
||||
stream.init().expect("Unable to initialize the stream");
|
||||
|
||||
let _lreginfo = stream.reg_info().expect("Unable to retrieve register info.");
|
||||
|
||||
|
||||
@@ -222,7 +222,6 @@ where Ctx: Context<IFn=qf_abv::QF_ABV_Fn>,
|
||||
Ok(token_opt_) => token_opt_,
|
||||
Err(_err) => {
|
||||
panic!("ERROR tokenizing!");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if let Some(ref token) = token_opt {
|
||||
@@ -235,7 +234,6 @@ where Ctx: Context<IFn=qf_abv::QF_ABV_Fn>,
|
||||
Ok(operands_opt) => operands_opt,
|
||||
Err(_err) => {
|
||||
panic!("Error fetching operands!");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@ extern crate petgraph;
|
||||
extern crate esil;
|
||||
extern crate r2pipe;
|
||||
extern crate r2api;
|
||||
extern crate rustc_serialize;
|
||||
extern crate regex;
|
||||
extern crate libsmt;
|
||||
#[macro_use] extern crate serde_derive;
|
||||
|
||||
@@ -8,12 +8,13 @@ use std::hash::Hash;
|
||||
use std::io::prelude::*;
|
||||
use std::fs::File;
|
||||
|
||||
use rustc_serialize::{Decodable};
|
||||
use rustc_serialize::json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use r2pipe::r2::R2;
|
||||
use r2api::structs::LOpInfo;
|
||||
use r2api::api_trait::R2Api;
|
||||
use r2api::api_trait::R2PApi;
|
||||
|
||||
pub trait Decodable: for<'a> Deserialize<'a> + Serialize {}
|
||||
|
||||
pub trait InstructionStream {
|
||||
type Output: Debug + Clone;
|
||||
@@ -33,7 +34,7 @@ impl InstructionStream for R2 {
|
||||
}
|
||||
|
||||
fn at(&mut self, addr: u64) -> Option<Self::Output> {
|
||||
let addr_ = format!("{}", addr);
|
||||
let addr_ = format!("{addr}");
|
||||
Some(self.insts(Some(1), Some(&addr_)).unwrap()[0].clone())
|
||||
}
|
||||
}
|
||||
@@ -42,10 +43,10 @@ impl InstructionStream for R2 {
|
||||
// This is useful for tests, debug and other smaller applications.
|
||||
// Maintains a HashMap from address to LOpInfo that it should provide
|
||||
// when asked for that address.
|
||||
#[derive(Clone, Debug, RustcDecodable, Default)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Default)]
|
||||
pub struct FileStream<I, Op>
|
||||
where I: Debug + Clone + Decodable + Hash + PartialEq + Eq,
|
||||
Op: Debug + Clone + Decodable
|
||||
where I: Debug + Clone + Hash + PartialEq + Eq,
|
||||
Op: Debug + Clone
|
||||
{
|
||||
insts: HashMap<I, Op>,
|
||||
}
|
||||
@@ -59,7 +60,7 @@ impl<I, Op> FileStream<I, Op>
|
||||
let mut f = File::open(fname).expect("Failed to open file");
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s).expect("Failed to read from file");
|
||||
self.insts = json::decode(&s).expect("Failed to decode json");
|
||||
self.insts = serde_json::from_str::<HashMap<I, Op>>(&s).expect("Failed to decode json");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use r2pipe::r2::R2;
|
||||
|
||||
use r2api::api_trait::R2Api;
|
||||
use r2api::api_trait::R2PApi;
|
||||
|
||||
use crate::context::rune_ctx::RuneContext;
|
||||
use crate::context::context::{ContextAPI};
|
||||
|
||||
Reference in new issue
Block a user