Skip to content

Commit 145f517

Browse files
committed
Allow function parameters to specify they need to be passed by reference/value without specifying an exact location
1 parent f951f8a commit 145f517

File tree

14 files changed

+126
-63
lines changed

14 files changed

+126
-63
lines changed

arch/x86/arch_x86.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4863,7 +4863,7 @@ class X64SystemVCallingConvention: public X64BaseCallingConvention
48634863

48644864
for (auto& param : params)
48654865
{
4866-
if (!param.defaultLocation)
4866+
if (param.locationSource == CustomLocationSource)
48674867
{
48684868
// Parameter is not stored in a normal location, use custom variable
48694869
result.push_back(param.location);
@@ -4887,7 +4887,8 @@ class X64SystemVCallingConvention: public X64BaseCallingConvention
48874887
size_t width = type->GetWidth();
48884888
bool indirect = false;
48894889

4890-
if (type->GetClass() == ArrayTypeClass)
4890+
if ((type->GetClass() == ArrayTypeClass || param.locationSource == PassByReferenceLocationSource)
4891+
&& param.locationSource != PassByValueLocationSource)
48914892
{
48924893
type = Type::PointerType(GetArchitecture(), type);
48934894
indirect = true;

binaryninjaapi.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10604,16 +10604,16 @@ namespace BinaryNinja {
1060410604
{
1060510605
std::string name;
1060610606
Confidence<Ref<Type>> type;
10607-
bool defaultLocation;
10607+
BNValueLocationSource locationSource;
1060810608
ValueLocation location;
1060910609

1061010610
FunctionParameter() = default;
10611-
FunctionParameter(const std::string& name, Confidence<Ref<Type>> type): name(name), type(type), defaultLocation(true)
10611+
FunctionParameter(const std::string& name, Confidence<Ref<Type>> type): name(name), type(type), locationSource(DefaultLocationSource)
1061210612
{}
1061310613

10614-
FunctionParameter(const std::string& name, const Confidence<Ref<Type>>& type, bool defaultLocation,
10614+
FunctionParameter(const std::string& name, const Confidence<Ref<Type>>& type, BNValueLocationSource source,
1061510615
const ValueLocation& location) :
10616-
name(name), type(type), defaultLocation(defaultLocation), location(location)
10616+
name(name), type(type), locationSource(source), location(location)
1061710617
{}
1061810618

1061910619
static FunctionParameter FromAPIObject(const BNFunctionParameter* param);

binaryninjacore.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2637,12 +2637,20 @@ extern "C"
26372637
uint8_t confidence;
26382638
} BNValueLocationListWithConfidence;
26392639

2640+
BN_ENUM(uint8_t, BNValueLocationSource)
2641+
{
2642+
DefaultLocationSource,
2643+
PassByValueLocationSource,
2644+
PassByReferenceLocationSource,
2645+
CustomLocationSource
2646+
};
2647+
26402648
typedef struct BNFunctionParameter
26412649
{
26422650
char* name;
26432651
BNType* type;
26442652
uint8_t typeConfidence;
2645-
bool defaultLocation;
2653+
BNValueLocationSource locationSource;
26462654
BNValueLocation location;
26472655
} BNFunctionParameter;
26482656

demangler/gnu3/demangle_gnu3.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ TypeBuilder DemangleGNU3::DemangleFunction(bool cnst, bool vltl)
312312
continue;
313313
MyLogDebug("Var_%d - %s\n", i++, param.GetString().c_str());
314314
m_functionSubstitute.back().push_back(param);
315-
params.push_back({"", param.Finalize(), true, Variable()});
315+
params.push_back({"", param.Finalize(), DefaultLocationSource, Variable()});
316316
}
317317
m_reader.Consume();
318318
m_functionSubstitute.pop_back();
@@ -1640,12 +1640,12 @@ void DemangleGNU3::DemangleTemplateArgs(vector<FunctionParameter>& args)
16401640
{
16411641
case 'L':
16421642
expr = DemanglePrimaryExpression();
1643-
args.push_back({expr, nullptr, true, Variable()});
1643+
args.push_back({expr, nullptr, DefaultLocationSource, Variable()});
16441644
tmp = CreateUnknownType(expr);
16451645
tmpValid = true;
16461646
break;
16471647
case 'X':
1648-
args.push_back({DemangleExpression(), nullptr, true, Variable()});
1648+
args.push_back({DemangleExpression(), nullptr, DefaultLocationSource, Variable()});
16491649
if (m_reader.Read() != 'E')
16501650
throw DemangleException();
16511651
break;
@@ -1658,7 +1658,7 @@ void DemangleGNU3::DemangleTemplateArgs(vector<FunctionParameter>& args)
16581658
m_topLevel = false;
16591659
tmp = DemangleType();
16601660
m_topLevel = topLevel;
1661-
args.push_back({tmp.GetString(), nullptr, true, Variable()});
1661+
args.push_back({tmp.GetString(), nullptr, DefaultLocationSource, Variable()});
16621662
tmpValid = true;
16631663
}
16641664
if (m_topLevel && tmpValid)
@@ -2202,7 +2202,7 @@ TypeBuilder DemangleGNU3::DemangleSymbol(QualifiedName& varName)
22022202
break;
22032203
}
22042204
m_functionSubstitute.back().push_back(param);
2205-
params.push_back({"", param.Finalize(), true, Variable()});
2205+
params.push_back({"", param.Finalize(), DefaultLocationSource, Variable()});
22062206
if (param.GetClass() == VarArgsTypeClass)
22072207
{
22082208
if (m_reader.Peek() == 'E')

demangler/msvc/demangle_msvc.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ void Demangle::DemangleVariableList(vector<FunctionParameter>& paramList, Backre
732732
}
733733
vt.name = name.GetString();
734734
vt.type = type.Finalize();
735-
vt.defaultLocation = true;
735+
vt.locationSource = DefaultLocationSource;
736736

737737
paramList.push_back(vt);
738738
m_logger->LogDebug("Argument %zu: '%s' - '%s'\n", i, vt.type->GetString().c_str(), reader.GetRaw());
@@ -1607,7 +1607,7 @@ TypeBuilder Demangle::DemangleFunction(BNNameType classFunctionType, bool pointe
16071607
QualifiedName thisName = m_varName;
16081608
if (thisName.size() > 0)
16091609
thisName.erase(thisName.end() - 1);
1610-
params.push_back(FunctionParameter("this", Type::PointerType(m_arch, Type::NamedType(thisName, Type::VoidType())), true, {}));
1610+
params.push_back(FunctionParameter("this", Type::PointerType(m_arch, Type::NamedType(thisName, Type::VoidType())), DefaultLocationSource, {}));
16111611
}
16121612

16131613
DemangleVariableList(params, m_backrefList);

lang/rust/rusttypes.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,13 @@ vector<InstructionTextToken> RustTypePrinter::GetTypeTokensAfterNameInternal(
173173
}
174174
tokens.push_back(nameToken);
175175
tokens.emplace_back(TextToken, ": ");
176+
177+
if (params[i].locationSource == PassByReferenceLocationSource || params[i].location.indirect)
178+
tokens.emplace_back(baseConfidence, OperationToken, "&");
179+
176180
tokens.insert(tokens.end(), paramTokens.begin(), paramTokens.end());
177181

178-
if (!params[i].defaultLocation && platform && var.has_value())
182+
if (params[i].locationSource == CustomLocationSource && platform && var.has_value())
179183
{
180184
switch (var->type)
181185
{

objectivec/objc.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,9 +1247,9 @@ bool ObjCProcessor::ApplyMethodType(Class& cls, Method& method, bool isInstanceM
12471247
cls.associatedName.IsEmpty() ?
12481248
m_types.id :
12491249
Type::PointerType(m_data->GetAddressSize(), Type::NamedType(m_data, cls.associatedName)),
1250-
true, BinaryNinja::Variable()});
1250+
DefaultLocationSource, BinaryNinja::Variable()});
12511251

1252-
params.push_back({"sel", m_types.sel, true, BinaryNinja::Variable()});
1252+
params.push_back({"sel", m_types.sel, DefaultLocationSource, BinaryNinja::Variable()});
12531253

12541254
for (size_t i = 3; i < typeTokens.size(); i++)
12551255
{
@@ -1259,7 +1259,7 @@ bool ObjCProcessor::ApplyMethodType(Class& cls, Method& method, bool isInstanceM
12591259
else
12601260
name = "arg";
12611261

1262-
params.push_back({std::move(name), typeForQualifiedNameOrType(typeTokens[i]), true, BinaryNinja::Variable()});
1262+
params.push_back({std::move(name), typeForQualifiedNameOrType(typeTokens[i]), DefaultLocationSource, BinaryNinja::Variable()});
12631263
}
12641264

12651265
auto funcType = BinaryNinja::Type::FunctionType(retType, cc, params);

plugins/workflow_swift/src/demangler/function_type.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use binaryninja::architecture::{ArchitectureExt, CoreArchitecture};
22
use binaryninja::confidence::Conf;
33
use binaryninja::rc::Ref;
4-
use binaryninja::types::{FunctionParameter, Type, ValueLocation};
4+
use binaryninja::types::{FunctionParameter, Type, ValueLocation, ValueLocationSource};
55
use swift_demangler::{
66
Accessor, AccessorKind, ConstructorKind, HasFunctionSignature, HasModule, Metadata,
77
MetadataKind, Symbol,
@@ -78,7 +78,7 @@ impl CallingConvention {
7878
self.leading_params.push(FunctionParameter {
7979
ty: self_ty.into(),
8080
name: "self".to_string(),
81-
location: None,
81+
location: ValueLocationSource::Default,
8282
});
8383
}
8484

@@ -98,12 +98,12 @@ impl CallingConvention {
9898
self.trailing_params.push(FunctionParameter {
9999
ty: void_ptr.clone().into(),
100100
name: "selfMetadata".to_string(),
101-
location: None,
101+
location: ValueLocationSource::Default,
102102
});
103103
self.trailing_params.push(FunctionParameter {
104104
ty: void_ptr.into(),
105105
name: "selfWitnessTable".to_string(),
106-
location: None,
106+
location: ValueLocationSource::Default,
107107
});
108108
}
109109

@@ -139,7 +139,7 @@ impl CallingConvention {
139139
all_params.push(FunctionParameter {
140140
ty: error_ty.into(),
141141
name: "error".to_string(),
142-
location: self.abi.as_ref().and_then(|a| a.error_location()),
142+
location: self.abi.as_ref().and_then(|a| a.error_location()).into(),
143143
});
144144
}
145145

@@ -148,7 +148,11 @@ impl CallingConvention {
148148
all_params.push(FunctionParameter {
149149
ty: ptr_ty.into(),
150150
name: "asyncContext".to_string(),
151-
location: self.abi.as_ref().and_then(|a| a.async_context_location()),
151+
location: self
152+
.abi
153+
.as_ref()
154+
.and_then(|a| a.async_context_location())
155+
.into(),
152156
});
153157
}
154158

@@ -240,7 +244,7 @@ pub fn build_function_type(symbol: &Symbol, arch: &CoreArchitecture) -> Option<R
240244
Some(FunctionParameter {
241245
ty: ty.into(),
242246
name,
243-
location: None,
247+
location: ValueLocationSource::Default,
244248
})
245249
})
246250
.collect();
@@ -283,7 +287,7 @@ fn build_accessor_type(accessor: &Accessor, arch: &CoreArchitecture) -> Option<R
283287
let params = vec![FunctionParameter {
284288
ty: prop_ty.into(),
285289
name: "newValue".to_string(),
286-
location: None,
290+
location: ValueLocationSource::Default,
287291
}];
288292
Some(cc.build_type(&Type::void(), params))
289293
}
@@ -309,12 +313,12 @@ fn build_metadata_function_type(metadata: &Metadata, arch: &CoreArchitecture) ->
309313
FunctionParameter {
310314
ty: void_ptr.clone().into(),
311315
name: "metadata".to_string(),
312-
location: None,
316+
location: ValueLocationSource::Default,
313317
},
314318
FunctionParameter {
315319
ty: void_ptr.clone().into(),
316320
name: "method".to_string(),
317-
location: None,
321+
location: ValueLocationSource::Default,
318322
},
319323
];
320324
Some(Type::function(&void_ptr, params, false))

plugins/workflow_swift/src/demangler/type_reconstruction.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use binaryninja::architecture::{Architecture, CoreArchitecture};
22
use binaryninja::rc::Ref;
3-
use binaryninja::types::{NamedTypeReference, NamedTypeReferenceClass, QualifiedName, Type};
3+
use binaryninja::types::{
4+
NamedTypeReference, NamedTypeReferenceClass, QualifiedName, Type, ValueLocationSource,
5+
};
46
use swift_demangler::{TypeKind, TypeRef};
57

68
pub(crate) trait TypeRefExt {
@@ -57,7 +59,7 @@ impl TypeRefExt for TypeRef<'_> {
5759
Some(binaryninja::types::FunctionParameter {
5860
ty: ty.into(),
5961
name,
60-
location: None,
62+
location: ValueLocationSource::Default,
6163
})
6264
})
6365
.collect();

