use crate::{
assumption::{KnownContradiction, Proposition, Truth, Violation},
types::TypeId,
value::{
bytes::{Bytes, BytesId},
function::FunctionId,
interner::{Interner, LiteralInterner},
literal::{Literal, LiteralId},
varnode::{Varnode, VarnodeId},
},
};
use jstd::registry::Registry;
use rustc_hash::FxHashMap as HashMap;
use std::collections::BTreeSet;
#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct ValueRegistry<'str> {
pub literals: LiteralInterner,
#[serde(default)]
pub bytes: Interner<BytesId, Bytes>,
#[serde(default)]
pub poisons: Interner<crate::value::PoisonId, crate::value::Poison>,
#[serde(default)]
pub(crate) bytes_display: HashMap<BytesId, crate::value::BytesDisplay>,
pub varnodes: Registry<VarnodeId, Varnode<'str>>,
#[serde(default)]
pub(crate) varnode_types: HashMap<VarnodeId, TypeId>,
pub(crate) truths: HashMap<Proposition, Truth>,
pub(crate) violations: Vec<Violation>,
#[serde(default, skip)]
pub(crate) known_contradictions: Vec<KnownContradiction>,
#[serde(default)]
pub(crate) synthetic_callees: HashMap<FunctionId, BTreeSet<u64>>,
}
impl<'str> ValueRegistry<'str> {
pub fn get_or_make_typed_literal(&self, value: u64, type_id: TypeId, size: usize) -> LiteralId {
self.literals
.get_or_make_typed_literal(value, type_id, size)
}
pub fn push_literal(&self, literal: Literal) -> LiteralId {
self.literals.push_literal(literal)
}
pub fn add_synthetic_callee(&mut self, caller: FunctionId, callee_addr: u64) -> bool {
self.synthetic_callees
.entry(caller)
.or_default()
.insert(callee_addr)
}
pub fn synthetic_callees_of(&self, caller: FunctionId) -> impl Iterator<Item = u64> + '_ {
self.synthetic_callees
.get(&caller)
.into_iter()
.flatten()
.copied()
}
pub fn push_varnode(&mut self, varnode: Varnode<'str>) -> VarnodeId {
self.varnodes.push(varnode)
}
pub fn push_poison(&self, type_id: TypeId) -> crate::value::PoisonId {
self.poisons.push(crate::value::Poison { type_id })
}
}