Skip to content

Commit 08a312d

Browse files
committed
impl rust DisassemblyTextRenderer
1 parent 88a574f commit 08a312d

File tree

2 files changed

+309
-2
lines changed

2 files changed

+309
-2
lines changed

rust/src/disassembly.rs

+308-1
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,28 @@
1515

1616
use binaryninjacore_sys::*;
1717

18+
use crate::architecture::Architecture;
19+
use crate::architecture::CoreArchitecture;
20+
use crate::basic_block::BasicBlock;
21+
use crate::function::NativeBlock;
22+
use crate::high_level_il as hlil;
23+
use crate::low_level_il as llil;
24+
use crate::medium_level_il as mlil;
25+
use crate::string::BnStrCompatible;
1826
use crate::string::{raw_to_string, strings_to_string_list, BnString};
1927

2028
use crate::rc::*;
2129

2230
use crate::confidence::MAX_CONFIDENCE;
23-
use crate::function::HighlightColor;
31+
use crate::function::{Function, HighlightColor};
2432
use crate::tags::Tag;
2533
use crate::types::Type;
34+
use crate::variable::StackVariableReference;
35+
2636
use std::convert::From;
37+
use std::ffi;
2738
use std::fmt::{Display, Formatter};
39+
use std::ptr;
2840

