Skip to content

Commit 6cfa5e0

Browse files
committed
Merge remote-tracking branch 'origin/dev' into powerpc_vle_merging
2 parents 6322c1c + 3a1a81c commit 6cfa5e0

File tree

10 files changed

+81
-16
lines changed

10 files changed

+81
-16
lines changed

binaryninjaapi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11436,6 +11436,9 @@ namespace BinaryNinja {
1143611436
BNEarlyReturn GetEarlyReturn(uint64_t addr);
1143711437
void SetEarlyReturn(uint64_t addr, BNEarlyReturn mode);
1143811438

11439+
BNSwitchRecovery GetSwitchRecovery(uint64_t addr);
11440+
void SetSwitchRecovery(uint64_t addr, BNSwitchRecovery mode);
11441+
1143911442
std::map<Variable, std::set<Variable>> GetMergedVariables();
1144011443
void MergeVariables(const Variable& target, const std::set<Variable>& sources);
1144111444
void UnmergeVariables(const Variable& target, const std::set<Variable>& sources);

binaryninjacore.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 110
40+
#define BN_CURRENT_CORE_ABI_VERSION 111
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
@@ -1030,6 +1030,9 @@ extern "C"
10301030

10311031
// HLIL condition can be rewritten as an early return
10321032
HLILEarlyReturnPossible = 0x400,
1033+
1034+
// HLIL condition chain can be rewritten as a switch statement
1035+
HLILSwitchRecoveryPossible = 0x800,
10331036
} BNILInstructionAttribute;
10341037

10351038
typedef enum BNIntrinsicClass
@@ -3254,6 +3257,13 @@ extern "C"
32543257
FalseSideEarlyReturn
32553258
} BNEarlyReturn;
32563259

