Skip to content

Commit 06c7a21

Browse files
toolCHAINZchf0xdzonerzydaniele.linguaglossa
authored
API Cleanup (#35)
* Target newer z3, fmt, clippy * Remove reference * Add catch for sleigh size mismatch * Fix condition * fmt * Initial context work * Add context; will slowly move stuff over to using this instead * Add derives * Pub z3 * cargo fmt * Ditch cargo lock * Update ci * Remove registers from context for now until link issues are fixed * Relax context requirement * Add state equality helper * Bump z3 * Store language id in sleigh context * Update image section debug * Oops * Actually run cargo check this time; comment out thing I didn't finish writing * Try section flags instead of segment flags * Add bb-read * Only load executable sections into ghidra for now * Only load executable sections into ghidra for now * Try bumping to ghidra 11.1 * Update how loading is done for ghidra 11.1 * Fix get_registers() * Update test * Add section parsing log * Fmt * Show range instead * Kludgy try_from impl, silencing warnings, fmt, clippy * Clone if there's only one * impl (Partial)Eq for Instruction * Derive ParitalEq/Eq so that I can derive Hash soundly * Readme tweak * Remove unnecessary compile API now that Ghidraships with precompiled sla. Also added a new bin target for jingle * Initial CLI * cargo fmt * Basic bin functionality * Add readme note and two missing operations * Simplify printed model * Sleigh parsing tweaks * Update logo * Gimli change * Block tweak * Add input enumeration * Add constraint * Explicitly add pointer dependencies to input call * Add arch and fmt * Initial context stuff * Fixed up C++ build side, now to fix FFI * Fix stuff and fmt. Builds, but need to make sure it actually works * Need to fix tests now * Some small tweaks * Gitignore, heap-allocate some stuff * Tweaks * Move back to storing all images directly in context * Add test * Bump ghidra to 11.2 * Fix jingle build * Fix jingle binary build * Fixes context variables * Re-add image * Add initialize call * Some bounds checking fixes * Move pcode/assembly emitters into their own files * Add test * Change get_reg impl for now * Add wrapper to ensure an image is loaded before parsing * Fmt * Clippy * More clippy * Fix jingle * fmt * Clippy * Fix binary * Don't consume varnode in `get_register_name` * Initial trait work * Tweaks * Some build fixes * More stuff * Maybe just need to add the impls now? * Build fixed * fmt * Clippy * Actually fix build * Fix crashes * Start on gimli * Impl gimli * actually actually fix build * Fmt and gimli tweak * Remove unused file * Remove more unused files * Fix build * clippy --fix * Clippy fixes * Changes to traits * fmt * Clippy * pub perms * More trait stuff * Convert LoadedSleighContext to struct * Trying more stuff * More trait gymnastics * Clippy * Remove unused generic bounds * Add owned file * Pub all of gimli * Reshuffle * Filter * Fix loading * Display register names * Change display impl * fmt * clippy * fmt * broken * Add new address type * More stuff * Name tweak * Changes * Add memory state relation * Clippy and fmt * Fix imports * More formatting * Some little pcode tweaks * Add in pcode operation cpu relations * Fix CLI build * Remove extra file * Simplify concretize * Add clone to context * Remove extra lifetime * ide warnings * Add methods to apply operations to state * Remove unsued method * Add read_bytes * Initial cache for building cfg * Add read_bytes * cherrypick get_bytes * Fix relative pcode branch destination * Add helper to summarize branches * Add helper to summarize branches * Add initial operation visitor * Very initial gross control flow recovery * Add merge of cache * Update logo * Update jingle.svg * Change branch flag * Remove duplicate def * Add call * Made ImageSectionIterator::new pub This would allow users to implement ImageProvider trait for their datatypes * Target master branch of z3.rs * Add rebasing API * Fix rebasing API * Context refactor * Fix formatting * fmt * Clippy * Tweaks * Make writing to a state consume the state * Slight reorganization * Use separate symbolic BVs to avoid unnecessary extract/concat operations Also fmt * Clippy --fix * Clear internal space * Stop carting around the sleigh context in the modeling context * Small tweaks * Only expose image bytes in the code space * Add doc comment * clippy * fmt * Blanket impl for ImageProvider * Fmt * Pub bmc * re-exports and fallthrough * Fix spaces * Bundle Zlib (#23) * Experiment with bundling zlib * Check if testing works in CI * Suppress warnings * Revert workflow change * Re-add all-features * Multiplatform CI (#24) * Enforce Fmt and Lint in CI * Build jingle_sleigh on linux, macos, and windows * Build jingle on linux * Fix ldefs (#26) * fix ldef * return error if there are not ldefs * fix clippy --------- Co-authored-by: daniele.linguaglossa <[email protected]> * Remove explicit dependence on p-code operation memory location from SMT encoding * fmt * pub ctx * Add fun * Add eq stufff * Add lazy helper * Simplify stuff for merge * fmt + clippy * Fix some awkward APIs * Bump version since I probably broke things * fmt * fmt * Clippy * Clippy * Re-add api I was using --------- Co-authored-by: chf0x <[email protected]> Co-authored-by: Daniele Linguaglossa <[email protected]> Co-authored-by: daniele.linguaglossa <[email protected]>
1 parent 0b94ed6 commit 06c7a21

File tree

29 files changed

+1552
-205
lines changed

29 files changed

+1552
-205
lines changed

jingle/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "jingle"
3-
version = "0.1.1"
3+
version = "0.2.1"
44
edition = "2021"
55
description = "SMT Modeling for Ghidra's PCODE"
66
homepage = "https://github.com/toolCHAINZ/jingle"
@@ -19,7 +19,7 @@ name = "jingle"
1919
required-features = ["bin_features"]
2020

2121
[dependencies]
22-
jingle_sleigh = { path = "../jingle_sleigh", version = "0.1.1" }
22+
jingle_sleigh = { path = "../jingle_sleigh", version = "0.2.0" }
2323
z3 = { git = "https://github.com/prove-rs/z3.rs.git", branch = "master" }
2424
thiserror = "1.0.58"
2525
serde = { version = "1.0.197", features = ["derive"] }

jingle/src/context.rs

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,54 @@
11
use crate::modeling::State;
2-
use jingle_sleigh::{RegisterManager, SpaceInfo, SpaceManager, VarNode};
2+
use jingle_sleigh::{ArchInfoProvider, SpaceInfo, VarNode};
33
use std::ops::Deref;
44
use std::rc::Rc;
55
use z3::Context;
66

7+
#[derive(Clone, Debug)]
8+
pub struct CachedArchInfo {
9+
registers: Vec<(VarNode, String)>,
10+
spaces: Vec<SpaceInfo>,
11+
default_code_space: usize,
12+
}
13+
14+
impl ArchInfoProvider for JingleContext<'_> {
15+
fn get_space_info(&self, idx: usize) -> Option<&SpaceInfo> {
16+
self.info.spaces.get(idx)
17+
}
18+
19+
fn get_all_space_info(&self) -> impl Iterator<Item = &SpaceInfo> {
20+
self.info.spaces.iter()
21+
}
22+
23+
fn get_code_space_idx(&self) -> usize {
24+
self.info.default_code_space
25+
}
26+
27+
fn get_register(&self, name: &str) -> Option<&VarNode> {
28+
self.info
29+
.registers
30+
.iter()
31+
.find(|(_, reg_name)| reg_name.as_str() == name)
32+
.map(|(vn, _)| vn)
33+
}
34+
35+
fn get_register_name(&self, location: &VarNode) -> Option<&str> {
36+
self.info
37+
.registers
38+
.iter()
39+
.find(|(vn, _)| vn == location)
40+
.map(|(_, name)| name.as_str())
41+
}
42+
43+
fn get_registers(&self) -> impl Iterator<Item = (&VarNode, &str)> {
44+
self.info.registers.iter().map(|(a, b)| (a, b.as_str()))
45+
}
46+
}
47+
748
#[derive(Clone, Debug)]
849
pub struct JingleContextInternal<'ctx> {
950
pub z3: &'ctx Context,
10-
spaces: Vec<SpaceInfo>,
11-
default_code_space_index: usize,
12-
registers: Vec<(VarNode, String)>,
51+
pub info: CachedArchInfo,
1352
}
1453