python/types.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from . import _binaryninjacore as core
2929
from .enums import (
3030
InlineDuringAnalysis, StructureVariant, SymbolType, SymbolBinding, TypeClass, NamedTypeReferenceClass,
31-
ReferenceType, VariableSourceType,
31+
ReferenceType, VariableSourceType, ValueLocationSource,
3232
TypeReferenceType, MemberAccess, MemberScope, TypeDefinitionLineType,
3333
TokenEscapingType,
3434
NameType, PointerSuffix, PointerBaseType
@@ -624,16 +624,21 @@ def _to_core_struct(self) -> core.BNReturnValue:
624624
class FunctionParameter:
625625
type: SomeType
626626
name: str = ""
627+
location_source: ValueLocationSource = ValueLocationSource.DefaultLocationSource
627628
location: Optional['ValueLocation'] = None
628629

629-
def __init__(self, type: SomeType, name: str = "", location: OptionalLocation = None):
630+
def __init__(self, type: SomeType, name: str = "", location: OptionalLocation = None, source: Optional['ValueLocationSource'] = None):
630631
self.type = type
631632
self.name = name
632633
location = ValueLocationWithConfidence.from_optional_location(location)
633634
if location is not None:
634635
self.location = location.location
636+
self.location_source = ValueLocationSource.CustomLocationSource
635637
else:
636638
self.location = None
639+
self.location_source = ValueLocationSource.DefaultLocationSource
640+
if source is not None:
641+
self.location_source = source
637642

638643
def __repr__(self):
639644
ic = self.type.immutable_copy()
@@ -651,11 +656,12 @@ def mutable_copy(self) -> 'FunctionParameter':
651656
def _from_core_struct(struct: 'core.BNFunctionParameter', arch: Optional['architecture.Architecture'] = None) -> 'FunctionParameter':
652657
name = struct.name
653658
ty = Type.from_core_struct(struct.type).with_confidence(struct.typeConfidence)
654-
if struct.defaultLocation:
655-
location = None
656-
else:
659+
source = ValueLocationSource(struct.locationSource)
660+
if source == ValueLocationSource.CustomLocationSource:
657661
location = ValueLocation._from_core_struct(struct.location, arch)
658-
return FunctionParameter(ty, name, location)
662+
else:
663+
location = None
664+
return FunctionParameter(ty, name, location, source)
659665

660666

661667
@dataclass(frozen=True)
@@ -1514,10 +1520,11 @@ def parameters(self) -> List[FunctionParameter]:
15141520
param_type = Type.create(
15151521
core.BNNewTypeReference(params[i].type), platform=self.platform, confidence=params[i].typeConfidence
15161522
)
1517-
if params[i].defaultLocation:
1518-
param_location = None
1519-
else:
1523+
source = ValueLocationSource(params[i].locationSource)
1524+
if source == ValueLocationSource.CustomLocationSource:
15201525
param_location = ValueLocation._from_core_struct(params[i].location, arch)
1526+
else:
1527+
param_location = None
15211528
result.append(FunctionParameter(param_type, params[i].name, param_location))
15221529
core.BNFreeTypeParameterList(params, count.value)
15231530
return result
@@ -1546,7 +1553,7 @@ def _to_core_struct(params: Optional[ParamsType] = None):
15461553
core_param.name = ""
15471554
core_param.type = param.handle
15481555
core_param.typeConfidence = param.confidence
1549-
core_param.defaultLocation = True
1556+
core_param.locationSource = int(ValueLocationSource.DefaultLocationSource)
15501557
core_param.location.count = 0
15511558
elif isinstance(param, FunctionParameter):
15521559
assert param.type is not None, "Attempting to construct function parameter without properly constructed type"
@@ -1555,11 +1562,10 @@ def _to_core_struct(params: Optional[ParamsType] = None):
15551562
core_param.name = param.name
15561563
core_param.type = param_type.handle
15571564
core_param.typeConfidence = param_type.confidence
1565+
core_param.locationSource = int(param.location_source)
15581566
if param.location is None:
1559-
core_param.defaultLocation = True
15601567
core_param.location.count = 0
15611568
else:
1562-
core_param.defaultLocation = False
15631569
if isinstance(param.location, ValueLocation):
15641570
core_param.location = param.location._to_core_struct()
15651571
elif isinstance(param.location, variable.CoreVariable):
@@ -1575,7 +1581,7 @@ def _to_core_struct(params: Optional[ParamsType] = None):
15751581
core_param.name = name
15761582
core_param.type = _type.handle
15771583
core_param.typeConfidence = _type.confidence
1578-
core_param.defaultLocation = True
1584+
core_param.locationSource = int(ValueLocationSource.DefaultLocationSource)
15791585
core_param.location.count = 0
15801586
else:
15811587
raise ValueError(f"Conversion from unsupported function parameter type {type(param)}")
@@ -3472,11 +3478,12 @@ def parameters(self) -> List[FunctionParameter]:
34723478
param_type = Type.create(
34733479
core.BNNewTypeReference(params[i].type), platform=self._platform, confidence=params[i].typeConfidence
34743480
)
3475-
if params[i].defaultLocation:
3476-
param_location = None
3477-
else:
3481+
source = ValueLocationSource(params[i].locationSource)
3482+
if source == ValueLocationSource.CustomLocationSource:
34783483
param_location = ValueLocation._from_core_struct(params[i].location, arch)
3479-
result.append(FunctionParameter(param_type, params[i].name, param_location))
3484+
else:
3485+
param_location = None
3486+
result.append(FunctionParameter(param_type, params[i].name, param_location, source))
34803487
core.BNFreeTypeParameterList(params, count.value)
34813488
return result
34823489

0 commit comments

Comments
 (0)