Skip to content

Commit 5a8251a

Browse files
committed
Parameter location display and parsing
1 parent fb16145 commit 5a8251a

File tree

8 files changed

+108
-7
lines changed

8 files changed

+108
-7
lines changed

binaryninjaapi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10222,6 +10222,8 @@ namespace BinaryNinja {
1022210222

1022310223
static ValueLocationComponent FromAPIObject(const BNValueLocationComponent* loc);
1022410224
BNValueLocationComponent ToAPIObject() const;
10225+
10226+
std::string ToString(Architecture* arch) const;
1022510227
};
1022610228

1022710229
struct ValueLocation
@@ -10251,6 +10253,9 @@ namespace BinaryNinja {
1025110253
static ValueLocation FromAPIObject(const BNValueLocation* loc);
1025210254
BNValueLocation ToAPIObject() const;
1025310255
static void FreeAPIObject(BNValueLocation* loc);
10256+
10257+
static std::optional<ValueLocation> Parse(const std::string& str, Architecture* arch, std::string& error);
10258+
std::string ToString(Architecture* arch) const;
1025410259
};
1025510260

1025610261
struct FunctionParameter

binaryninjacore.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ extern "C"
478478
BaseStructureNameToken = 37,
479479
BaseStructureSeparatorToken = 38,
480480
BraceToken = 39,
481+
ValueLocationToken = 40,
481482
// The following are output by the analysis system automatically, these should
482483
// not be used directly by the architecture plugins
483484
CodeSymbolToken = 64,
@@ -7035,6 +7036,10 @@ extern "C"
70357036
BINARYNINJACOREAPI BNReturnValue BNGetTypeReturnValue(BNType* type);
70367037
BINARYNINJACOREAPI bool BNIsTypeReturnValueDefaultLocation(BNType* type);
70377038
BINARYNINJACOREAPI BNValueLocationWithConfidence BNGetTypeReturnValueLocation(BNType* type);
7039+
BINARYNINJACOREAPI bool BNParseValueLocation(
7040+
const char* str, BNArchitecture* arch, BNValueLocation* location, char** error);
7041+
BINARYNINJACOREAPI char* BNValueLocationToString(BNValueLocation* location, BNArchitecture* arch);
7042+
BINARYNINJACOREAPI char* BNValueLocationComponentToString(BNValueLocationComponent* component, BNArchitecture* arch);
70387043
BINARYNINJACOREAPI void BNFreeValueLocation(BNValueLocation* location);
70397044
BINARYNINJACOREAPI BNCallingConventionWithConfidence BNGetTypeCallingConvention(BNType* type);
70407045
BINARYNINJACOREAPI BNCallingConventionName BNGetTypeCallingConventionName(BNType* type);

lang/rust/rusttypes.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ vector<InstructionTextToken> RustTypePrinter::GetTypeTokensAfterNameInternal(
177177

178178
if (!params[i].defaultLocation && platform && var.has_value())
179179
{
180-
// TODO: Emit a syntax for parameters spanning multiple storage locations
181180
switch (var->type)
182181
{
183182
case RegisterVariableSourceType:
@@ -202,10 +201,14 @@ vector<InstructionTextToken> RustTypePrinter::GetTypeTokensAfterNameInternal(
202201
tokens.emplace_back(IntegerToken, storageStr, var->storage);
203202
break;
204203
}
205-
case CompositeReturnValueSourceType:
206-
case CompositeParameterSourceType:
204+
default:
205+
{
206+
string locationStr = params[i].location.ToString(platform->GetArchitecture());
207+
tokens.emplace_back(TextToken, " @ ");
208+
tokens.emplace_back(ValueLocationToken, locationStr);
207209
break;
208210
}
211+
}
209212
}
210213
}
211214

@@ -235,6 +238,13 @@ vector<InstructionTextToken> RustTypePrinter::GetTypeTokensAfterNameInternal(
235238
i.context = FunctionReturnTokenContext;
236239
}
237240
tokens.insert(tokens.end(), retn.begin(), retn.end());
241+
if (!type->GetReturnValue().defaultLocation)
242+
{
243+
auto location = type->GetReturnValue().location;
244+
string locationStr = location->ToString(platform->GetArchitecture());
245+
tokens.emplace_back(TextToken, " @ ");
246+
tokens.emplace_back(location.GetCombinedConfidence(baseConfidence), ValueLocationToken, locationStr);
247+
}
238248
}
239249
break;
240250
}

