@@ -187,6 +187,46 @@ std::optional<RuntimeCall> DetectRewrittenDirectObjCMethodCall(const HighLevelIL
187
187
return RuntimeCall {RuntimeCall::MessageSend, constant, true };
188
188
}
189
189
190
+ bool VariableIsObjCSuperStruct (const Variable& variable, Function& function)
191
+ {
192
+ auto variableName = function.GetVariableName (variable);
193
+ if (variableName != " super" )
194
+ return false ;
195
+
196
+ const auto variableType = function.GetVariableType (variable);
197
+ if (!variableType || !variableType->IsNamedTypeRefer ())
198
+ return false ;
199
+
200
+ const auto namedType = function.GetView ()->GetTypeByRef (variableType->GetNamedTypeReference ());
201
+ if (!namedType || namedType->GetClass () != StructureTypeClass)
202
+ return false ;
203
+
204
+ if (namedType->GetStructureName ().GetString () != " objc_super" )
205
+ return false ;
206
+
207
+ return true ;
208
+ }
209
+
210
+ bool IsAssignmentToObjCSuperStructField (const HighLevelILInstruction& assignInstr, Function& function)
211
+ {
212
+ // Check if this is an assignment to a field of the objc_super struct
213
+ // Pattern: HLIL_ASSIGN { dest = HLIL_STRUCT_FIELD { source = HLIL_VAR { super }, }, field = ... }
214
+
215
+ if (assignInstr.operation != HLIL_ASSIGN)
216
+ return false ;
217
+
218
+ const auto destExpr = assignInstr.GetDestExpr ();
219
+ if (destExpr.operation != HLIL_STRUCT_FIELD)
220
+ return false ;
221
+
222
+ const auto sourceExpr = destExpr.GetSourceExpr ();
223
+ if (sourceExpr.operation != HLIL_VAR)
224
+ return false ;
225
+
226
+ auto variable = sourceExpr.GetVariable <HLIL_VAR>();
227
+ return VariableIsObjCSuperStruct (variable, function);
228
+ }
229
+
190
230
} // unnamed namespace
191
231
192
232
PseudoObjCFunction::PseudoObjCFunction (LanguageRepresentationFunctionType* type, Architecture* arch, Function* owner,
@@ -212,7 +252,8 @@ void PseudoObjCFunction::GetExpr_CALL_OR_TAILCALL(const BinaryNinja::HighLevelIL
212
252
{
213
253
case RuntimeCall::MessageSend:
214
254
case RuntimeCall::MessageSendSuper:
215
- if (GetExpr_ObjCMsgSend (objCRuntimeCall->address , objCRuntimeCall->isRewritten , destExpr, tokens, settings, parameterExprs))
255
+ if (GetExpr_ObjCMsgSend (objCRuntimeCall->address , objCRuntimeCall->type == RuntimeCall::MessageSendSuper,
256
+ objCRuntimeCall->isRewritten , destExpr, tokens, settings, parameterExprs))
216
257
{
217
258
if (statement)
218
259
tokens.AppendSemicolon ();
@@ -259,7 +300,7 @@ void PseudoObjCFunction::GetExpr_CALL_OR_TAILCALL(const BinaryNinja::HighLevelIL
259
300
return PseudoCFunction::GetExpr_CALL_OR_TAILCALL (instr, tokens, settings, precedence, statement);
260
301
}
261
302
262
- bool PseudoObjCFunction::GetExpr_ObjCMsgSend (uint64_t msgSendAddress, bool isRewritten,
303
+ bool PseudoObjCFunction::GetExpr_ObjCMsgSend (uint64_t msgSendAddress, bool isSuper, bool isRewritten,
263
304
const HighLevelILInstruction& instr, HighLevelILTokenEmitter& tokens, DisassemblySettings* settings,
264
305
const std::vector<HighLevelILInstruction>& parameterExprs)
265
306
{
@@ -278,7 +319,10 @@ bool PseudoObjCFunction::GetExpr_ObjCMsgSend(uint64_t msgSendAddress, bool isRew
278
319
279
320
tokens.AppendOpenBracket ();
280
321
281
- GetExprText (parameterExprs[0 ], tokens, settings);
322
+ if (isSuper)
323
+ tokens.Append (LocalVariableToken, " super" , instr.address );
324
+ else
325
+ GetExprText (parameterExprs[0 ], tokens, settings);
282
326
283
327
for (size_t index = 2 ; index < parameterExprs.size (); index++)
284
328
{
@@ -427,7 +471,7 @@ void PseudoObjCFunction::GetExpr_IMPORT(const BinaryNinja::HighLevelILInstructio
427
471
BNOperatorPrecedence precedence, bool statement)
428
472
{
429
473
const auto constant = instr.GetConstant <HLIL_IMPORT>();
430
- auto symbol = GetHighLevelILFunction ()-> GetFunction ()->GetView ()->GetSymbolByAddress (constant);
474
+ auto symbol = GetFunction ()->GetView ()->GetSymbolByAddress (constant);
431
475
const auto symbolType = symbol->GetType ();
432
476
433
477
if (symbol && (symbolType == ImportedDataSymbol || symbolType == ImportAddressSymbol))
@@ -449,6 +493,28 @@ void PseudoObjCFunction::GetExpr_IMPORT(const BinaryNinja::HighLevelILInstructio
449
493
PseudoCFunction::GetExpr_IMPORT (instr, tokens, settings, precedence, statement);
450
494
}
451
495
496
+ bool PseudoObjCFunction::ShouldSkipStatement (const BinaryNinja::HighLevelILInstruction& instr)
497
+ {
498
+ // Skip statements that are compiler-generated artifacts of Objective-C runtime calls
499
+ // For now this is limited to the declaration / initialization of the `objc_super` variable
500
+ // used for `objc_msgSendSuper` calls.
501
+ switch (instr.operation )
502
+ {
503
+ case HLIL_VAR_DECLARE:
504
+ if (VariableIsObjCSuperStruct (instr.GetVariable <HLIL_VAR_DECLARE>(), *GetFunction ()))
505
+ return true ;
506
+ break ;
507
+ case HLIL_ASSIGN:
508
+ if (IsAssignmentToObjCSuperStructField (instr, *GetFunction ()))
509
+ return true ;
510
+ break ;
511
+ default :
512
+ break ;
513
+ }
514
+
515
+ return PseudoCFunction::ShouldSkipStatement (instr);
516
+ }
517
+
452
518
453
519
PseudoObjCFunctionType::PseudoObjCFunctionType () : PseudoCFunctionType(" Pseudo Objective-C" ) {}
454
520
0 commit comments