3260+
typedef enum BNSwitchRecovery
3261+
{
3262+
DefaultSwitchRecovery,
3263+
PreventSwitchRecovery,
3264+
AllowSwitchRecovery
3265+
} BNSwitchRecovery;
3266+
32573267
typedef struct BNDebugFunctionInfo
32583268
{
32593269
char* shortName;
@@ -5013,6 +5023,8 @@ extern "C"
50135023
BINARYNINJACOREAPI void BNSetConditionInverted(BNFunction* func, uint64_t addr, bool invert);
50145024
BINARYNINJACOREAPI BNEarlyReturn BNGetEarlyReturn(BNFunction* func, uint64_t addr);
50155025
BINARYNINJACOREAPI void BNSetEarlyReturn(BNFunction* func, uint64_t addr, BNEarlyReturn mode);
5026+
BINARYNINJACOREAPI BNSwitchRecovery BNGetSwitchRecovery(BNFunction* func, uint64_t addr);
5027+
BINARYNINJACOREAPI void BNSetSwitchRecovery(BNFunction* func, uint64_t addr, BNSwitchRecovery mode);
50165028
BINARYNINJACOREAPI BNMergedVariable* BNGetMergedVariables(BNFunction* func, size_t* count);
50175029
BINARYNINJACOREAPI void BNFreeMergedVariableList(BNMergedVariable* vars, size_t count);
50185030
BINARYNINJACOREAPI void BNMergeVariables(BNFunction* func, const BNVariable* target, const BNVariable* sources,

docs/guide/index.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -807,28 +807,41 @@ Performing this action on both variables in the example results in the following
807807

808808
![Dead Store Elimination Results](../img/dead-store-after.png "Dead Store Elimination Results"){ width="500" }
809809

810-
## Expression Folding
810+
## High Level Optimization Overrides
811811

812812
Binary Ninja automatically performs optimization passes on high level code. One of these optimizations is to fold
813813
assignments with a single use into the statement that uses it. An example of a function call being folded into another
814814
is shown below:
815815

816816
![Expression Folding](../img/folding-before.png "Expression Folding"){ width="500" }
817817

818-
Binary Ninja uses heuristics to determine if this will improve readability, but sometimes it doesn't make the preferred
819-
choice. You can override the heuristic by right-clicking an expression and choosing "Allow" or "Prevent" from the
820-
"Expression Folding" submenu.
818+
Binary Ninja uses heuristics to determine if optimizatoins will improve readability, but sometimes it doesn't make the
819+
preferred choice. In the case above, you can override the heuristic by right-clicking the inner call expression and
820+
choosing "Allow" or "Prevent" from the "Expression Folding" submenu.
821821

822822
![Expression Folding Menu](../img/folding-menu.png "Expression Folding Menu"){ width="500" }
823823

824-
This option will only appear if the expression can be folded. If Binary Ninja's analysis determines that it is not sound
825-
to fold an expression, the submenu will not be present.
824+
These options will only appear if the given optimizations are applied or can be applied. If Binary Ninja's analysis
825+
determines that it is not sound to perform an optimization, the submenus will not be present.
826826

827827
Choosing "Prevent" from the "Expression Folding" menu on the call to `_strlen` in the example above results in the
828828
following output:
829829

830830
![Expression Folding Results](../img/folding-after.png "Expression Folding Results"){ width="500" }
831831

832+
The heuristics can sometimes choose to not apply an optimization. You can override the heuristic to apply the
833+
optimization using the same right-click submenus.
834+
835+
Several optimizations offer the option to override heuristics. The optimizations that support
836+
this feature are shown in the table below:
837+
838+
| Optimization | Description | Valid Locations |
839+
|----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|
840+
| Early Return | Rewrites trailing `if`/`else` constructs to return early from one side. Avoids large indented `if` blocks. | `if` statements |
841+
| Expression Folding | Folds a store of an expression into another expression. Heuristics try to reduce lines of code and number of active variables. | Inner expressions (when optimization is applied) or assignments (when optimization is not applied) |
842+
| Show Condition as Inverted | Heuristics try to pick the best condition for `if`/`else` constructs, but an override can invert the chosen condition and rearrange the `if`/`else` construct. | `if` statements |
843+
| Switch Recovery | Heuristics try to avoid tiny switch constructs. Overrides can choose to display the code as a `switch` or a chain of `if`/`else` constructs. | `if` or `switch` statements |
844+
832845
## Merging and Splitting Variables
833846

834847
Binary Ninja automatically splits all variables that the analysis determines to be safely splittable. This allows the user to assign different types to different uses of the same register or memory location. Sometimes, however, the code is more clear if two or more of these variables are merged together into a single variable.

function.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2849,6 +2849,18 @@ void Function::SetEarlyReturn(uint64_t addr, BNEarlyReturn mode)
28492849
}
28502850

28512851

2852+
BNSwitchRecovery Function::GetSwitchRecovery(uint64_t addr)
2853+
{
2854+
return BNGetSwitchRecovery(m_object, addr);
2855+
}
2856+
2857+
2858+
void Function::SetSwitchRecovery(uint64_t addr, BNSwitchRecovery mode)
2859+
{
2860+
BNSetSwitchRecovery(m_object, addr, mode);
2861+
}
2862+
2863+
28522864
std::map<Variable, std::set<Variable>> Function::GetMergedVariables()
28532865
{
28542866
size_t count;

python/function.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from .enums import (
3030
AnalysisSkipReason, FunctionGraphType, SymbolType, InstructionTextTokenType, HighlightStandardColor,
3131
HighlightColorStyle, DisassemblyOption, IntegerDisplayType, FunctionAnalysisSkipOverride, FunctionUpdateType,
32-
BuiltinType, ExprFolding, EarlyReturn
32+
BuiltinType, ExprFolding, EarlyReturn, SwitchRecovery
3333
)
3434

3535
from . import associateddatastore # Required in the main scope due to being an argument for _FunctionAssociatedDataStore
@@ -3538,6 +3538,16 @@ def set_early_return(self, addr: Union[int, highlevelil.HighLevelILInstruction],
35383538
addr = addr.address
35393539
core.BNSetEarlyReturn(self.handle, addr, value)
35403540

3541+
def get_switch_recovery(self, addr: Union[int, highlevelil.HighLevelILInstruction]) -> SwitchRecovery:
3542+
if isinstance(addr, highlevelil.HighLevelILInstruction):
3543+
addr = addr.address
3544+
return SwitchRecovery(core.BNGetSwitchRecovery(self.handle, addr))
3545+
3546+
def set_switch_recovery(self, addr: Union[int, highlevelil.HighLevelILInstruction], value: SwitchRecovery):
3547+
if isinstance(addr, highlevelil.HighLevelILInstruction):
3548+
addr = addr.address
3549+
core.BNSetSwitchRecovery(self.handle, addr, value)
3550+
35413551

35423552
class AdvancedFunctionAnalysisDataRequestor:
35433553
def __init__(self, func: Optional['Function'] = None):

python/highlevelil.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ class HighLevelILInstruction(BaseILInstruction):
215215
("constant", "int"), ("offset", "int")
216216
], HighLevelILOperation.HLIL_FLOAT_CONST: [("constant", "float")], HighLevelILOperation.HLIL_IMPORT: [
217217
("constant", "int")
218-
], HighLevelILOperation.HLIL_CONST_DATA: [("constant_data", "constant_data")], HighLevelILOperation.HLIL_CONST_DATA: [
219-
("constant_data", "constant_data")
218+
], HighLevelILOperation.HLIL_CONST_DATA: [("constant", "ConstantData")], HighLevelILOperation.HLIL_CONST_DATA: [
219+
("constant", "ConstantData")
220220
], HighLevelILOperation.HLIL_ADD: [("left", "expr"), ("right", "expr")], HighLevelILOperation.HLIL_ADC: [
221221
("left", "expr"), ("right", "expr"), ("carry", "expr")
222222
], HighLevelILOperation.HLIL_SUB: [("left", "expr"), ("right", "expr")], HighLevelILOperation.HLIL_SBB: [
@@ -1811,14 +1811,18 @@ def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]:
18111811

18121812
@dataclass(frozen=True, repr=False, eq=False)
18131813
class HighLevelILConstData(HighLevelILInstruction, Constant):
1814+
@property
1815+
def constant(self) -> variable.ConstantData:
1816+
return self.get_constant_data(0, 1)
1817+
18141818
@property
18151819
def constant_data(self) -> variable.ConstantData:
18161820
return self.get_constant_data(0, 1)
18171821

18181822
@property
18191823
def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]:
18201824
return [
1821-
("constant_data", self.constant_data, "ConstantData"),
1825+
("constant", self.constant, "ConstantData"),
18221826
]
18231827

18241828

@@ -2422,7 +2426,7 @@ def src(self) -> 'mediumlevelil.SSAVariable':
24222426
HighLevelILOperation.HLIL_EXTERN_PTR: HighLevelILExternPtr, # ("constant", "int"), ("offset", "int"),
24232427
HighLevelILOperation.HLIL_FLOAT_CONST: HighLevelILFloatConst, # ("constant", "float"),
24242428
HighLevelILOperation.HLIL_IMPORT: HighLevelILImport, # ("constant", "int"),
2425-
HighLevelILOperation.HLIL_CONST_DATA: HighLevelILConstData, # [("constant_data", "constant_data")],
2429+
HighLevelILOperation.HLIL_CONST_DATA: HighLevelILConstData, # [("constant", "ConstantData")],
24262430
HighLevelILOperation.HLIL_ADD: HighLevelILAdd, # ("left", "expr"), ("right", "expr"),
24272431
HighLevelILOperation.HLIL_ADC: HighLevelILAdc, # ("left", "expr"), ("right", "expr"), ("carry", "expr"),
24282432
HighLevelILOperation.HLIL_SUB: HighLevelILSub, # ("left", "expr"), ("right", "expr"),

python/mediumlevelil.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,8 @@ class MediumLevelILInstruction(BaseILInstruction):
202202
("constant", "int"), ("offset", "int")
203203
], MediumLevelILOperation.MLIL_FLOAT_CONST: [("constant", "float")], MediumLevelILOperation.MLIL_IMPORT: [
204204
("constant", "int")
205-
], MediumLevelILOperation.MLIL_CONST_DATA: [("constant_data", "constant_data")], MediumLevelILOperation.MLIL_CONST_DATA: [
206-
("constant_data", "constant_data")
205+
], MediumLevelILOperation.MLIL_CONST_DATA: [("constant", "ConstantData")], MediumLevelILOperation.MLIL_CONST_DATA: [
206+
("constant", "ConstantData")
207207
], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [
208208
("left", "expr"), ("right", "expr"), ("carry", "expr")
209209
], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_SBB: [
@@ -1318,13 +1318,17 @@ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]:
13181318

