@@ -112,6 +112,9 @@ struct RuntimeCall
112112 Autorelease,
113113 RetainAutorelease,
114114 Class,
115+ Self,
116+ RespondsToSelector,
117+ IsKindOfClass
115118 };
116119
117120 Type type;
@@ -129,6 +132,9 @@ constexpr std::array RUNTIME_CALLS = {
129132 std::make_pair (" _objc_msgSendSuper2" , RuntimeCall::MessageSendSuper),
130133 std::make_pair (" _objc_opt_class" , RuntimeCall::Class),
131134 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),
132138 std::make_pair (" _objc_release" , RuntimeCall::Release),
133139 std::make_pair (" _objc_retain" , RuntimeCall::Retain),
134140 std::make_pair (" _objc_retainAutoreleasedReturnValue" , RuntimeCall::Retain),
@@ -143,6 +149,9 @@ constexpr std::array RUNTIME_CALLS = {
143149 std::make_pair (" j__objc_msgSendSuper2" , RuntimeCall::MessageSendSuper),
144150 std::make_pair (" j__objc_opt_class" , RuntimeCall::Class),
145151 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),
146155 std::make_pair (" j__objc_release" , RuntimeCall::Release),
147156 std::make_pair (" j__objc_retain" , RuntimeCall::Retain),
148157 std::make_pair (" j__objc_retainAutoreleasedReturnValue" , RuntimeCall::Retain),
@@ -244,7 +253,20 @@ void PseudoObjCFunction::GetExpr_CALL_OR_TAILCALL(const BinaryNinja::HighLevelIL
244253 case RuntimeCall::Class:
245254 runtimeCallTokens = {" class" };
246255 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+ }
248270 break ;
249271 }
250272
@@ -332,6 +354,24 @@ bool PseudoObjCFunction::GetExpr_GenericObjCRuntimeCall(uint64_t address, const
332354 return true ;
333355}
334356
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+
335375void PseudoObjCFunction::GetExpr_CONST_PTR (const BinaryNinja::HighLevelILInstruction& instr,
336376 BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings,
337377 BNOperatorPrecedence precedence, bool statement)
0 commit comments