Vector35 / Vector35/binaryninja-api
API surrounding LowLevelILLabel / Goto is confusing and contradictory (rust)
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 1.3k
- Forks
- 298
- Avg merge
- 5d 5h
- Merged PRs (30d)
- 19
Description
While trying to skip instructions in lifted low level IL, ran into some issue trying to get LLIL_GOTO to do the right thing. The typical usage is to create a label mark and then use goto, however this didn't seem to work at all in the function workflow.
Had a helpful tip from @bdash on slack that he was setting the operand field of the mark. When trying this, it seemed to work, however the rust sources define the mark:
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct LowLevelILLabel {
/// Used to update the label map if the label is associated with a location.
pub location: Option<Location>,
pub resolved: bool,
// TODO: This expr_ref is not actually a valid one sometimes...
// TODO: We should make these non public and only accessible if resolved is true.
pub expr_ref: LowLevelExpressionIndex,
// TODO: If this is 7 this label is not valid.
pub operand: usize,
}
which seems contradictory to how it was working, especially the operand field description.
While this works now in my plugin, it is creating a lot of warning messages:
[Default] LLIL goto target 90 (instruction 74 in 0x6ffffd5f76b4) does not have a marked label
[Default] LLIL goto target 130 (instruction 114 in 0x6ffffd5f76b4) does not have a marked label
[Default] LLIL goto target 34 (instruction 27 in 0x6ffffd5f7c2e) does not have a marked label
[Default] LLIL goto target 34 (instruction 27 in 0x6ffffd5f7c2e) does not have a marked label
[Default] LLIL goto target 84 (instruction 68 in 0x6ffffd5f7c2e) does not have a marked label
[Default] LLIL goto target 34 (instruction 27 in 0x6ffffd5f7c2e) does not have a marked label
[Default] LLIL goto target 84 (instruction 68 in 0x6ffffd5f7c2e) does not have a marked label
[Default] LLIL goto target 108 (instruction 101 in 0x6ffffd5f7c2e) does not have a marked label
Which seems to indicate that something is still not entirely right. My current hacky code which basically tries to skip an entire PUSH .... POP section by replacing the PUSH by a GOTO to right after the POP location:
let label = llil.label_for_address(after_pop_reg.address());
let expr = match label {
Some(mut lbl) => llil.goto(&mut lbl),
None => {
let Some(LowLevelInstructionIndex(tgt_idx)) =
llil.instruction_index_at::<Location>(after_pop_reg.address().into())
else {
return err_instr!(after_pop_reg, "unable to fetch LLInstructionIndex");
};
log::trace!("tgt_idx = {}", tgt_idx);
let mut lbl = LowLevelILLabel::new();
lbl.operand = tgt_idx;
llil.goto(&mut lbl)
}
};
unsafe {
llil.replace_expression(push_reg.expr_idx(), expr);
};
Some clarification on proper usage of the API would be welcome and/or some more examples in the repo to help people figure it out.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Rust definition of LowLevelILLabel and the LowLevelILLabel/Goto API usage shown in this issue, then inspect existing LLIL examples in the repository. Verify how location, resolved, expr_ref, and operand are intended to work in the function workflow. Done means the API behavior is documented consistently and includes a working example that avoids the reported warnings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- documentation, reverse-engineering
- Issue type
- Documentation
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100