13191319
@dataclass(frozen=True, repr=False, eq=False)
13201320
class MediumLevelILConstData(MediumLevelILConstBase):
1321+
@property
1322+
def constant(self) -> variable.ConstantData:
1323+
return self._get_constant_data(0, 1)
1324+
13211325
@property
13221326
def constant_data(self) -> variable.ConstantData:
13231327
return self._get_constant_data(0, 1)
13241328

13251329
@property
13261330
def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]:
1327-
return [("constant_data", self.constant_data, "ConstantData")]
1331+
return [("constant", self.constant, "ConstantData")]
13281332

13291333

13301334
@dataclass(frozen=True, repr=False, eq=False)
@@ -3067,7 +3071,7 @@ def src(self) -> SSAVariable:
30673071
MediumLevelILOperation.MLIL_CONST_PTR: MediumLevelILConstPtr, # [("constant", "int")],
30683072
MediumLevelILOperation.MLIL_FLOAT_CONST: MediumLevelILFloatConst, # [("constant", "float")],
30693073
MediumLevelILOperation.MLIL_IMPORT: MediumLevelILImport, # [("constant", "int")],
3070-
MediumLevelILOperation.MLIL_CONST_DATA: MediumLevelILConstData, # [("constant_data", "constant_data")],
3074+
MediumLevelILOperation.MLIL_CONST_DATA: MediumLevelILConstData, # [("constant", "ConstData")],
30713075
MediumLevelILOperation.MLIL_SET_VAR: MediumLevelILSetVar, # [("dest", "var"), ("src", "expr")],
30723076
MediumLevelILOperation.MLIL_LOAD_STRUCT: MediumLevelILLoadStruct, # [("src", "expr"), ("offset", "int")],
30733077
MediumLevelILOperation.MLIL_STORE: MediumLevelILStore, # [("dest", "expr"), ("src", "expr")],

