summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h28
-rw-r--r--binaryninjacore.h32
-rw-r--r--function.cpp27
-rw-r--r--plugins/workflow_objc/src/activities/inline_stubs.rs4
-rw-r--r--python/function.py41
-rw-r--r--python/types.py35
-rw-r--r--rust/src/confidence.rs21
-rw-r--r--rust/src/function.rs9
-rw-r--r--view/sharedcache/workflow/SharedCacheWorkflow.cpp2
9 files changed, 157 insertions, 42 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index db54a9a8..e28ebfb1 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -13139,6 +13139,8 @@ namespace BinaryNinja {
bool GetInstructionContainingAddress(Architecture* arch, uint64_t addr, uint64_t* start);
Confidence<bool> IsInlinedDuringAnalysis();
+ Confidence<BNInlineDuringAnalysis> GetInlinedDuringAnalysis();
+
/*! Set whether the function should be inlined during analysis.
This will take effect if the new confidence level is higher than the confidence
@@ -13148,8 +13150,30 @@ namespace BinaryNinja {
\param inlined Whether the function should be inlined.
*/
- void SetAutoInlinedDuringAnalysis(Confidence<bool> inlined);
- void SetUserInlinedDuringAnalysis(Confidence<bool> inlined);
+ void SetAutoInlinedDuringAnalysis(Confidence<BNInlineDuringAnalysis> inlined);
+ void SetUserInlinedDuringAnalysis(Confidence<BNInlineDuringAnalysis> inlined);
+
+ // These overloads are needed to disambiguate calls that pass enum values directly.
+ void SetAutoInlinedDuringAnalysis(BNInlineDuringAnalysis inlined) { SetAutoInlinedDuringAnalysis(Confidence(inlined)); }
+ void SetUserInlinedDuringAnalysis(BNInlineDuringAnalysis inlined) { SetUserInlinedDuringAnalysis(Confidence(inlined)); }
+
+ /*!
+ \deprecated Use the overload that takes `BNInlineDuringAnalysis`.
+ */
+ void SetAutoInlinedDuringAnalysis(Confidence<bool> inlined)
+ {
+ BNInlineDuringAnalysis value = inlined.GetValue() ? InlinePreservingTargetInstructionAddresses : DoNotInlineCall;
+ SetAutoInlinedDuringAnalysis(Confidence(value, inlined.GetConfidence()));
+ };
+
+ /*!
+ \deprecated Use the overload that takes `BNInlineDuringAnalysis`.
+ */
+ void SetUserInlinedDuringAnalysis(Confidence<bool> inlined)
+ {
+ BNInlineDuringAnalysis value = inlined.GetValue() ? InlinePreservingTargetInstructionAddresses : DoNotInlineCall;
+ SetUserInlinedDuringAnalysis(Confidence(value, inlined.GetConfidence()));
+ };
// TODO: Documentation
bool IsInstructionCollapsed(const HighLevelILInstruction& instr, uint64_t designator = 0) const;
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 8144ed7e..1e346bb1 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -1131,6 +1131,33 @@ extern "C"
MemoryIntrinsicClass
};
+ BN_ENUM(uint8_t, BNInlineDuringAnalysis)
+ {
+ // The called function should not be inlined.
+ DoNotInlineCall,
+
+ // The called function should be inlined, with the inlined
+ // instructions preserving their original addresses.
+ // This was the only behavior available up through Binary Ninja 5.2.
+ InlinePreservingTargetInstructionAddresses,
+
+ // The called function should be inlined, with the inlined
+ // instructions using the call site address as their address.
+ // This ensures that when the function is inlined into a caller
+ // multiple times, each occurrence can have different adjustments
+ // applied to it. The trade-off is that the instructions inlined
+ // at a given call site have the same address, which in turn
+ // prevents applying adjustments that depend on instruction
+ // address to only a subset of those instructions.
+ InlineUsingCallAddress,
+ };
+
+ typedef struct BNInlineDuringAnalysisWithConfidence
+ {
+ BNInlineDuringAnalysis value;
+ uint8_t confidence;
+ } BNInlineDuringAnalysisWithConfidence;
+
typedef struct BNLowLevelILInstruction
{
BNLowLevelILOperation operation;
@@ -5175,8 +5202,9 @@ extern "C"
BINARYNINJACOREAPI BNRegisterValueWithConfidence BNGetFunctionRegisterValueAtExit(BNFunction* func, uint32_t reg);
BINARYNINJACOREAPI BNBoolWithConfidence BNIsFunctionInlinedDuringAnalysis(BNFunction* func);
- BINARYNINJACOREAPI void BNSetAutoFunctionInlinedDuringAnalysis(BNFunction* func, BNBoolWithConfidence inlined);
- BINARYNINJACOREAPI void BNSetUserFunctionInlinedDuringAnalysis(BNFunction* func, BNBoolWithConfidence inlined);
+ BINARYNINJACOREAPI BNInlineDuringAnalysisWithConfidence BNGetFunctionInlinedDuringAnalysis(BNFunction* func);
+ BINARYNINJACOREAPI void BNSetAutoFunctionInlinedDuringAnalysis(BNFunction* func, BNInlineDuringAnalysisWithConfidence inlined);
+ BINARYNINJACOREAPI void BNSetUserFunctionInlinedDuringAnalysis(BNFunction* func, BNInlineDuringAnalysisWithConfidence inlined);
BINARYNINJACOREAPI bool BNGetInstructionContainingAddress(
BNFunction* func, BNArchitecture* arch, uint64_t addr, uint64_t* start);
diff --git a/function.cpp b/function.cpp
index d5e692de..3f5f5b2e 100644
--- a/function.cpp
+++ b/function.cpp
@@ -3230,21 +3230,28 @@ Confidence<bool> Function::IsInlinedDuringAnalysis()
}
-void Function::SetAutoInlinedDuringAnalysis(Confidence<bool> inlined)
+Confidence<BNInlineDuringAnalysis> Function::GetInlinedDuringAnalysis()
{
- BNBoolWithConfidence bc;
- bc.value = inlined.GetValue();
- bc.confidence = inlined.GetConfidence();
- BNSetAutoFunctionInlinedDuringAnalysis(m_object, bc);
+ BNInlineDuringAnalysisWithConfidence value = BNGetFunctionInlinedDuringAnalysis(m_object);
+ return Confidence(value.value, value.confidence);
}
-void Function::SetUserInlinedDuringAnalysis(Confidence<bool> inlined)
+void Function::SetAutoInlinedDuringAnalysis(Confidence<BNInlineDuringAnalysis> inlined)
{
- BNBoolWithConfidence bc;
- bc.value = inlined.GetValue();
- bc.confidence = inlined.GetConfidence();
- BNSetUserFunctionInlinedDuringAnalysis(m_object, bc);
+ BNInlineDuringAnalysisWithConfidence value;
+ value.value = inlined.GetValue();
+ value.confidence = inlined.GetConfidence();
+ BNSetAutoFunctionInlinedDuringAnalysis(m_object, value);
+}
+
+
+void Function::SetUserInlinedDuringAnalysis(Confidence<BNInlineDuringAnalysis> inlined)
+{
+ BNInlineDuringAnalysisWithConfidence value;
+ value.value = inlined.GetValue();
+ value.confidence = inlined.GetConfidence();
+ BNSetUserFunctionInlinedDuringAnalysis(m_object, value);
}
diff --git a/plugins/workflow_objc/src/activities/inline_stubs.rs b/plugins/workflow_objc/src/activities/inline_stubs.rs
index daae9baa..8ddb2fa3 100644
--- a/plugins/workflow_objc/src/activities/inline_stubs.rs
+++ b/plugins/workflow_objc/src/activities/inline_stubs.rs
@@ -1,4 +1,4 @@
-use binaryninja::workflow::AnalysisContext;
+use binaryninja::{function::InlineDuringAnalysis, workflow::AnalysisContext};
use crate::{metadata::GlobalState, Error};
@@ -19,7 +19,7 @@ pub fn process(ac: &AnalysisContext) -> Result<(), Error> {
};
if objc_stubs.contains(&func.start()) {
- func.set_auto_inline_during_analysis(true);
+ func.set_auto_inline_during_analysis(InlineDuringAnalysis::InlineUsingCallAddress);
}
Ok(())
diff --git a/python/function.py b/python/function.py
index c328ca77..29527f4d 100644
--- a/python/function.py
+++ b/python/function.py
@@ -1667,13 +1667,13 @@ class Function:
return self.view.get_function_parent_components(self)
@property
- def inline_during_analysis(self) -> 'types.BoolWithConfidence':
+ def inline_during_analysis(self) -> 'types.InlineDuringAnalysisWithConfidence':
"""Whether the function's IL should be inlined into all callers' IL"""
- result = core.BNIsFunctionInlinedDuringAnalysis(self.handle)
- return types.BoolWithConfidence(result.value, confidence=result.confidence)
+ result = core.BNGetFunctionInlinedDuringAnalysis(self.handle)
+ return types.InlineDuringAnalysisWithConfidence(result.value, confidence=result.confidence)
@inline_during_analysis.setter
- def inline_during_analysis(self, value: Union[bool, 'types.BoolWithConfidence']):
+ def inline_during_analysis(self, value: Union['types.InlineDuringAnalysis', 'types.InlineDuringAnalysisWithConfidence', bool, 'types.BoolWithConfidence']):
self.set_user_inline_during_analysis(value)
def mark_recent_use(self) -> None:
@@ -3553,23 +3553,26 @@ class Function:
"""
core.BNUnsplitVariable(self.handle, var.to_BNVariable())
- def set_auto_inline_during_analysis(self, value: Union[bool, 'types.BoolWithConfidence']):
- bc = core.BNBoolWithConfidence()
- bc.value = bool(value)
- if isinstance(value, types.BoolWithConfidence):
- bc.confidence = value.confidence
- else:
- bc.confidence = core.max_confidence
- core.BNSetAutoFunctionInlinedDuringAnalysis(self.handle, bc)
+ @classmethod
+ def _inline_during_analysis_with_confidence(cls, value: Union['types.InlineDuringAnalysis', 'types.InlineDuringAnalysisWithConfidence', bool, 'types.BoolWithConfidence']) -> 'types.InlineDuringAnalysisWithConfidence':
+ if isinstance(value, types.InlineDuringAnalysisWithConfidence):
+ return value
- def set_user_inline_during_analysis(self, value: Union[bool, 'types.BoolWithConfidence']):
- bc = core.BNBoolWithConfidence()
- bc.value = bool(value)
if isinstance(value, types.BoolWithConfidence):
- bc.confidence = value.confidence
- else:
- bc.confidence = core.max_confidence
- core.BNSetUserFunctionInlinedDuringAnalysis(self.handle, bc)
+ return core.BNInlineDuringAnalysisWithConfidence(int(value.value), value.confidence)
+
+ if isinstance(value, bool):
+ return core.BNInlineDuringAnalysisWithConfidence(int(value), core.max_confidence)
+
+ return core.BNInlineDuringAnalysisWithConfidence(value, core.max_confidence)
+
+ def set_auto_inline_during_analysis(self, value: Union['types.InlineDuringAnalysis', 'types.InlineDuringAnalysisWithConfidence', bool, 'types.BoolWithConfidence']):
+ value = self._inline_during_analysis_with_confidence(value)
+ core.BNSetAutoFunctionInlinedDuringAnalysis(self.handle, value)
+
+ def set_user_inline_during_analysis(self, value: Union['types.InlineDuringAnalysis', 'types.InlineDuringAnalysisWithConfidence', bool, 'types.BoolWithConfidence']):
+ value = self._inline_during_analysis_with_confidence(value)
+ core.BNSetUserFunctionInlinedDuringAnalysis(self.handle, value)
def toggle_region(self, hash):
"""
diff --git a/python/types.py b/python/types.py
index a47f531d..44583c4d 100644
--- a/python/types.py
+++ b/python/types.py
@@ -27,7 +27,7 @@ import uuid
# Binary Ninja components
from . import _binaryninjacore as core
from .enums import (
- StructureVariant, SymbolType, SymbolBinding, TypeClass, NamedTypeReferenceClass,
+ InlineDuringAnalysis, StructureVariant, SymbolType, SymbolBinding, TypeClass, NamedTypeReferenceClass,
ReferenceType, VariableSourceType,
TypeReferenceType, MemberAccess, MemberScope, TypeDefinitionLineType,
TokenEscapingType,
@@ -528,6 +528,39 @@ class BoolWithConfidence:
return BoolWithConfidence(value, confidence)._to_core_struct()
+@dataclass(frozen=True)
+class InlineDuringAnalysisWithConfidence:
+ """Represents an InlineDuringAnalysis value with an associated confidence level."""
+ value: InlineDuringAnalysis
+ confidence: int = core.max_confidence
+
+ def __eq__(self, other):
+ if not isinstance(other, self.__class__):
+ # For backward compatibility, allow comparison with bool
+ if isinstance(other, bool):
+ return bool(self.value) == other
+ # Allow comparison with enum value directly
+ return self.value == other
+ else:
+ return (self.value, self.confidence) == (other.value, other.confidence)
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __bool__(self):
+ return bool(self.value)
+
+ def _to_core_struct(self) -> core.BNInlineDuringAnalysisWithConfidence:
+ result = core.BNInlineDuringAnalysisWithConfidence()
+ result.value = self.value
+ result.confidence = self.confidence
+ return result
+
+ @classmethod
+ def from_core_struct(cls, core_struct: core.BNInlineDuringAnalysisWithConfidence) -> 'InlineDuringAnalysisWithConfidence':
+ return cls(InlineDuringAnalysis(core_struct.value), core_struct.confidence)
+
+
@dataclass
class MutableTypeBuilder(Generic[TB]):
type: TB
diff --git a/rust/src/confidence.rs b/rust/src/confidence.rs
index fd0b5532..f8745180 100644
--- a/rust/src/confidence.rs
+++ b/rust/src/confidence.rs
@@ -6,7 +6,8 @@ use crate::rc::{Ref, RefCountable};
use crate::types::Type;
use binaryninjacore_sys::{
BNBoolWithConfidence, BNCallingConventionWithConfidence, BNGetCallingConventionArchitecture,
- BNOffsetWithConfidence, BNTypeWithConfidence,
+ BNInlineDuringAnalysis, BNInlineDuringAnalysisWithConfidence, BNOffsetWithConfidence,
+ BNTypeWithConfidence,
};
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
@@ -280,6 +281,15 @@ impl From<BNOffsetWithConfidence> for Conf<i64> {
}
}
+impl From<BNInlineDuringAnalysisWithConfidence> for Conf<BNInlineDuringAnalysis> {
+ fn from(inline_with_confidence: BNInlineDuringAnalysisWithConfidence) -> Self {
+ Self::new(
+ inline_with_confidence.value,
+ inline_with_confidence.confidence,
+ )
+ }
+}
+
impl From<Conf<bool>> for BNBoolWithConfidence {
fn from(conf: Conf<bool>) -> Self {
Self {
@@ -297,3 +307,12 @@ impl From<Conf<i64>> for BNOffsetWithConfidence {
}
}
}
+
+impl From<Conf<BNInlineDuringAnalysis>> for BNInlineDuringAnalysisWithConfidence {
+ fn from(conf: Conf<BNInlineDuringAnalysis>) -> Self {
+ Self {
+ value: conf.contents,
+ confidence: conf.confidence,
+ }
+ }
+}
diff --git a/rust/src/function.rs b/rust/src/function.rs
index e5516d14..c19e2107 100644
--- a/rust/src/function.rs
+++ b/rust/src/function.rs
@@ -36,6 +36,7 @@ pub use binaryninjacore_sys::BNBuiltinType as BuiltinType;
pub use binaryninjacore_sys::BNFunctionAnalysisSkipOverride as FunctionAnalysisSkipOverride;
pub use binaryninjacore_sys::BNFunctionUpdateType as FunctionUpdateType;
pub use binaryninjacore_sys::BNHighlightStandardColor as HighlightStandardColor;
+pub use binaryninjacore_sys::BNInlineDuringAnalysis as InlineDuringAnalysis;
use crate::architecture::{IndirectBranchInfo, RegisterId};
use crate::binary_view::AddressRange;
@@ -1127,17 +1128,17 @@ impl Function {
pub fn set_auto_inline_during_analysis<C>(&self, value: C)
where
- C: Into<Conf<bool>>,
+ C: Into<Conf<InlineDuringAnalysis>>,
{
- let value: Conf<bool> = value.into();
+ let value: Conf<InlineDuringAnalysis> = value.into();
unsafe { BNSetAutoFunctionInlinedDuringAnalysis(self.handle, value.into()) }
}
pub fn set_user_inline_during_analysis<C>(&self, value: C)
where
- C: Into<Conf<bool>>,
+ C: Into<Conf<InlineDuringAnalysis>>,
{
- let value: Conf<bool> = value.into();
+ let value: Conf<InlineDuringAnalysis> = value.into();
unsafe { BNSetUserFunctionInlinedDuringAnalysis(self.handle, value.into()) }
}
diff --git a/view/sharedcache/workflow/SharedCacheWorkflow.cpp b/view/sharedcache/workflow/SharedCacheWorkflow.cpp
index dcdf6c23..2b9cd28b 100644
--- a/view/sharedcache/workflow/SharedCacheWorkflow.cpp
+++ b/view/sharedcache/workflow/SharedCacheWorkflow.cpp
@@ -199,7 +199,7 @@ void AnalyzeStubFunction(Ref<Function> func, Ref<MediumLevelILFunction> mlil, Sh
{
case MLIL_CONST_PTR:
// NOTE: This runs every single function update.
- func->SetAutoInlinedDuringAnalysis(true);
+ func->SetAutoInlinedDuringAnalysis(InlineUsingCallAddress);
break;
default:
break;