Skip to content

Commit b2e4cc5

Browse files
committed
More rust cleanup
- Rename Label to LowLevelILLabel - Update the functions label map automatically This fixed a major api blunder where the label map is returned as a reference and originally resulted in UB prone lifetime semantics. It was temporarily "fixed" with explicit label updates in the architecture implementation code. But that was less than ideal and was easy to mess up. Now the label map will be updated automatically as the location of labels is now tracked.
1 parent fc17319 commit b2e4cc5

File tree

3 files changed

+57
-60
lines changed

3 files changed

+57
-60
lines changed

arch/msp430/src/lift.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::flag::{Flag, FlagWrite};
33
use crate::register::Register;
44
use crate::Msp430;
55

6-
use binaryninja::{architecture::FlagCondition, low_level_il::lifting::Label};
6+
use binaryninja::{architecture::FlagCondition, low_level_il::lifting::LowLevelILLabel};
77

88
use msp430_asm::emulate::Emulated;
99
use msp430_asm::instruction::Instruction;
@@ -142,12 +142,12 @@ macro_rules! conditional_jump {
142142

143143
let mut true_label = $il.label_for_address(true_addr).unwrap_or_else(|| {
144144
new_true = true;
145-
Label::new()
145+
LowLevelILLabel::new()
146146
});
147147

148148
let mut false_label = $il.label_for_address(false_addr).unwrap_or_else(|| {
149149
new_false = true;
150-
Label::new()
150+
LowLevelILLabel::new()
151151
});
152152

153153
$il.if_expr($cond, &mut true_label, &mut false_label)
@@ -156,14 +156,10 @@ macro_rules! conditional_jump {
156156
if new_true {
157157
$il.mark_label(&mut true_label);
158158
$il.jump($il.const_ptr(true_addr)).append();
159-
} else {
160-
$il.update_label_for_address(true_addr, true_label);
161159
}
162160

163161
if new_false {
164162
$il.mark_label(&mut false_label);
165-
} else {
166-
$il.update_label_for_address(false_addr, false_label);
167163
}
168164
};
169165
}
@@ -289,7 +285,6 @@ pub(crate) fn lift_instruction(
289285
match label {
290286
Some(mut label) => {
291287
il.goto(&mut label).append();
292-
il.update_label_for_address(fixed_addr, label);
293288
}
294289
None => {
295290
il.jump(il.const_ptr(fixed_addr)).append();
@@ -424,7 +419,6 @@ pub(crate) fn lift_instruction(
424419
let dest = if let Some(Operand::Immediate(dest)) = inst.destination() {
425420
if let Some(mut label) = il.label_for_address(*dest as u64) {
426421
il.goto(&mut label).append();
427-
il.update_label_for_address(*dest as u64, label);
428422
return;
429423
} else {
430424
il.const_ptr(*dest as u64)

arch/riscv/src/lib.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ use binaryninja::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE};
3939
use binaryninja::logger::Logger;
4040
use binaryninja::low_level_il::expression::{LowLevelILExpressionKind, ValueExpr};
4141
use binaryninja::low_level_il::instruction::LowLevelILInstructionKind;
42-
use binaryninja::low_level_il::lifting::{Label, LiftableLowLevelIL, LiftableLowLevelILWithSize};
42+
use binaryninja::low_level_il::lifting::{
43+
LiftableLowLevelIL, LiftableLowLevelILWithSize, LowLevelILLabel,
44+
};
4345
use binaryninja::low_level_il::{
4446
expression::ExpressionHandler, instruction::InstructionHandler, LowLevelILRegister,
4547
MutableLiftedILExpr, MutableLiftedILFunction, RegularLowLevelILFunction,
@@ -1220,11 +1222,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo
12201222
let target = addr.wrapping_add(j.imm() as i64 as u64);
12211223

12221224
match (j.rd().id(), il.label_for_address(target)) {
1223-
(0, Some(mut l)) => {
1224-
let jump_expr = il.goto(&mut l);
1225-
il.update_label_for_address(target, l);
1226-
jump_expr
1227-
}
1225+
(0, Some(mut l)) => il.goto(&mut l),
12281226
(0, None) => il.jump(il.const_ptr(target)),
12291227
(_, _) => il.call(il.const_ptr(target)),
12301228
}
@@ -1289,27 +1287,23 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo
12891287

12901288
let mut f = il.label_for_address(ft).unwrap_or_else(|| {
12911289
new_false = true;
1292-
Label::new()
1290+
LowLevelILLabel::new()
12931291
});
12941292

12951293
let mut t = il.label_for_address(tt).unwrap_or_else(|| {
12961294
new_true = true;
1297-
Label::new()
1295+
LowLevelILLabel::new()
12981296
});
12991297

13001298
il.if_expr(cond_expr, &mut t, &mut f).append();
13011299

13021300
if new_true {
13031301
il.mark_label(&mut t);
13041302
il.jump(il.const_ptr(tt)).append();
1305-
} else {
1306-
il.update_label_for_address(tt, t);
13071303
}
13081304

13091305
if new_false {
13101306
il.mark_label(&mut f);
1311-
} else {
1312-
il.update_label_for_address(ft, f);
13131307
}
13141308
}
13151309

@@ -1461,14 +1455,14 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo
14611455
il.set_reg(max_width, dest_reg, il.unimplemented()).append();
14621456

14631457
let mut new_false = false;
1464-
let mut t = Label::new();
1458+
let mut t = LowLevelILLabel::new();
14651459

14661460
let cond_expr = il.cmp_e(max_width, dest_reg, 0u64);
14671461

14681462
let ft = addr.wrapping_add(inst_len);
14691463
let mut f = il.label_for_address(ft).unwrap_or_else(|| {
14701464
new_false = true;
1471-
Label::new()
1465+
LowLevelILLabel::new()
14721466
});
14731467

14741468
il.if_expr(cond_expr, &mut t, &mut f).append();
@@ -1480,8 +1474,6 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo
14801474

14811475
if new_false {
14821476
il.mark_label(&mut f);
1483-
} else {
1484-
il.update_label_for_address(ft, f);
14851477
}
14861478
}
14871479
Op::AmoSwap(a)

rust/src/low_level_il/lifting.rs

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,8 +1097,8 @@ where
10971097
pub fn if_expr<'a: 'b, 'b, C>(
10981098
&'a self,
10991099
cond: C,
1100-
true_label: &'b mut Label,
1101-
false_label: &'b mut Label,
1100+
true_label: &'b mut LowLevelILLabel,
1101+
false_label: &'b mut LowLevelILLabel,
11021102
) -> LowLevelILExpression<'a, A, Mutable, NonSSA<LiftedNonSSA>, VoidExpr>
11031103
where
11041104
C: LiftableLowLevelIL<'b, A, Result = ValueExpr>,
@@ -1119,24 +1119,27 @@ where
11191119
};
11201120

11211121
// Update the labels after they have been resolved.
1122-
*true_label = Label::from(raw_true_label);
1123-
*false_label = Label::from(raw_false_label);
1122+
*true_label = LowLevelILLabel::from(raw_true_label);
1123+
*false_label = LowLevelILLabel::from(raw_false_label);
1124+
self.update_label_map_for_label(true_label);
1125+
self.update_label_map_for_label(false_label);
11241126

11251127
LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
11261128
}
11271129

11281130
// TODO: Wtf are these lifetimes??
11291131
pub fn goto<'a: 'b, 'b>(
11301132
&'a self,
1131-
label: &'b mut Label,
1133+
label: &'b mut LowLevelILLabel,
11321134
) -> LowLevelILExpression<'a, A, Mutable, NonSSA<LiftedNonSSA>, VoidExpr> {
11331135
use binaryninjacore_sys::BNLowLevelILGoto;
11341136

