-
Notifications
You must be signed in to change notification settings - Fork 281
Expand file tree
/
Copy pathalloc_init.rs
More file actions
73 lines (61 loc) · 2.13 KB
/
alloc_init.rs
File metadata and controls
73 lines (61 loc) · 2.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use binaryninja::{
binary_view::{BinaryView, BinaryViewExt as _},
medium_level_il::MediumLevelILLiftedInstruction,
rc::Ref,
types::Type,
workflow::AnalysisContext,
};
use bstr::ByteSlice;
use super::util;
use crate::{error::ILLevel, metadata::GlobalState, workflow::Confidence, Error};
// j_ prefixes are for stub functions in the dyld shared cache.
// The prefix is added by Binary Ninja's shared cache workflow.
const ALLOC_INIT_FUNCTIONS: &[&[u8]] = &[
b"_objc_alloc_init",
b"_objc_alloc_initWithZone",
b"_objc_alloc",
b"_objc_allocWithZone",
b"_objc_opt_new",
b"j__objc_alloc_init",
b"j__objc_alloc_initWithZone",
b"j__objc_alloc",
b"j__objc_allocWithZone",
b"j__objc_opt_new",
];
fn return_type_for_alloc_call(call: &util::Call<'_>, view: &BinaryView) -> Option<Ref<Type>> {
if call.call.params.is_empty() {
return None;
}
let class_addr =
util::match_constant_pointer_or_load_of_constant_pointer(&call.call.params[0])?;
let class_symbol_name = view.symbol_by_address(class_addr)?.full_name();
let class_name = util::class_name_from_symbol_name(class_symbol_name.to_bytes().as_bstr())?;
let class_type = view.type_by_name(class_name.to_str_lossy())?;
Some(Type::pointer(&call.target.arch(), &class_type))
}
fn process_instruction(instr: &MediumLevelILLiftedInstruction, view: &BinaryView) -> Option<()> {
let call = util::match_call_to_function_named(instr, view, ALLOC_INIT_FUNCTIONS)?;
util::adjust_return_type_of_call(
&call,
return_type_for_alloc_call(&call, view)?.as_ref(),
Confidence::AllocInit as u8,
);
Some(())
}
pub fn process(ac: &AnalysisContext) -> Result<(), Error> {
let bv = ac.view();
if GlobalState::should_ignore_view(&bv) {
return Ok(());
}
let mlil = ac.mlil_function().ok_or(Error::MissingIL {
level: ILLevel::Medium,
func_start: ac.function().start(),
})?;
let mlil_ssa = mlil.ssa_form();
for block in &mlil_ssa.basic_blocks() {
for instr in block.iter() {
process_instruction(&instr.lift(), &bv);
}
}
Ok(())
}