@@ -26,55 +26,6 @@ static std::mutex g_initialAnalysisMutex;
2626using SectionRef = BinaryNinja::Ref<BinaryNinja::Section>;
2727using SymbolRef = BinaryNinja::Ref<BinaryNinja::Symbol>;
2828
29- std::set<uint64_t > Workflow::findMsgSendFunctions (BinaryViewRef bv)
30- {
31- std::set<uint64_t > results;
32-
33- const auto authStubsSection = bv->GetSectionByName (" __auth_stubs" );
34- const auto stubsSection = bv->GetSectionByName (" __stubs" );
35- const auto authGotSection = bv->GetSectionByName (" __auth_got" );
36- const auto gotSection = bv->GetSectionByName (" __got" );
37- const auto laSymbolPtrSection = bv->GetSectionByName (" __la_symbol_ptr" );
38-
39- // Shorthand to check if a symbol lies in a given section.
40- auto sectionContains = [](SectionRef section, SymbolRef symbol) {
41- const auto start = section->GetStart ();
42- const auto length = section->GetLength ();
43- const auto address = symbol->GetAddress ();
44-
45- return (uint64_t )(address - start) <= length;
46- };
47-
48- // There can be multiple `_objc_msgSend` symbols in the same binary; there
49- // may even be lots. Some of them are valid, others aren't. In order of
50- // preference, `_objc_msgSend` symbols in the following sections are
51- // preferred:
52- //
53- // 1. __auth_stubs
54- // 2. __stubs
55- // 3. __auth_got
56- // 4. __got
57- // ?. __la_symbol_ptr
58- //
59- // There is often an `_objc_msgSend` symbol that is a stub function, found
60- // in the `__stubs` section, which will come with an imported symbol of the
61- // same name in the `__got` section. Not all `__objc_msgSend` calls will be
62- // routed through the stub function, making it important to make note of
63- // both symbols' addresses. Furthermore, on ARM64, the `__auth{stubs,got}`
64- // sections are preferred over their unauthenticated counterparts.
65- const auto candidates = bv->GetSymbolsByName (" _objc_msgSend" );
66- for (const auto & c : candidates) {
67- if ((authStubsSection && sectionContains (authStubsSection, c))
68- || (stubsSection && sectionContains (stubsSection, c))
69- || (authGotSection && sectionContains (authGotSection, c))
70- || (gotSection && sectionContains (gotSection, c))
71- || (laSymbolPtrSection && sectionContains (laSymbolPtrSection, c)))
72- results.insert (c->GetAddress ());
73- }
74-
75- return results;
76- }
77-
7829void Workflow::rewriteMethodCall (LLILFunctionRef ssa, size_t insnIndex)
7930{
8031 const auto bv = ssa->GetFunction ()->GetView ();
@@ -187,6 +138,7 @@ void Workflow::inlineMethodCalls(AnalysisContextRef ac)
187138 CustomTypes::defineAll (bv);
188139 CFStringArchitectureHook* currentHook = new CFStringArchitectureHook (bv->GetDefaultArchitecture ());
189140 bv->GetDefaultArchitecture ()->Register (currentHook);
141+ auto messageHandler = GlobalState::messageHandler (bv);
190142
191143 try {
192144 auto file = std::make_shared<ObjectiveNinja::BinaryViewFile>(bv);
@@ -200,7 +152,7 @@ void Workflow::inlineMethodCalls(AnalysisContextRef ac)
200152
201153 InfoHandler::applyInfoToView (info, bv);
202154
203- const auto msgSendFunctions = findMsgSendFunctions (bv );
155+ const auto msgSendFunctions = messageHandler-> getMessageSendFunctions ( );
204156 for (auto addr : msgSendFunctions)
205157 {
206158 BinaryNinja::QualifiedNameAndType nameAndType;
@@ -237,12 +189,8 @@ void Workflow::inlineMethodCalls(AnalysisContextRef ac)
237189 }
238190 }
239191
240- // Try to find the `objc_msgSend` functions(s), abort activity if missing.
241- //
242- // TODO: These results should be cached somehow as it can't be efficient to
243- // repeatedly search for all the usable function addresses.
244- const auto msgSendFunctions = findMsgSendFunctions (bv);
245- if (msgSendFunctions.empty ()) {
192+ auto messageHandler = GlobalState::messageHandler (bv);
193+ if (!messageHandler->hasMessageSendFunctions ()) {
246194 log->LogError (" Cannot perform Objective-C IL cleanup; no objc_msgSend candidates found" );
247195 GlobalState::addIgnoredView (bv);
248196 return ;
@@ -259,14 +207,14 @@ void Workflow::inlineMethodCalls(AnalysisContextRef ac)
259207 return ;
260208 }
261209
262- const auto rewriteIfEligible = [bv, msgSendFunctions , ssa](size_t insnIndex) {
210+ const auto rewriteIfEligible = [bv, messageHandler , ssa](size_t insnIndex) {
263211 auto insn = ssa->GetInstruction (insnIndex);
264212
265213 if (insn.operation == LLIL_CALL_SSA)
266214 {
267215 // Filter out calls that aren't to `objc_msgSend`.
268216 auto callExpr = insn.GetDestExpr <LLIL_CALL_SSA>();
269- if (!msgSendFunctions. count (callExpr.GetValue ().value ))
217+ if (!messageHandler-> isMessageSend (callExpr.GetValue ().value ))
270218 return ;
271219
272220 // By convention, the selector is the second argument to `objc_msgSend`,
@@ -279,6 +227,7 @@ void Workflow::inlineMethodCalls(AnalysisContextRef ac)
279227 return ;
280228
281229 rewriteMethodCall (ssa, insnIndex);
230+
282231 }
283232 else if (insn.operation == LLIL_SET_REG_SSA)
284233 {
0 commit comments