1554
#[derive(Clone, Debug)]
@@ -23,49 +62,27 @@ impl<'ctx> Deref for JingleContext<'ctx> {
2362
}
2463
}
2564
impl<'ctx> JingleContext<'ctx> {
26-
pub fn new<S: RegisterManager>(z3: &'ctx Context, r: &S) -> Self {
27-
let spaces = r.get_all_space_info().to_vec();
28-
let default_code_space_index = r.get_code_space_idx();
65+
pub fn new<S: ArchInfoProvider>(z3: &'ctx Context, r: &S) -> Self {
2966
Self(Rc::new(JingleContextInternal {
3067
z3,
31-
spaces,
32-
default_code_space_index,
33-
registers: r.get_registers(),
68+
info: CachedArchInfo {
69+
spaces: r.get_all_space_info().cloned().collect(),
70+
registers: r
71+
.get_registers()
72+
.map(|(a, b)| (a.clone(), b.to_string()))
73+
.collect(),
74+
default_code_space: r.get_code_space_idx(),
75+
},
3476
}))
3577
}
3678
pub fn fresh_state(&self) -> State<'ctx> {
3779
State::new(self)
3880
}
39-
}
40-
41-
impl SpaceManager for JingleContext<'_> {
42-
fn get_space_info(&self, idx: usize) -> Option<&SpaceInfo> {
43-
self.spaces.get(idx)
44-
}
45-
46-
fn get_all_space_info(&self) -> &[SpaceInfo] {
47-
self.spaces.as_slice()
48-
}
49-
50-
fn get_code_space_idx(&self) -> usize {
51-
self.default_code_space_index
52-
}
53-
}
54-
55-
impl RegisterManager for JingleContext<'_> {
56-
fn get_register(&self, name: &str) -> Option<VarNode> {
57-
self.registers
58-
.iter()
59-
.find_map(|i| i.1.eq(name).then_some(i.0.clone()))
60-
}
6181