python/examples/pseudo_python.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,23 +1136,33 @@ def function_type_tokens(self, func: Function, settings: DisassemblySettings) ->
11361136
tokens.append(InstructionTextToken(InstructionTextTokenType.KeywordToken, "def "))
11371137
tokens.append(InstructionTextToken(InstructionTextTokenType.CodeSymbolToken, func.name, value=func.start))
11381138
tokens.append(InstructionTextToken(InstructionTextTokenType.BraceToken, "("))
1139+
params = func.type.parameters
11391140
for (i, param) in enumerate(func.type.parameters_with_all_locations):
11401141
if i > 0:
11411142
tokens.append(InstructionTextToken(InstructionTextTokenType.TextToken, ", "))
1143+
var = param.location.variable_for_parameter(i)
11421144
tokens.append(InstructionTextToken(InstructionTextTokenType.ArgumentNameToken, param.name,
11431145
context=InstructionTextTokenContext.LocalVariableTokenContext,
1144-
address=param.location.identifier))
1146+
address=var.identifier))
11451147
tokens.append(InstructionTextToken(InstructionTextTokenType.TextToken, ": "))
11461148
for token in param.type.get_tokens():
11471149
token.context = InstructionTextTokenContext.LocalVariableTokenContext
1148-
token.address = param.location.identifier
1150+
token.address = var.identifier
11491151
tokens.append(token)
1152+
if i < len(params) and params[i].location is not None:
1153+
tokens.append(InstructionTextToken(InstructionTextTokenType.TextToken, " @ "))
1154+
tokens.append(InstructionTextToken(InstructionTextTokenType.ValueLocationToken,
1155+
params[i].location.to_string(func.arch)))
11501156
tokens.append(InstructionTextToken(InstructionTextTokenType.BraceToken, ")"))
11511157
if func.can_return.value and func.type.return_value is not None and not isinstance(func.type.return_value, VoidType):
11521158
tokens.append(InstructionTextToken(InstructionTextTokenType.TextToken, " -> "))
11531159
for token in func.type.return_value.get_tokens():
11541160
token.context = InstructionTextTokenContext.FunctionReturnTokenContext
11551161
tokens.append(token)
1162+
if func.type.return_value_location is not None:
1163+
tokens.append(InstructionTextToken(InstructionTextTokenType.TextToken, " @ "))
1164+
tokens.append(InstructionTextToken(InstructionTextTokenType.ValueLocationToken,
1165+
func.type.return_value_location.location.to_string(func.arch)))
11561166
tokens.append(InstructionTextToken(InstructionTextTokenType.TextToken, ":"))
11571167
return [DisassemblyTextLine(tokens, func.start)]
11581168

python/types.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,10 @@ def _to_core_struct(self) -> core.BNValueLocationComponent:
471471
struct.returnedPointer = self.returned_pointer.to_BNVariable()
472472
return struct
473473

474+
def to_string(self, arch: 'architecture.Architecture'):
475+
struct = self._to_core_struct()
476+
return core.BNValueLocationComponentToString(struct, arch.handle)
477+
474478

475479
@dataclass
476480
class ValueLocation:
@@ -495,6 +499,30 @@ def _to_core_struct(self) -> core.BNValueLocation:
495499
def with_confidence(self, confidence: int) -> 'ValueLocationWithConfidence':
496500
return ValueLocationWithConfidence(self, confidence)
497501

502+
def variable_for_parameter(self, idx: int) -> Optional['variable.CoreVariable']:
503+
struct = self._to_core_struct()
504+
var = core.BNVariable()
505+
if core.BNGetValueLocationVariableForParameter(struct, var, idx):
506+
return variable.CoreVariable.from_BNVariable(var)
507+
return None
508+
509+
@staticmethod
510+
def parse(string: str, arch: 'architecture.Architecture') -> 'ValueLocation':
511+
struct = core.BNValueLocation()
512+
error = ctypes.c_char_p()
513+
if not core.BNParseValueLocation(string, arch.handle, struct, error):
514+
assert error.value is not None, "core.BNParseValueLocation returned 'error' set to None"
515+
error_str = error.value.decode("utf-8")
516+
core.free_string(error)
517+
raise SyntaxError(error_str)
518+
result = ValueLocation._from_core_struct(struct)
519+
core.BNFreeValueLocation(struct)
520+
return result
521+
522+
def to_string(self, arch: 'architecture.Architecture'):
523+
struct = self._to_core_struct()
524+
return core.BNValueLocationToString(struct, arch.handle)
525+
498526

