@@ -112,6 +112,9 @@ struct RuntimeCall
112
112
Autorelease,
113
113
RetainAutorelease,
114
114
Class,
115
+ Self,
116
+ RespondsToSelector,
117
+ IsKindOfClass
115
118
};
116
119
117
120
Type type;
@@ -129,6 +132,9 @@ constexpr std::array RUNTIME_CALLS = {
129
132
std::make_pair (" _objc_msgSendSuper2" , RuntimeCall::MessageSendSuper),
130
133
std::make_pair (" _objc_opt_class" , RuntimeCall::Class),
131
134
std::make_pair (" _objc_opt_new" , RuntimeCall::New),
135
+ std::make_pair (" _objc_opt_self" , RuntimeCall::Self),
136
+ std::make_pair (" _objc_opt_respondsToSelector" , RuntimeCall::RespondsToSelector),
137
+ std::make_pair (" _objc_opt_isKindOfClass" , RuntimeCall::IsKindOfClass),
132
138
std::make_pair (" _objc_release" , RuntimeCall::Release),
133
139
std::make_pair (" _objc_retain" , RuntimeCall::Retain),
134
140
std::make_pair (" _objc_retainAutoreleasedReturnValue" , RuntimeCall::Retain),
@@ -143,6 +149,9 @@ constexpr std::array RUNTIME_CALLS = {
143
149
std::make_pair (" j__objc_msgSendSuper2" , RuntimeCall::MessageSendSuper),
144
150
std::make_pair (" j__objc_opt_class" , RuntimeCall::Class),
145
151
std::make_pair (" j__objc_opt_new" , RuntimeCall::New),
152
+ std::make_pair (" j__objc_opt_self" , RuntimeCall::Self),
153
+ std::make_pair (" j__objc_opt_respondsToSelector" , RuntimeCall::RespondsToSelector),
154
+ std::make_pair (" j__objc_opt_isKindOfClass" , RuntimeCall::IsKindOfClass),
146
155
std::make_pair (" j__objc_release" , RuntimeCall::Release),
147
156
std::make_pair (" j__objc_retain" , RuntimeCall::Retain),
148
157
std::make_pair (" j__objc_retainAutoreleasedReturnValue" , RuntimeCall::Retain),
@@ -244,7 +253,20 @@ void PseudoObjCFunction::GetExpr_CALL_OR_TAILCALL(const BinaryNinja::HighLevelIL
244
253
case RuntimeCall::Class:
245
254
runtimeCallTokens = {" class" };
246
255
break ;
247
- default :
256
+ case RuntimeCall::Self:
257
+ runtimeCallTokens = {" self" };
258
+ break ;
259
+ case RuntimeCall::RespondsToSelector:
260
+ case RuntimeCall::IsKindOfClass:
261
+ std::string_view selectorToken =
262
+ objCRuntimeCall->type == RuntimeCall::RespondsToSelector ? " respondsToSelector:" : " isKindOfClass:" ;
263
+ if (GetExpr_TwoParamObjCRuntimeCall (
264
+ objCRuntimeCall->address , instr, tokens, settings, parameterExprs, selectorToken))
265
+ {
266
+ if (statement)
267
+ tokens.AppendSemicolon ();
268
+ return ;
269
+ }
248
270
break ;
249
271
}
250
272
@@ -332,6 +354,24 @@ bool PseudoObjCFunction::GetExpr_GenericObjCRuntimeCall(uint64_t address, const
332
354
return true ;
333
355
}
334
356
357
+ bool PseudoObjCFunction::GetExpr_TwoParamObjCRuntimeCall (uint64_t address, const HighLevelILInstruction& instr,
358
+ HighLevelILTokenEmitter& tokens, DisassemblySettings* settings,
359
+ const std::vector<HighLevelILInstruction>& parameterExprs, std::string_view selectorToken)
360
+ {
361
+ if (parameterExprs.size () < 2 )
362
+ return false ;
363
+
364
+ tokens.AppendOpenBracket ();
365
+
366
+ GetExprText (parameterExprs[0 ], tokens, settings);
367
+ tokens.Append (TextToken, " " );
368
+ tokens.Append (CodeSymbolToken, StringReferenceTokenContext, std::string (selectorToken), instr.address , address);
369
+ GetExprText (parameterExprs[1 ], tokens, settings, MemberAndFunctionOperatorPrecedence);
370
+ tokens.AppendCloseBracket ();
371
+
372
+ return true ;
373
+ }
374
+
335
375
void PseudoObjCFunction::GetExpr_CONST_PTR (const BinaryNinja::HighLevelILInstruction& instr,
336
376
BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings,
337
377
BNOperatorPrecedence precedence, bool statement)
0 commit comments