62-
fn get_register_name(&self, location: &VarNode) -> Option<&str> {
63-
self.registers
64-
.iter()
65-
.find_map(|i| i.0.eq(location).then_some(i.1.as_str()))
66-
}
67-
68-
fn get_registers(&self) -> Vec<(VarNode, String)> {
69-
self.registers.clone()
82+
pub fn with_fresh_z3_context(&self, z3: &'ctx Context) -> Self {
83+
Self(Rc::new(JingleContextInternal {
84+
z3,
85+
info: self.info.clone(),
86+
}))
7087
}
7188
}

jingle/src/error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ pub enum JingleError {
77
Sleigh(#[from] JingleSleighError),
88
#[error("Given address disassembles cleanly but does not terminate within the given bound")]
99
DisassemblyLengthBound,
10-
#[error("This block exhibits unhandled intra-instruction control-flow")]
11-
IntraInstructionControlFlow,
10+
#[error("Attempted to construct an illegally-sized branch target")]
11+
InvalidBranchTargetSize,
1212
#[error("A z3 array selection operation returned something other than a bitvector")]
1313
UnexpectedArraySort,
1414
#[error("Something referenced a space that isn't declared")]

jingle/src/modeling/block.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use crate::modeling::{ModelingContext, TranslationContext};
66
use crate::varnode::ResolvedVarnode;
77
use crate::JingleContext;
88
use crate::JingleError::EmptyBlock;
9-
use jingle_sleigh::Instruction;
109
use jingle_sleigh::PcodeOperation;
11-
use jingle_sleigh::{SpaceInfo, SpaceManager};
10+
use jingle_sleigh::SpaceInfo;
11+
use jingle_sleigh::{ArchInfoProvider, Instruction, VarNode};
1212
use std::collections::HashSet;
1313
use std::fmt::{Display, Formatter};
1414

@@ -122,16 +122,29 @@ impl<'ctx> ModeledBlock<'ctx> {
122122
}
123123
}
124124

125-
impl SpaceManager for ModeledBlock<'_> {
125+
impl ArchInfoProvider for ModeledBlock<'_> {
126126
fn get_space_info(&self, idx: usize) -> Option<&SpaceInfo> {
127-
self.state.get_space_info(idx)
127+
self.jingle.get_space_info(idx)
128128
}
129129

130-
fn get_all_space_info(&self) -> &[SpaceInfo] {
131-
self.state.get_all_space_info()
130+
fn get_all_space_info(&self) -> impl Iterator<Item = &SpaceInfo> {
131+
self.jingle.get_all_space_info()
132132
}
133+
133134
fn get_code_space_idx(&self) -> usize {
134-
self.state.get_code_space_idx()
135+
self.jingle.get_code_space_idx()
136+
}
137+
138+
fn get_register(&self, name: &str) -> Option<&VarNode> {
139+
self.jingle.get_register(name)
140+
}
141+
142+
fn get_register_name(&self, location: &VarNode) -> Option<&str> {
143+
self.jingle.get_register_name(location)
144+
}
145+
146+
fn get_registers(&self) -> impl Iterator<Item = (&VarNode, &str)> {
147+
self.jingle.get_registers()
135148
}
136149
}
137150

jingle/src/modeling/instruction.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::modeling::{ModelingContext, TranslationContext};
2-
use jingle_sleigh::Instruction;
32
use jingle_sleigh::PcodeOperation;
3+
use jingle_sleigh::{Instruction, VarNode};
44

55
use std::collections::HashSet;
66

@@ -9,7 +9,7 @@ use crate::modeling::state::State;
99

1010
use crate::varnode::ResolvedVarnode;
1111
use crate::{JingleContext, JingleError};
12-
use jingle_sleigh::{SpaceInfo, SpaceManager};
12+
use jingle_sleigh::{ArchInfoProvider, SpaceInfo};
1313

1414
/// A `jingle` model of an individual SLEIGH instruction
1515
#[derive(Debug, Clone)]
@@ -51,17 +51,29 @@ impl<'ctx> ModeledInstruction<'ctx> {
5151
}
5252
}
5353