499527
@dataclass
500528
class ValueLocationWithConfidence:

rust/src/disassembly.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ pub enum InstructionTextTokenKind {
506506
// TODO: Explain what this is
507507
hash: Option<u64>,
508508
},
509+
ValueLocation,
509510
CodeSymbol {
510511
// Target address of the symbol
511512
value: u64,
@@ -700,6 +701,7 @@ impl InstructionTextTokenKind {
700701
hash => Some(hash),
701702
},
702703
},
704+
BNInstructionTextTokenType::ValueLocationToken => Self::ValueLocation,
703705
BNInstructionTextTokenType::CodeSymbolToken => Self::CodeSymbol {
704706
value: value.value,
705707
size: value.size,
@@ -914,6 +916,9 @@ impl From<InstructionTextTokenKind> for BNInstructionTextTokenType {
914916
BNInstructionTextTokenType::BaseStructureSeparatorToken
915917
}
916918
InstructionTextTokenKind::Brace { .. } => BNInstructionTextTokenType::BraceToken,
919+
InstructionTextTokenKind::ValueLocation => {
920+
BNInstructionTextTokenType::ValueLocationToken
921+
}
917922
InstructionTextTokenKind::CodeSymbol { .. } => {
918923
BNInstructionTextTokenType::CodeSymbolToken
919924
}

rust/src/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ impl ValueLocation {
11801180
}
11811181
}
11821182

1183-
pub(crate) fn into_rust_raw(value: &Self) -> BNValueLocation {
1183+
pub fn into_rust_raw(value: &Self) -> BNValueLocation {
11841184
let components: Box<[BNValueLocationComponent]> = value
11851185
.components
11861186
.iter()
@@ -1193,7 +1193,7 @@ impl ValueLocation {
11931193
}
11941194

11951195
/// Free a RUST ALLOCATED possible value set. Do not use this with CORE ALLOCATED values.
1196-
pub(crate) fn free_rust_raw(value: BNValueLocation) {
1196+
pub fn free_rust_raw(value: BNValueLocation) {
11971197
let raw_components =
11981198
unsafe { std::slice::from_raw_parts_mut(value.components, value.count) };
11991199
let _ = unsafe { Box::from_raw(raw_components) };

type.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,16 @@ BNValueLocationComponent ValueLocationComponent::ToAPIObject() const
591591
}
592592

593593

594+
std::string ValueLocationComponent::ToString(Architecture* arch) const
595+
{
596+
auto componentRaw = ToAPIObject();
597+
char* str = BNValueLocationComponentToString(&componentRaw, arch->GetObject());
598+
string result = str;
599+
BNFreeString(str);
600+
return result;
601+
}
602+
603+
594604
std::optional<Variable> ValueLocation::GetVariableForReturnValue() const
595605
{
596606
BNValueLocation loc = ToAPIObject();
@@ -680,6 +690,34 @@ void ValueLocation::FreeAPIObject(BNValueLocation* loc)
680690
}
681691

682692

693+
std::optional<ValueLocation> ValueLocation::Parse(const std::string& str, Architecture* arch, std::string& error)
694+
{
695+
BNValueLocation locationRaw;
696+
char* errorRaw;
697+
if (BNParseValueLocation(str.c_str(), arch->GetObject(), &locationRaw, &errorRaw))
698+
{
699+
auto location = FromAPIObject(&locationRaw);
700+
BNFreeValueLocation(&locationRaw);
701+
return location;
702+
}
703+
704+
error = errorRaw;
705+
BNFreeString(errorRaw);
706+
return std::nullopt;
707+
}
708+
709+
710+
std::string ValueLocation::ToString(Architecture* arch) const
711+
{
712+
auto locationRaw = ToAPIObject();
713+
char* str = BNValueLocationToString(&locationRaw, arch->GetObject());
714+
FreeAPIObject(&locationRaw);
715+
string result = str;
716+
BNFreeString(str);
717+
return result;
718+
}
719+
720+
683721
bool ReturnValue::operator==(const ReturnValue& nt) const
684722
{
685723
if (type != nt.type)

0 commit comments

Comments
 (0)