Skip to content

Commit 7077652

Browse files
committed
Fix sysv x86 indirect return stack adjustment, and add APIs and documentation for dereferencing NTRs for GetCallLayout
1 parent 72f8924 commit 7077652

8 files changed

Lines changed: 107 additions & 2 deletions

File tree

arch/x86/arch_x86.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3862,12 +3862,24 @@ class X86SystemVCallingConvention: public X86BaseCallingConvention
38623862
return true;
38633863
if (type->IsStructure() || type->IsArray())
38643864
return false;
3865+
3866+
// If we have an unresolved NTR, we don't actually know what the type is. But it is more likely to
3867+
// be a structure than anything else, so use the same logic as an identified structure.
3868+
if (type->IsNamedTypeRefer())
3869+
return false;
3870+
38653871
if (type->GetWidth() == 0 || type->GetWidth() == 1 || type->GetWidth() == 2 || type->GetWidth() == 4
38663872
|| type->GetWidth() == 8)
38673873
return true;
38683874
return false;
38693875
}
38703876

3877+
bool IsStackAdjustedOnReturn() override
3878+
{
3879+
// Only for indirect returns, see GetStackAdjustmentForLocations below
3880+
return true;
3881+
}
3882+
38713883
int64_t GetStackAdjustmentForLocations(BinaryView*, const std::optional<ValueLocation>& returnValue,
38723884
const vector<ValueLocation>&, const vector<Ref<Type>>&) override
38733885
{

binaryninjaapi.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5520,6 +5520,8 @@ namespace BinaryNinja {
55205520
class TypeArchive;
55215521
class MemoryMap;
55225522
struct HighLevelILInstruction;
5523+
struct FunctionParameter;
5524+
struct ReturnValue;
55235525

55245526
class QueryMetadataException : public ExceptionWithStackTrace
55255527
{
@@ -8253,6 +8255,9 @@ namespace BinaryNinja {
82538255
void SetUserGlobalPointerValue(const Confidence<RegisterValue>& value);
82548256

82558257
std::optional<std::pair<std::string, BNStringType>> StringifyUnicodeData(Architecture* arch, const DataBuffer& buffer, bool nullTerminates = true, bool allowShortStrings = false);
8258+
8259+
std::vector<FunctionParameter> DerefParameterNamedTypeRefs(const std::vector<FunctionParameter>& params);
8260+
ReturnValue DerefReturnValueNamedTypeRefs(const ReturnValue& returnValue);
82568261
};
82578262

82588263
/*! MemoryMap provides access to the system-level memory map describing how a BinaryView is loaded into memory.
@@ -18252,6 +18257,11 @@ namespace BinaryNinja {
1825218257

1825318258
The default implementation calls GetDefaultCallLayout.
1825418259

18260+
When calling this function to query the layout of a function, the return value and parameters
18261+
should have their named type references dereferenced before passing them to this function.
18262+
Calling the functions BinaryView::DerefReturnValueNamedTypeRefs and
18263+
BinaryView::DerefParameterNamedTypeRefs will perform this dereferencing.
18264+
1825518265
\param view BinaryView providing type information
1825618266
\param returnValue Return value of the call
1825718267
\param params Parameters of the call

binaryview.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5847,6 +5847,26 @@ Ref<Relocation> BinaryView::GetNextRelocation(uint64_t addr, uint64_t maxAddr)
58475847
}
58485848

58495849

5850+
vector<FunctionParameter> BinaryView::DerefParameterNamedTypeRefs(const vector<FunctionParameter>& params)
5851+
{
5852+
vector<FunctionParameter> result;
5853+
result.reserve(params.size());
5854+
for (auto& i : params)
5855+
result.emplace_back(i.name, i.type->DerefNamedTypeReference(this)->WithConfidence(i.type.GetConfidence()),
5856+
i.locationSource, i.location);
5857+
return result;
5858+
}
5859+
5860+
5861+
ReturnValue BinaryView::DerefReturnValueNamedTypeRefs(const ReturnValue& returnValue)
5862+
{
5863+
ReturnValue result = returnValue;
5864+
if (result.type.GetValue())
5865+
result.type.SetValue(result.type->DerefNamedTypeReference(this));
5866+
return result;
5867+
}
5868+
5869+
58505870
Relocation::Relocation(BNRelocation* reloc)
58515871
{
58525872
m_object = reloc;

python/binaryview.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11037,6 +11037,24 @@ def stringify_unicode_data(self, arch: Optional['architecture.Architecture'], bu
1103711037
core.free_string(string)
1103811038
return result, StringType(string_type.value)
1103911039

11040+
def deref_parameter_named_type_references(self, params: List['_types.FunctionParameter']):
11041+
result = []
11042+
for param in params:
11043+
if param.type is None:
11044+
ty = None
11045+
else:
11046+
ty = param.type.deref_named_type_reference(self).with_confidence(param.type.confidence)
11047+
result.append(_types.FunctionParameter(ty, param.name, param.location, param.location_source))
11048+
return result
11049+
11050+
def deref_return_value_named_type_references(self, value: '_types.ReturnValue'):
11051+
if value.type is None:
11052+
ty = None
11053+
else:
11054+
ty = value.type.deref_named_type_reference(self).with_confidence(value.type.confidence)
11055+
return _types.ReturnValue(ty, value.location)
11056+
11057+
1104011058
class BinaryReader:
1104111059
"""
1104211060
``class BinaryReader`` is a convenience class for reading binary data.

python/callingconvention.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,11 @@ def get_call_layout(
10711071
10721072
The default implementation calls :py:meth:`get_default_call_layout`.
10731073
1074+
When calling this method to query the layout of a function, the return value and parameters
1075+
should have their named type references dereferenced before passing them to this method.
1076+
Calling the methods :py:meth:`BinaryView.deref_return_value_named_type_references` and
1077+
:py:meth:`BinaryView.deref_parameter_named_type_references` will perform this dereferencing.
1078+
10741079
:param BinaryView view: binary view providing type information
10751080
:param return_value: return value of the call
10761081
:param params: parameters of the call

rust/src/binary_view.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ use crate::string::*;
5151
use crate::symbol::{Symbol, SymbolType};
5252
use crate::tags::{Tag, TagReference, TagType};
5353
use crate::types::{
54-
NamedTypeReference, QualifiedName, QualifiedNameAndType, QualifiedNameTypeAndId, Type,
55-
TypeArchive, TypeArchiveId, TypeContainer, TypeLibrary,
54+
FunctionParameter, NamedTypeReference, QualifiedName, QualifiedNameAndType,
55+
QualifiedNameTypeAndId, ReturnValue, Type, TypeArchive, TypeArchiveId, TypeContainer,
56+
TypeLibrary,
5657
};
5758
use crate::variable::DataVariable;
5859
use crate::workflow::Workflow;
@@ -2964,6 +2965,36 @@ impl BinaryView {
29642965
let path_str = unsafe { BnString::into_string(result) };
29652966
Some(PathBuf::from(path_str))
29662967
}
2968+
2969+
pub fn deref_return_value_named_type_references(
2970+
&self,
2971+
return_value: &ReturnValue,
2972+
) -> ReturnValue {
2973+
ReturnValue {
2974+
ty: Conf::new(
2975+
return_value.ty.contents.deref_named_type_reference(self),
2976+
return_value.ty.confidence,
2977+
),
2978+
location: return_value.location.clone(),
2979+
}
2980+
}
2981+
2982+
pub fn deref_parameter_named_type_references(
2983+
&self,
2984+
params: &[FunctionParameter],
2985+
) -> Vec<FunctionParameter> {
2986+
params
2987+
.iter()
2988+
.map(|param| FunctionParameter {
2989+
ty: Conf::new(
2990+
param.ty.contents.deref_named_type_reference(self),
2991+
param.ty.confidence,
2992+
),
2993+
name: param.name.clone(),
2994+
location: param.location.clone(),
2995+
})
2996+
.collect()
2997+
}
29672998
}
29682999

29693000
impl BinaryViewBase for BinaryView {

rust/src/calling_convention.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ pub trait CallingConvention: 'static + Sync + Sized + AsRef<CoreCallingConventio
210210
/// It is recommended to only override this method if the calling convention behavior cannot be
211211
/// modeled with [`CallingConvention::return_value_location`] and/or
212212
/// [`CallingConvention::parameter_locations`].
213+
///
214+
/// When calling this function to query the layout of a function, the return value and
215+
/// parameters should have their named type references dereferenced before passing them to
216+
/// this function. Calling the functions [`BinaryView::deref_return_value_named_type_references`]
217+
/// and [`BinaryView::deref_parameter_named_type_references`] will perform this dereferencing.
213218
fn call_layout(
214219
&self,
215220
view: Option<&BinaryView>,

rust/src/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,10 @@ impl Type {
10841084
QualifiedName::free_raw(raw_name);
10851085
type_id
10861086
}
1087+
1088+
pub fn deref_named_type_reference(&self, view: &BinaryView) -> Ref<Type> {
1089+
unsafe { Self::ref_from_raw(BNDerefNamedTypeReference(view.handle, self.handle)) }
1090+
}
10871091
}
10881092

10891093
impl Display for Type {

0 commit comments

Comments
 (0)