54-
impl SpaceManager for ModeledInstruction<'_> {
54+
impl ArchInfoProvider for ModeledInstruction<'_> {
5555
fn get_space_info(&self, idx: usize) -> Option<&SpaceInfo> {
56-
self.state.get_space_info(idx)
56+
self.jingle.get_space_info(idx)
5757
}
5858

59-
fn get_all_space_info(&self) -> &[SpaceInfo] {
60-
self.state.get_all_space_info()
59+
fn get_all_space_info(&self) -> impl Iterator<Item = &SpaceInfo> {
60+
self.jingle.get_all_space_info()
6161
}
6262

6363
fn get_code_space_idx(&self) -> usize {
64-
self.state.get_code_space_idx()
64+
self.jingle.get_code_space_idx()
65+
}
66+
67+
fn get_register(&self, name: &str) -> Option<&VarNode> {
68+
self.jingle.get_register(name)
69+
}
70+
71+
fn get_register_name(&self, location: &VarNode) -> Option<&str> {
72+
self.jingle.get_register_name(location)
73+
}
74+
75+
fn get_registers(&self) -> impl Iterator<Item = (&VarNode, &str)> {
76+
self.jingle.get_registers()
6577
}
6678
}
6779

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use crate::modeling::machine::cpu::symbolic::SymbolicPcodeAddress;
2+
use jingle_sleigh::VarNode;
3+
use std::fmt::{Display, Formatter, LowerHex};
4+
use z3::ast::BV;
5+
use z3::Context;
6+
7+
pub type PcodeMachineAddress = u64;
8+
pub type PcodeOffset = u8;
9+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
10+
pub struct ConcretePcodeAddress {
11+
pub(crate) machine: PcodeMachineAddress,
12+
pub(crate) pcode: PcodeOffset,
13+
}
14+
15+
impl Display for ConcretePcodeAddress {
16+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
17+
write!(f, "{}:{}", self.machine, self.pcode)
18+
}
19+
}
20+
21+
impl LowerHex for ConcretePcodeAddress {
22+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
23+
write!(f, "{:x}:{:x}", self.machine, self.pcode)
24+
}
25+
}
26+
27+
impl ConcretePcodeAddress {
28+
pub fn next_pcode(&self) -> Self {
29+
self.add_pcode_offset(1)
30+
}
31+
32+
pub fn machine(&self) -> PcodeMachineAddress {
33+
self.machine
34+
}
35+
36+
pub fn pcode(&self) -> PcodeOffset {
37+
self.pcode
38+
}
39+
40+
pub(crate) fn add_pcode_offset(&self, off: PcodeOffset) -> Self {
41+
Self {
42+
machine: self.machine,
43+
pcode: self.pcode.wrapping_add(off),
44+
}
45+
}
46+
pub fn symbolize<'ctx>(&self, z3: &'ctx Context) -> SymbolicPcodeAddress<'ctx> {
47+
SymbolicPcodeAddress {
48+
machine: BV::from_u64(
49+
z3,
50+
self.machine,
51+
size_of::<PcodeMachineAddress>() as u32 * 8,
52+
),
53+
pcode: BV::from_u64(z3, self.pcode as u64, size_of::<PcodeOffset>() as u32 * 8),
54+
}
55+
}
56+
57+
pub fn resolve_from_varnode(vn: &VarNode, loc: ConcretePcodeAddress) -> Self {
58+
if vn.is_const() {
59+
// relative jump
60+
loc.add_pcode_offset(vn.offset as u8)
61+
} else {
62+
// absolute jump
63+
ConcretePcodeAddress {
64+
machine: vn.offset,
65+
pcode: 0,
66+
}
67+
}
68+
}
69+
}
70+
71+
impl From<PcodeMachineAddress> for ConcretePcodeAddress {
72+
fn from(value: PcodeMachineAddress) -> Self {
73+
Self {
74+
machine: value,
75+
pcode: 0,
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)