2941
pub type DisassemblyOption = BNDisassemblyOption;
3042
pub type InstructionTextTokenType = BNInstructionTextTokenType;
@@ -1005,3 +1017,298 @@ unsafe impl RefCountable for DisassemblySettings {
10051017
BNFreeDisassemblySettings(handle.handle);
10061018
}
10071019
}
1020+
1021+
#[repr(transparent)]
1022+
pub struct DisassemblyTextRenderer {
1023+
handle: ptr::NonNull<BNDisassemblyTextRenderer>,
1024+
}
1025+
1026+
impl DisassemblyTextRenderer {
1027+
pub unsafe fn from_raw(handle: ptr::NonNull<BNDisassemblyTextRenderer>) -> Self {
1028+
Self { handle }
1029+
}
1030+
1031+
#[allow(clippy::mut_from_ref)]
1032+
pub unsafe fn as_raw(&self) -> &mut BNDisassemblyTextRenderer {
1033+
unsafe { &mut *self.handle.as_ptr() }
1034+
}
1035+
1036+
pub fn from_function(func: &Function, settings: Option<&DisassemblySettings>) -> Self {
1037+
let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1038+
let result = unsafe { BNCreateDisassemblyTextRenderer(func.handle, settings_ptr) };
1039+
unsafe { Self::from_raw(ptr::NonNull::new(result).unwrap()) }
1040+
}
1041+
1042+
pub fn from_llil_function<
1043+
A: Architecture,
1044+
M: llil::function::FunctionMutability,
1045+
F: llil::function::FunctionForm,
1046+
>(
1047+
func: &llil::function::LowLevelILFunction<A, M, F>,
1048+
settings: Option<&DisassemblySettings>,
1049+
) -> Self {
1050+
let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1051+
let result =
1052+
unsafe { BNCreateLowLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1053+
unsafe { Self::from_raw(ptr::NonNull::new(result).unwrap()) }
1054+
}
1055+
1056+
pub fn from_mlil_function(
1057+
func: &mlil::MediumLevelILFunction,
1058+
settings: Option<&DisassemblySettings>,
1059+
) -> Self {
1060+
let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1061+
let result =
1062+
unsafe { BNCreateMediumLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1063+
unsafe { Self::from_raw(ptr::NonNull::new(result).unwrap()) }
1064+
}
1065+
1066+
pub fn from_hlil_function(
1067+
func: &hlil::HighLevelILFunction,
1068+
settings: Option<&DisassemblySettings>,
1069+
) -> Self {
1070+
let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1071+
let result =
1072+
unsafe { BNCreateHighLevelILDisassemblyTextRenderer(func.handle, settings_ptr) };
1073+
unsafe { Self::from_raw(ptr::NonNull::new(result).unwrap()) }
1074+
}
1075+
1076+
pub fn function(&self) -> Ref<Function> {
1077+
let result = unsafe { BNGetDisassemblyTextRendererFunction(self.as_raw()) };
1078+
assert!(!result.is_null());
1079+
unsafe { Function::ref_from_raw(result) }
1080+
}
1081+
1082+
pub fn llil_function<M: llil::function::FunctionMutability, F: llil::function::FunctionForm>(
1083+
&self,
1084+
) -> Ref<llil::function::LowLevelILFunction<CoreArchitecture, M, F>> {
1085+
let arch = self.arch();
1086+
let result = unsafe { BNGetDisassemblyTextRendererLowLevelILFunction(self.as_raw()) };
1087+
assert!(!result.is_null());
1088+
unsafe { llil::function::LowLevelILFunction::ref_from_raw(arch.handle(), result) }
1089+
}
1090+
1091+
pub fn mlil_function(&self) -> Ref<mlil::MediumLevelILFunction> {
1092+
let result = unsafe { BNGetDisassemblyTextRendererMediumLevelILFunction(self.as_raw()) };
1093+
assert!(!result.is_null());
1094+
unsafe { mlil::MediumLevelILFunction::ref_from_raw(result) }
1095+
}
1096+
1097+
pub fn hlil_function(&self) -> Ref<hlil::HighLevelILFunction> {
1098+
let result = unsafe { BNGetDisassemblyTextRendererHighLevelILFunction(self.as_raw()) };
1099+
assert!(!result.is_null());
1100+
unsafe { hlil::HighLevelILFunction::ref_from_raw(result, true) }
1101+
}
1102+
1103+
pub fn basic_block(&self) -> Option<Ref<BasicBlock<NativeBlock>>> {
1104+
let result = unsafe { BNGetDisassemblyTextRendererBasicBlock(self.as_raw()) };
1105+
if result.is_null() {
1106+
return None;
1107+
}
1108+
Some(unsafe { Ref::new(BasicBlock::from_raw(result, NativeBlock::new())) })
1109+
}
1110+
1111+
pub fn set_basic_block(&self, value: Option<&BasicBlock<NativeBlock>>) {
1112+
let block_ptr = value.map(|b| b.handle).unwrap_or(ptr::null_mut());
1113+
unsafe { BNSetDisassemblyTextRendererBasicBlock(self.as_raw(), block_ptr) }
1114+
}
1115+
1116+
pub fn arch(&self) -> CoreArchitecture {
1117+
let result = unsafe { BNGetDisassemblyTextRendererArchitecture(self.as_raw()) };
1118+
assert!(!result.is_null());
1119+
unsafe { CoreArchitecture::from_raw(result) }
1120+
}
1121+
1122+
pub fn set_arch(&self, value: CoreArchitecture) {
1123+
unsafe { BNSetDisassemblyTextRendererArchitecture(self.as_raw(), value.handle) }
1124+
}
1125+
1126+
pub fn settings(&self) -> DisassemblySettings {
1127+
DisassemblySettings {
1128+
handle: unsafe { BNGetDisassemblyTextRendererSettings(self.as_raw()) },
1129+
}
1130+
}
1131+
1132+
pub fn set_settings(&self, settings: Option<&DisassemblySettings>) {
1133+
let settings_ptr = settings.map(|s| s.handle).unwrap_or(ptr::null_mut());
1134+
unsafe { BNSetDisassemblyTextRendererSettings(self.as_raw(), settings_ptr) }
1135+
}
1136+
1137+
pub fn is_il(&self) -> bool {
1138+
unsafe { BNIsILDisassemblyTextRenderer(self.as_raw()) }
1139+
}
1140+
1141+
pub fn has_data_flow(&self) -> bool {
1142+
unsafe { BNDisassemblyTextRendererHasDataFlow(self.as_raw()) }
1143+
}
1144+
1145+
pub fn instruction_annotations(&self, addr: u64) -> Array<InstructionTextToken> {
1146+
let mut count = 0;
1147+
let result = unsafe {
1148+
BNGetDisassemblyTextRendererInstructionAnnotations(self.as_raw(), addr, &mut count)
1149+
};
1150+
assert!(!result.is_null());
1151+
unsafe { Array::new(result, count, ()) }
1152+
}
1153+
1154+
pub fn instruction_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1155+
let mut count = 0;
1156+
let mut length = 0;
1157+
let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1158+
let result = unsafe {
1159+
BNGetDisassemblyTextRendererInstructionText(
1160+
self.as_raw(),
1161+
addr,
1162+
&mut length,
1163+
&mut lines,
1164+
&mut count,
1165+
)
1166+
};
1167+
result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1168+
}
1169+
1170+
pub fn disassembly_text(&self, addr: u64) -> Option<(Array<DisassemblyTextLine>, usize)> {
1171+
let mut count = 0;
1172+
let mut length = 0;
1173+
let mut lines: *mut BNDisassemblyTextLine = ptr::null_mut();
1174+
let result = unsafe {
1175+
BNGetDisassemblyTextRendererLines(
1176+
self.as_raw(),
1177+
addr,
1178+
&mut length,
1179+
&mut lines,
1180+
&mut count,
1181+
)
1182+
};
1183+
result.then(|| (unsafe { Array::new(lines, count, ()) }, length))
1184+
}
1185+
1186+
// TODO post_process_lines BNPostProcessDisassemblyTextRendererLines
1187+
1188+
pub fn is_integer_token(token_type: InstructionTextTokenType) -> bool {
1189+
unsafe { BNIsIntegerToken(token_type) }
1190+
}
1191+
1192+
pub fn reset_deduplicated_comments(&self) {
1193+
unsafe { BNResetDisassemblyTextRendererDeduplicatedComments(self.as_raw()) }
1194+
}
1195+
1196+
pub fn symbol_tokens(
1197+
&self,
1198+
addr: u64,
1199+
size: usize,
1200+
operand: Option<usize>,
1201+
) -> Option<Array<InstructionTextToken>> {
1202+
let operand = operand.unwrap_or(0xffffffff);
1203+
let mut count = 0;
1204+
let mut tokens: *mut BNInstructionTextToken = ptr::null_mut();
1205+
let result = unsafe {
1206+
BNGetDisassemblyTextRendererSymbolTokens(
1207+
self.as_raw(),
1208+
addr,
1209+
size,
1210+
operand,
1211+
&mut tokens,
1212+
&mut count,
1213+
)
1214+
};
1215+
result.then(|| unsafe { Array::new(tokens, count, ()) })
1216+
}
1217+
1218+
pub fn stack_var_reference_tokens(
1219+
&self,
1220+
ref_: &StackVariableReference,
1221+
) -> Array<InstructionTextToken> {
1222+
let name = ref_.name.clone().into_bytes_with_nul();
1223+
let mut stack_ref = StackVariableReference::into_raw(ref_.clone());
1224+
let mut count = 0;
1225+
let tokens = unsafe {
1226+
BNGetDisassemblyTextRendererStackVariableReferenceTokens(
1227+
self.as_raw(),
1228+
&mut stack_ref,
1229+
&mut count,
1230+
)
1231+
};
1232+
assert!(!tokens.is_null());
1233+
unsafe { Array::new(tokens, count, ()) }
1234+
}
1235+
1236+
pub fn integer_token(
1237+
&self,
1238+
int_token: &InstructionTextToken,
1239+
addr: u64,
1240+
arch: Option<CoreArchitecture>,
1241+
) -> Array<InstructionTextToken> {
1242+
let arch = arch.map(|a| a.handle).unwrap_or(ptr::null_mut());
1243+
let mut count = 0;
1244+
let int_token_raw = InstructionTextToken::into_raw(int_token.clone());
1245+
let tokens = unsafe {
1246+
BNGetDisassemblyTextRendererIntegerTokens(
1247+
self.as_raw(),
1248+
&int_token_raw as *const BNInstructionTextToken as *mut _,
1249+
arch,
1250+
addr,
1251+
&mut count,
1252+
)
1253+
};
1254+
assert!(!tokens.is_null());
1255+
unsafe { Array::new(tokens, count, ()) }
1256+
}
1257+
1258+
pub fn wrap_comment<S1: BnStrCompatible, S2: BnStrCompatible, S3: BnStrCompatible>(
1259+
&self,
1260+
cur_line: &DisassemblyTextLine,
1261+
comment: S1,
1262+
has_auto_annotations: bool,
1263+
leading_spaces: S2,
1264+
indent_spaces: S3,
1265+
) -> Array<DisassemblyTextLine> {
1266+
//// //leading_spaces: str = " ", indent_spaces: str = ""
1267+
let mut tokens_raw: Vec<_> = cur_line
1268+
.tokens
1269+
.iter()
1270+
.map(|x| InstructionTextToken::into_raw(x.clone()))
1271+
.collect();
1272+
let mut cur_line_obj = BNDisassemblyTextLine {
1273+
addr: cur_line.address,
1274+
instrIndex: cur_line.instruction_index,
1275+
tokens: tokens_raw.as_mut_ptr(),
1276+
count: cur_line.tokens.len(),
1277+
highlight: cur_line.highlight.into(),
1278+
..Default::default()
1279+
};
1280+
let mut count = 0;
1281+
let comment_raw = comment.into_bytes_with_nul();
1282+
let leading_spaces_raw = leading_spaces.into_bytes_with_nul();
1283+
let indent_spaces_raw = indent_spaces.into_bytes_with_nul();
1284+
let lines = unsafe {
1285+
BNDisassemblyTextRendererWrapComment(
1286+
self.as_raw(),
1287+
&mut cur_line_obj,
1288+
&mut count,
1289+
comment_raw.as_ref().as_ptr() as *const ffi::c_char,
1290+
has_auto_annotations,
1291+
leading_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1292+
indent_spaces_raw.as_ref().as_ptr() as *const ffi::c_char,
1293+
)
1294+
};
1295+
assert!(!lines.is_null());
1296+
unsafe { Array::new(lines, count, ()) }
1297+
}
1298+
}
1299+
1300+
impl Clone for DisassemblyTextRenderer {
1301+
fn clone(&self) -> Self {
1302+
unsafe {
1303+
Self::from_raw(
1304+
ptr::NonNull::new(BNNewDisassemblyTextRendererReference(self.as_raw())).unwrap(),
1305+
)
1306+
}
1307+
}
1308+
}
1309+
1310+
impl Drop for DisassemblyTextRenderer {
1311+
fn drop(&mut self) {
1312+
unsafe { BNFreeDisassemblyTextRenderer(self.as_raw()) }
1313+
}
1314+
}

rust/src/variable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ unsafe impl CoreArrayProviderInner for UserVariableValue {
268268

269269
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
270270
pub struct StackVariableReference {
271-
source_operand: u32,
271+
pub(crate) source_operand: u32,
272272
pub variable_type: Conf<Ref<Type>>,
273273
pub name: String,
274274
pub variable: Variable,

0 commit comments

Comments
 (0)