1+ use anyhow:: Context ;
12use clap:: { Parser , Subcommand } ;
23use hex:: decode;
34use jingle:: modeling:: { ModeledBlock , ModelingContext } ;
@@ -8,7 +9,7 @@ use jingle_sleigh::{Disassembly, Instruction, JingleSleighError, PcodeOperation,
89use serde:: { Deserialize , Serialize } ;
910use std:: path:: PathBuf ;
1011use z3:: ast:: Ast ;
11- use z3:: { Config , Context , Solver } ;
12+ use z3:: { Config , Context as Z3Context , Solver } ;
1213
1314#[ derive( Debug , PartialEq , Eq , Serialize , Deserialize ) ]
1415struct JingleConfig {
@@ -73,10 +74,10 @@ enum Commands {
7374 Architectures ,
7475}
7576
76- fn main ( ) {
77+ fn main ( ) -> anyhow :: Result < ( ) > {
7778 let params: JingleParams = JingleParams :: parse ( ) ;
7879 update_config ( & params) ;
79- let config: JingleConfig = confy:: load ( "jingle" , None ) . unwrap ( ) ;
80+ let config: JingleConfig = confy:: load ( "jingle" , None ) ? ;
8081 match params. command {
8182 Commands :: Disassemble {
8283 architecture,
@@ -90,15 +91,17 @@ fn main() {
9091 architecture,
9192 hex_bytes,
9293 } => model ( & config, architecture, hex_bytes) ,
93- Commands :: Architectures => list_architectures ( & config) ,
94+ Commands :: Architectures => Ok ( list_architectures ( & config) ) ,
9495 }
9596}
9697
9798fn update_config ( params : & JingleParams ) {
9899 let stored_config: JingleConfig = confy:: load ( "jingle" , None ) . unwrap ( ) ;
99- let new_config = JingleConfig :: from ( params) ;
100- if stored_config != new_config {
101- confy:: store ( "jingle" , None , new_config) . unwrap ( )
100+ if params. ghidra_path . is_some ( ) {
101+ let new_config = JingleConfig :: from ( params) ;
102+ if stored_config != new_config {
103+ confy:: store ( "jingle" , None , new_config) . unwrap ( )
104+ }
102105 }
103106}
104107
@@ -113,13 +116,20 @@ fn get_instructions(
113116 config : & JingleConfig ,
114117 architecture : String ,
115118 hex_bytes : String ,
116- ) -> ( LoadedSleighContext , Vec < Instruction > ) {
117- let sleigh_build = config. sleigh_builder ( ) . unwrap ( ) ;
118- let img = decode ( hex_bytes) . unwrap ( ) ;
119+ ) -> anyhow:: Result < ( LoadedSleighContext , Vec < Instruction > ) > {
120+ let sleigh_build = config. sleigh_builder ( ) . context ( format ! (
121+ "Unable to parse selected architecture. \n \
122+ This may indicate that your configured Ghidra path is incorrect: {}",
123+ config. ghidra_path. display( )
124+ ) ) ?;
125+ let img = decode ( hex_bytes) ?;
119126 let max_len = img. len ( ) ;
120127 let mut offset = 0 ;
121- let sleigh = sleigh_build. build ( & architecture) . unwrap ( ) ;
122- let sleigh = sleigh. initialize_with_image ( img) . unwrap ( ) ;
128+ let sleigh = sleigh_build
129+ . build ( & architecture)
130+ . context ( "Unable to build the selected architecture.\n \
131+ This is either a bug in sleigh or the .sinc file for your architecture is malformed.") ?;
132+ let sleigh = sleigh. initialize_with_image ( img) ?;
123133 let mut instrs = vec ! [ ] ;
124134 while offset < max_len {
125135 if let Some ( instruction) = sleigh. instruction_at ( offset as u64 ) {
@@ -130,29 +140,35 @@ fn get_instructions(
130140 break ;
131141 }
132142 }
133- ( sleigh, instrs)
143+ Ok ( ( sleigh, instrs) )
134144}
135145
136- fn disassemble ( config : & JingleConfig , architecture : String , hex_bytes : String ) {
137- for instr in get_instructions ( config, architecture, hex_bytes) . 1 {
146+ fn disassemble (
147+ config : & JingleConfig ,
148+ architecture : String ,
149+ hex_bytes : String ,
150+ ) -> anyhow:: Result < ( ) > {
151+ for instr in get_instructions ( config, architecture, hex_bytes) ?. 1 {
138152 println ! ( "{}" , instr. disassembly)
139153 }
154+ Ok ( ( ) )
140155}
141156
142- fn lift ( config : & JingleConfig , architecture : String , hex_bytes : String ) {
143- let ( sleigh, instrs) = get_instructions ( config, architecture, hex_bytes) ;
157+ fn lift ( config : & JingleConfig , architecture : String , hex_bytes : String ) -> anyhow :: Result < ( ) > {
158+ let ( sleigh, instrs) = get_instructions ( config, architecture, hex_bytes) ? ;
144159 for instr in instrs {
145160 for x in instr. ops {
146- let x_disp = x. display ( & sleigh) . unwrap ( ) ;
161+ let x_disp = x. display ( & sleigh) ? ;
147162 println ! ( "{}" , x_disp)
148163 }
149164 }
165+ Ok ( ( ) )
150166}
151167
152- fn model ( config : & JingleConfig , architecture : String , hex_bytes : String ) {
153- let z3 = Context :: new ( & Config :: new ( ) ) ;
168+ fn model ( config : & JingleConfig , architecture : String , hex_bytes : String ) -> anyhow :: Result < ( ) > {
169+ let z3 = Z3Context :: new ( & Config :: new ( ) ) ;
154170 let solver = Solver :: new ( & z3) ;
155- let ( sleigh, mut instrs) = get_instructions ( config, architecture, hex_bytes) ;
171+ let ( sleigh, mut instrs) = get_instructions ( config, architecture, hex_bytes) ? ;
156172 // todo: this is a disgusting hack to let us read a modeled block without requiring the user
157173 // to enter a block-terminating instruction. Everything with reading blocks needs to be reworked
158174 // at some point. For now, this lets me not break anything else relying on this behavior while
@@ -174,8 +190,10 @@ fn model(config: &JingleConfig, architecture: String, hex_bytes: String) {
174190 } ) ;
175191
176192 let jingle_ctx = JingleContext :: new ( & z3, & sleigh) ;
177- let block = ModeledBlock :: read ( & jingle_ctx, instrs. into_iter ( ) ) . unwrap ( ) ;
193+ let block = ModeledBlock :: read ( & jingle_ctx, instrs. into_iter ( ) ) ? ;
178194 let final_state = jingle_ctx. fresh_state ( ) ;
179- solver. assert ( & final_state. _eq ( block. get_final_state ( ) ) . unwrap ( ) . simplify ( ) ) ;
180- println ! ( "{}" , solver. to_smt2( ) )
195+ println ! ( "{}" , block. get_final_state( ) . fmt_smt_arrays( ) ) ;
196+ solver. assert ( & final_state. _eq ( block. get_final_state ( ) ) ?. simplify ( ) ) ;
197+ println ! ( "{}" , solver. to_smt2( ) ) ;
198+ Ok ( ( ) )
181199}
0 commit comments