11351137
let mut raw_label = BNLowLevelILLabel::from(*label);
11361138
let expr_idx = unsafe { BNLowLevelILGoto(self.handle, &mut raw_label) };
11371139

11381140
// Update the labels after they have been resolved.
1139-
*label = Label::from(raw_label);
1141+
*label = LowLevelILLabel::from(raw_label);
1142+
self.update_label_map_for_label(label);
11401143

11411144
LowLevelILExpression::new(self, LowLevelExpressionIndex(expr_idx))
11421145
}
@@ -1549,51 +1552,58 @@ where
15491552
}
15501553
}
15511554

1552-
pub fn label_for_address<L: Into<Location>>(&self, loc: L) -> Option<Label> {
1555+
pub fn label_for_address<L: Into<Location>>(&self, loc: L) -> Option<LowLevelILLabel> {
15531556
use binaryninjacore_sys::BNGetLowLevelILLabelForAddress;
15541557

15551558
let loc: Location = loc.into();
15561559
let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
15571560
let raw_label =
15581561
unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
15591562
match raw_label.is_null() {
1560-
false => Some(unsafe { Label::from(*raw_label) }),
1563+
false => {
1564+
let mut label = unsafe { LowLevelILLabel::from(*raw_label) };
1565+
// Set the location so that calls to [Self::update_label_map_for_label] will update the label map.
1566+
label.location = Some(loc);
1567+
Some(label)
1568+
}
15611569
true => None,
15621570
}
15631571
}
15641572

1565-
// TODO: Make this private and then force the updates in the expressions.
15661573
/// Call this after updating the label through an il operation or via [`Self::mark_label`].
1567-
///
1568-
/// If you retrieved a label via [`Self::label_for_address`] than you very likely want to use this.
1569-
pub fn update_label_for_address<L: Into<Location>>(&self, loc: L, label: Label) {
1574+
fn update_label_map_for_label(&self, label: &LowLevelILLabel) {
15701575
use binaryninjacore_sys::BNGetLowLevelILLabelForAddress;
15711576

1572-
let loc: Location = loc.into();
1573-
let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1574-
// Add the label into the label map
1575-
unsafe { BNAddLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1576-
// Retrieve a pointer to the label in the map
1577-
let raw_label =
1578-
unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1579-
// We should always have a valid label here
1580-
assert!(!raw_label.is_null(), "Failed to add label for address!");
1581-
// Update the label in the map with `label`
1582-
unsafe { *raw_label = label.into() };
1577+
// Only need to update the label if there is an associated address.
1578+
if let Some(loc) = label.location {
1579+
let loc: Location = loc.into();
1580+
let arch = loc.arch.unwrap_or_else(|| *self.arch().as_ref());
1581+
// Add the label into the label map
1582+
unsafe { BNAddLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1583+
// Retrieve a pointer to the label in the map
1584+
let raw_label =
1585+
unsafe { BNGetLowLevelILLabelForAddress(self.handle, arch.handle, loc.addr) };
1586+
// We should always have a valid label here
1587+
assert!(!raw_label.is_null(), "Failed to add label for address!");
1588+
// Update the label in the map with `label`
1589+
unsafe { *raw_label = label.into() };
1590+
}
15831591
}
15841592

1585-
pub fn mark_label(&self, label: &mut Label) {
1593+
pub fn mark_label(&self, label: &mut LowLevelILLabel) {
15861594
use binaryninjacore_sys::BNLowLevelILMarkLabel;
15871595

15881596
let mut raw_label = BNLowLevelILLabel::from(*label);
15891597
unsafe { BNLowLevelILMarkLabel(self.handle, &mut raw_label) };
1590-
*label = Label::from(raw_label);
1598+
*label = LowLevelILLabel::from(raw_label);
1599+
self.update_label_map_for_label(label);
15911600
}
15921601
}
15931602

1594-
// TODO: Rename to LowLevelILLabel
1595-
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1596-
pub struct Label {
1603+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1604+
pub struct LowLevelILLabel {
1605+
/// Used to update the label map if the label is associated with a location.
1606+
pub location: Option<Location>,
15971607
pub resolved: bool,
15981608
// TODO: This expr_ref is not actually a valid one sometimes...
15991609
// TODO: We should make these non public and only accessible if resolved is true.
@@ -1602,7 +1612,7 @@ pub struct Label {
16021612
pub operand: usize,
16031613
}
16041614

1605-
impl Label {
1615+
impl LowLevelILLabel {
16061616
pub fn new() -> Self {
16071617
use binaryninjacore_sys::BNLowLevelILInitLabel;
16081618

@@ -1612,18 +1622,19 @@ impl Label {
16121622
}
16131623
}
16141624

1615-
impl From<BNLowLevelILLabel> for Label {
1625+
impl From<BNLowLevelILLabel> for LowLevelILLabel {
16161626
fn from(value: BNLowLevelILLabel) -> Self {
16171627
Self {
1628+
location: None,
16181629
resolved: value.resolved,
16191630
expr_ref: LowLevelExpressionIndex(value.ref_),
16201631
operand: value.operand,
16211632
}
16221633
}
16231634
}
16241635

1625-
impl From<Label> for BNLowLevelILLabel {
1626-
fn from(value: Label) -> Self {
1636+
impl From<LowLevelILLabel> for BNLowLevelILLabel {
1637+
fn from(value: LowLevelILLabel) -> Self {
16271638
Self {
16281639
resolved: value.resolved,
16291640
ref_: value.expr_ref.0,
@@ -1632,13 +1643,13 @@ impl From<Label> for BNLowLevelILLabel {
16321643
}
16331644
}
16341645

1635-
impl From<&Label> for BNLowLevelILLabel {
1636-
fn from(value: &Label) -> Self {
1646+
impl From<&LowLevelILLabel> for BNLowLevelILLabel {
1647+
fn from(value: &LowLevelILLabel) -> Self {
16371648
Self::from(*value)
16381649
}
16391650
}
16401651

1641-
impl Default for Label {
1652+
impl Default for LowLevelILLabel {
16421653
fn default() -> Self {
16431654
Self::new()
16441655
}

0 commit comments

Comments
 (0)