1#![deny(missing_docs)]
2
3use crate::basic_block::BasicBlockId;
4use crate::function::{Function, FunctionError};
5use crate::instruction::Instruction;
6use crate::opcode::Opcode;
7use crate::operand::OperandError;
8use crate::utils::STRUCTURE_ANALYSIS_MAX_ITERATIONS;
9use serde::Serialize;
10use std::backtrace::Backtrace;
11use std::collections::HashMap;
12use thiserror::Error;
13
14use super::ast::array_kind::ArrayKind;
15use super::ast::expr::ExprKind;
16use super::ast::function::FunctionNode;
17use super::ast::visitors::emit_context::EmitContext;
18use super::ast::visitors::emitter::Gs2Emitter;
19use super::ast::{AstKind, AstVisitable, new_array};
20use super::execution_frame::ExecutionFrame;
21use super::function_decompiler_context::FunctionDecompilerContext;
22use super::structure_analysis::region::{RegionId, RegionType};
23use super::structure_analysis::{ControlFlowEdgeType, StructureAnalysis, StructureAnalysisError};
24
25#[derive(Debug, Error, Serialize)]
27pub enum FunctionDecompilerError {
28 #[error("Encountered FunctionError while decompiling: {source}")]
30 FunctionError {
31 source: FunctionError,
33 context: Box<FunctionDecompilerErrorContext>,
35 #[serde(skip)]
37 backtrace: Backtrace,
38 },
39
40 #[error("Register not found: {register_id}")]
42 RegisterNotFound {
43 register_id: usize,
45 context: Box<FunctionDecompilerErrorContext>,
47 #[serde(skip)]
49 backtrace: Backtrace,
50 },
51
52 #[error("Encountered an error while processing the operand: {source}")]
54 OperandError {
55 source: OperandError,
57 context: Box<FunctionDecompilerErrorContext>,
59 #[serde(skip)]
61 backtrace: Backtrace,
62 },
63
64 #[error("Encountered AstNodeError while decompiling: {source}")]
66 AstNodeError {
67 source: super::ast::AstNodeError,
69 context: Box<FunctionDecompilerErrorContext>,
71 #[serde(skip)]
73 backtrace: Backtrace,
74 },
75
76 #[error("The instruction associated with opcode {opcode} must have an operand.")]
78 InstructionMustHaveOperand {
79 opcode: Opcode,
81 context: Box<FunctionDecompilerErrorContext>,
83 #[serde(skip)]
85 backtrace: Backtrace,
86 },
87
88 #[error("Unexpected AstNode sub-type on stack. Expected {expected}.")]
90 UnexpectedNodeType {
91 expected: String,
93 context: Box<FunctionDecompilerErrorContext>,
95 #[serde(skip)]
97 backtrace: Backtrace,
98 },
99
100 #[error("Unimplemented Opcode: {opcode}")]
102 UnimplementedOpcode {
103 opcode: Opcode,
105 context: Box<FunctionDecompilerErrorContext>,
107 #[serde(skip)]
109 backtrace: Backtrace,
110 },
111
112 #[error("The AST Node stack is empty.")]
114 ExecutionStackEmpty {
115 context: Box<FunctionDecompilerErrorContext>,
117 #[serde(skip)]
119 backtrace: Backtrace,
120 },
121
122 #[error("Unexpected execution state.")]
124 UnexpectedExecutionState {
125 context: Box<FunctionDecompilerErrorContext>,
127 #[serde(skip)]
129 backtrace: Backtrace,
130 },
131
132 #[error("A structure analysis error occurred while decompiling the function: {source}")]
134 StructureAnalysisError {
135 source: Box<StructureAnalysisError>,
137 context: Box<FunctionDecompilerErrorContext>,
139 #[serde(skip)]
141 backtrace: Backtrace,
142 },
143
144 #[error("An error occurred while decompiling the function: {message}")]
146 Other {
147 message: String,
149 context: Box<FunctionDecompilerErrorContext>,
151 #[serde(skip)]
153 backtrace: Backtrace,
154 },
155}
156
157pub trait FunctionDecompilerErrorDetails {
159 fn context(&self) -> &FunctionDecompilerErrorContext;
161 fn backtrace(&self) -> &Backtrace;
163 fn error_type(&self) -> String;
165}
166
167#[derive(Debug, Serialize, Clone)]
169pub struct FunctionDecompilerErrorContext {
170 pub current_block_id: BasicBlockId,
172 pub current_instruction: Instruction,
174 pub current_ast_node_stack: Vec<ExecutionFrame>,
176}
177
178pub struct FunctionDecompilerBuilder<'a> {
180 function: &'a Function,
181 emit_context: EmitContext,
182 structure_debug_mode: bool,
183 structure_analysis_max_iterations: usize,
184}
185
186impl<'a> FunctionDecompilerBuilder<'a> {
187 pub fn new(function: &'a Function) -> Self {
189 FunctionDecompilerBuilder {
190 function,
191 emit_context: EmitContext::default(),
192 structure_debug_mode: false,
193 structure_analysis_max_iterations: STRUCTURE_ANALYSIS_MAX_ITERATIONS,
194 }
195 }
196
197 pub fn emit_context(mut self, emit_context: EmitContext) -> Self {
199 self.emit_context = emit_context;
200 self
201 }
202
203 pub fn structure_debug_mode(mut self, structure_debug_mode: bool) -> Self {
206 self.structure_debug_mode = structure_debug_mode;
207 self
208 }
209
210 pub fn structure_analysis_max_iterations(mut self, max_iterations: usize) -> Self {
212 self.structure_analysis_max_iterations = max_iterations;
213 self
214 }
215
216 pub fn build(self) -> FunctionDecompiler<'a> {
218 FunctionDecompiler::new(
219 self.function,
220 self.structure_debug_mode,
221 self.structure_analysis_max_iterations,
222 )
223 }
224}
225
226pub struct FunctionDecompiler<'a> {
228 function: &'a Function,
230 block_to_region: HashMap<BasicBlockId, RegionId>,
232 context: Option<FunctionDecompilerContext>,
234 function_parameters: Option<ArrayKind>,
236 struct_analysis: StructureAnalysis,
238 did_run_analysis: bool,
240}
241
242impl<'a> FunctionDecompiler<'a> {
243 fn new(
256 function: &'a Function,
257 structure_debug_mode: bool,
258 structure_max_iterations: usize,
259 ) -> Self {
260 FunctionDecompiler {
261 function,
262 block_to_region: HashMap::new(),
263 context: None,
264 function_parameters: None,
265 struct_analysis: StructureAnalysis::new(structure_debug_mode, structure_max_iterations),
266 did_run_analysis: false,
267 }
268 }
269}
270
271impl FunctionDecompiler<'_> {
273 pub fn decompile(
284 &mut self,
285 emit_context: EmitContext,
286 ) -> Result<String, FunctionDecompilerError> {
287 self.process_regions()?;
288
289 let entry_block_id = self.function.get_entry_basic_block().id;
290 let entry_region_id = self.block_to_region.get(&entry_block_id).unwrap();
291
292 self.did_run_analysis = true;
293 self.struct_analysis.execute().map_err(|e| {
294 FunctionDecompilerError::StructureAnalysisError {
295 source: Box::new(e),
296 context: self.context.as_ref().unwrap().get_error_context(),
297 backtrace: Backtrace::capture(),
298 }
299 })?;
300 let entry_region = {
301 let region = self
302 .struct_analysis
303 .get_region(*entry_region_id)
304 .expect("[Bug] The entry region should exist.");
305 region.clone()
306 };
307 let entry_region_nodes = entry_region.iter_nodes().cloned().collect::<Vec<_>>();
308
309 let func = AstKind::Function(
310 FunctionNode::new(
311 self.function.id.name.clone(),
312 self.function_parameters
313 .clone()
314 .unwrap_or_else(|| new_array::<ExprKind>(vec![]).into()),
315 entry_region_nodes,
316 )
317 .into(),
318 );
319
320 let mut emitter = Gs2Emitter::new(emit_context);
321 let output: String = func.accept(&mut emitter).node;
322
323 Ok(output)
324 }
325
326 pub fn get_structure_analysis_snapshots(&self) -> Result<Vec<String>, FunctionDecompilerError> {
328 self.struct_analysis
329 .get_snapshots()
330 .map_err(|e| FunctionDecompilerError::StructureAnalysisError {
331 source: Box::new(e),
332 context: self.context.as_ref().unwrap().get_error_context(),
333 backtrace: Backtrace::capture(),
334 })
335 .cloned()
336 }
337
338 fn generate_regions(&mut self) -> Result<(), FunctionDecompilerError> {
339 for block in self.function.iter() {
340 let successors = self.function.get_successors(block.id).map_err(|e| {
342 FunctionDecompilerError::FunctionError {
343 source: e,
344 backtrace: Backtrace::capture(),
345 context: self.context.as_ref().unwrap().get_error_context(),
346 }
347 })?;
348 let region_type = if successors.is_empty() {
349 RegionType::Tail
350 } else {
351 RegionType::Linear
352 };
353
354 let new_region_id = self.struct_analysis.add_region(region_type);
355 self.block_to_region.insert(block.id, new_region_id);
356 }
357 Ok(())
358 }
359
360 fn process_regions(&mut self) -> Result<(), FunctionDecompilerError> {
361 self.generate_regions()?;
363
364 let mut ctx = FunctionDecompilerContext::new(self.function.get_entry_basic_block_id());
365
366 let reverse_post_order = self
368 .function
369 .get_reverse_post_order(self.function.get_entry_basic_block().id)
370 .map_err(|e| FunctionDecompilerError::FunctionError {
371 source: e,
372 backtrace: Backtrace::capture(),
373 context: ctx.get_error_context(),
374 })?;
375
376 for block_id in &reverse_post_order {
377 let region_id = *self
379 .block_to_region
380 .get(block_id)
381 .expect("[Bug] We just made the regions, so not sure why it doesn't exist.");
382
383 ctx.start_block_processing(*block_id)?;
384
385 self.connect_predecessor_regions(*block_id, region_id)?;
387
388 let instructions: Vec<_> = {
390 let block = self
391 .function
392 .get_basic_block_by_id(*block_id)
393 .map_err(|e| FunctionDecompilerError::FunctionError {
394 source: e,
395 backtrace: Backtrace::capture(),
396 context: ctx.get_error_context(),
397 })?;
398 block.iter().cloned().collect()
399 };
400
401 for instr in instructions {
402 let processed = ctx.process_instruction(&instr)?;
403 if let Some(node) = processed.node_to_push {
404 let current_region_id = self
405 .block_to_region
406 .get(block_id)
407 .expect("[Bug] The region should exist.");
408 self.struct_analysis
409 .push_to_region(*current_region_id, node);
410 }
411
412 if let Some(params) = processed.function_parameters {
413 self.function_parameters = Some(params);
414 }
415
416 if let Some(jmp) = &processed.jump_condition {
417 let current_region_id = self
418 .block_to_region
419 .get(block_id)
420 .expect("[Bug] The region should exist.");
421 let region = self
422 .struct_analysis
423 .get_region_mut(*current_region_id)
424 .expect("[Bug] The region should exist.");
425
426 let successors = self.function.get_successors(*block_id).map_err(|e| {
429 FunctionDecompilerError::FunctionError {
430 source: e,
431 backtrace: Backtrace::capture(),
432 context: ctx.get_error_context(),
433 }
434 })?;
435 let mut unique_successors = successors.to_vec();
436 unique_successors.dedup();
437 if unique_successors.len() == 1 {
440 region.set_region_type(RegionType::Linear);
441 } else {
442 region.set_jump_expr(Some(jmp.clone()));
443 region.set_region_type(RegionType::ControlFlow);
444 region.set_branch_opcode(instr.opcode);
445 }
446 }
447 }
448 }
449
450 self.context = Some(ctx);
451
452 Ok(())
453 }
454
455 fn get_predecessors(
457 &self,
458 block_id: BasicBlockId,
459 ) -> Result<Vec<(BasicBlockId, RegionId, ControlFlowEdgeType)>, FunctionDecompilerError> {
460 let predecessors = self.function.get_predecessors(block_id).map_err(|e| {
462 FunctionDecompilerError::FunctionError {
463 source: e,
464 backtrace: Backtrace::capture(),
465 context: self.context.as_ref().unwrap().get_error_context(),
466 }
467 })?;
468
469 let predecessor_regions: Vec<(BasicBlockId, RegionId, ControlFlowEdgeType)> = predecessors
471 .iter()
472 .map(|pred_id| {
473 let pred_region_id = *self.block_to_region.get(pred_id).unwrap();
474
475 let pred_block = self
477 .function
478 .get_basic_block_by_id(*pred_id)
479 .expect("Predecessor block not found");
480
481 let pred_last_instruction = pred_block.last().expect("Empty block");
485
486 let target_block = self
488 .function
489 .get_basic_block_by_id(block_id)
490 .expect("Target block not found");
491 let target_address = target_block.id.address;
492
493 let edge_type = if pred_last_instruction.address + 1 != target_address {
495 ControlFlowEdgeType::Branch
497 } else {
498 ControlFlowEdgeType::Fallthrough
499 };
500
501 (*pred_id, pred_region_id, edge_type)
502 })
503 .collect();
504 Ok(predecessor_regions)
505 }
506
507 fn connect_predecessor_regions(
508 &mut self,
509 block_id: BasicBlockId,
510 region_id: RegionId,
511 ) -> Result<Vec<(BasicBlockId, RegionId, ControlFlowEdgeType)>, FunctionDecompilerError> {
512 let predecessor_regions = self.get_predecessors(block_id)?;
514
515 for (_, pred_region_id, edge_type) in &predecessor_regions {
517 self.struct_analysis
518 .connect_regions(*pred_region_id, region_id, *edge_type)
519 .map_err(|e| FunctionDecompilerError::StructureAnalysisError {
520 source: Box::new(e),
521 context: self.context.as_ref().unwrap().get_error_context(),
522 backtrace: Backtrace::capture(),
523 })?;
524 }
525
526 Ok(predecessor_regions)
528 }
529}
530
531impl FunctionDecompilerErrorDetails for FunctionDecompilerError {
534 fn context(&self) -> &FunctionDecompilerErrorContext {
535 match self {
536 FunctionDecompilerError::FunctionError { context, .. } => context,
537 FunctionDecompilerError::OperandError { context, .. } => context,
538 FunctionDecompilerError::AstNodeError { context, .. } => context,
539 FunctionDecompilerError::InstructionMustHaveOperand { context, .. } => context,
540 FunctionDecompilerError::UnexpectedNodeType { context, .. } => context,
541 FunctionDecompilerError::UnimplementedOpcode { context, .. } => context,
542 FunctionDecompilerError::ExecutionStackEmpty { context, .. } => context,
543 FunctionDecompilerError::UnexpectedExecutionState { context, .. } => context,
544 FunctionDecompilerError::Other { context, .. } => context,
545 FunctionDecompilerError::StructureAnalysisError { context, .. } => context,
546 FunctionDecompilerError::RegisterNotFound { context, .. } => context,
547 }
548 }
549
550 fn backtrace(&self) -> &Backtrace {
551 match self {
552 FunctionDecompilerError::FunctionError { backtrace, .. } => backtrace,
553 FunctionDecompilerError::OperandError { backtrace, .. } => backtrace,
554 FunctionDecompilerError::AstNodeError { backtrace, .. } => backtrace,
555 FunctionDecompilerError::InstructionMustHaveOperand { backtrace, .. } => backtrace,
556 FunctionDecompilerError::UnexpectedNodeType { backtrace, .. } => backtrace,
557 FunctionDecompilerError::UnimplementedOpcode { backtrace, .. } => backtrace,
558 FunctionDecompilerError::ExecutionStackEmpty { backtrace, .. } => backtrace,
559 FunctionDecompilerError::UnexpectedExecutionState { backtrace, .. } => backtrace,
560 FunctionDecompilerError::Other { backtrace, .. } => backtrace,
561 FunctionDecompilerError::StructureAnalysisError { source, .. } => source.backtrace(),
562 FunctionDecompilerError::RegisterNotFound { backtrace, .. } => backtrace,
563 }
564 }
565
566 fn error_type(&self) -> String {
567 match self {
568 FunctionDecompilerError::FunctionError { .. } => "FunctionError".to_string(),
569 FunctionDecompilerError::OperandError { .. } => "OperandError".to_string(),
570 FunctionDecompilerError::AstNodeError { .. } => "AstNodeError".to_string(),
571 FunctionDecompilerError::InstructionMustHaveOperand { .. } => {
572 "InstructionMustHaveOperand".to_string()
573 }
574 FunctionDecompilerError::UnexpectedNodeType { .. } => "UnexpectedNodeType".to_string(),
575 FunctionDecompilerError::UnimplementedOpcode { .. } => {
576 "UnimplementedOpcode".to_string()
577 }
578 FunctionDecompilerError::ExecutionStackEmpty { .. } => {
579 "ExecutionStackEmpty".to_string()
580 }
581 FunctionDecompilerError::UnexpectedExecutionState { .. } => {
582 "UnexpectedExecutionState".to_string()
583 }
584 FunctionDecompilerError::Other { .. } => "Other".to_string(),
585 FunctionDecompilerError::StructureAnalysisError { .. } => {
586 "StructureAnalysisError".to_string()
587 }
588 FunctionDecompilerError::RegisterNotFound { .. } => "RegisterNotFound".to_string(),
589 }
590 }
591}