ui/commands.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ std::optional<uint64_t> getFoldableExprAddress(
9999
BinaryNinja::HighLevelILFunction* hlil, const HighlightTokenState& highlight);
100100
std::optional<uint64_t> getInvertableConditionAddress(BinaryNinja::HighLevelILFunction* hlil, size_t instrIndex);
101101
std::optional<uint64_t> getEarlyReturnAddress(BinaryNinja::HighLevelILFunction* hlil, size_t instrIndex);
102+
std::optional<uint64_t> getSwitchRecoveryAddress(BinaryNinja::HighLevelILFunction* hlil, size_t instrIndex);
102103

103104
/*!
104105
@}

ui/flowgraphwidget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ class BINARYNINJAUIAPI FlowGraphWidget :
172172
bool getCurrentConditionInverted();
173173
std::optional<uint64_t> getCurrentEarlyReturnAddress();
174174
BNEarlyReturn getCurrentEarlyReturn();
175+
std::optional<uint64_t> getCurrentSwitchRecoveryAddress();
176+
BNSwitchRecovery getCurrentSwitchRecovery();
175177
std::optional<std::pair<BinaryNinja::Variable, BinaryNinja::Variable>> getMergeVariablesAtCurrentLocation();
176178

177179
protected:
@@ -404,6 +406,7 @@ class BINARYNINJAUIAPI FlowGraphWidget :
404406
void setCurrentExprFolding(BNExprFolding folding);
405407
void toggleConditionInverted();
406408
void setCurrentEarlyReturn(BNEarlyReturn earlyReturn);
409+
void setCurrentSwitchRecovery(BNSwitchRecovery recovery);
407410
void splitToNewTabAndNavigateFromCursorPosition();
408411
void splitToNewWindowAndNavigateFromCursorPosition();
409412
void splitToNewPaneAndNavigateFromCursorPosition();

ui/linearview.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ class BINARYNINJAUIAPI LinearView : public QAbstractScrollArea, public View, pub
322322
bool getCurrentConditionInverted();
323323
std::optional<uint64_t> getCurrentEarlyReturnAddress();
324324
BNEarlyReturn getCurrentEarlyReturn();
325+
std::optional<uint64_t> getCurrentSwitchRecoveryAddress();
326+
BNSwitchRecovery getCurrentSwitchRecovery();
325327

326328
void setDataButtonVisible(bool visible);
327329
std::optional<std::pair<BinaryNinja::Variable, BinaryNinja::Variable>> getMergeVariablesAtCurrentLocation();
@@ -415,6 +417,7 @@ private Q_SLOTS:
415417
void setCurrentExprFolding(BNExprFolding folding);
416418
void toggleConditionInverted();
417419
void setCurrentEarlyReturn(BNEarlyReturn earlyReturn);
420+
void setCurrentSwitchRecovery(BNSwitchRecovery recovery);
418421

419422
Q_SIGNALS:
420423
void notifyResizeEvent(int width, int height);

0 commit comments

Comments
 (0)