1313#include " mediumlevelilinstruction.h"
1414#include " ../api/sharedcacheapi.h"
1515#include " thread"
16+ #include < shared_mutex>
1617
18+ using namespace SharedCacheAPI ;
1719
1820struct GlobalWorkflowState
1921{
@@ -22,30 +24,34 @@ struct GlobalWorkflowState
2224 bool autoLoadObjCStubRequirements = true ;
2325};
2426
25- static std::unordered_map<uint64_t , GlobalWorkflowState* > globalWorkflowState;
26- std::mutex globalWorkflowStateMutex;
27+ static std::unordered_map<uint64_t , std::shared_ptr< GlobalWorkflowState> > globalWorkflowState;
28+ std::shared_mutex globalWorkflowStateMutex;
2729
28- GlobalWorkflowState* GetGlobalWorkflowState (Ref<BinaryView> view)
30+ std::shared_ptr< GlobalWorkflowState> GetGlobalWorkflowState (Ref<BinaryView> view)
2931{
30- std::unique_lock<std::mutex> lock (globalWorkflowStateMutex);
31- if (globalWorkflowState.find (view->GetFile ()->GetSessionId ()) == globalWorkflowState.end ())
32+ std::shared_lock<std::shared_mutex> readLock (globalWorkflowStateMutex);
33+ uint64_t viewId = view->GetFile ()->GetSessionId ();
34+ auto foundState = globalWorkflowState.find (viewId);
35+ if (foundState != globalWorkflowState.end ())
36+ return foundState->second ;
37+ readLock.unlock ();
38+
39+ std::unique_lock<std::shared_mutex> writeLock (globalWorkflowStateMutex);
40+ globalWorkflowState[viewId] = std::make_shared<GlobalWorkflowState>();
41+ Ref<Settings> settings = view->GetLoadSettings (VIEW_NAME);
42+ bool autoLoadStubsAndDyldData = true ;
43+ if (settings && settings->Contains (" loader.dsc.autoLoadStubsAndDyldData" ))
3244 {
33- globalWorkflowState[view->GetFile ()->GetSessionId ()] = new GlobalWorkflowState ();
34- Ref<Settings> settings = view->GetLoadSettings (VIEW_NAME);
35- bool autoLoadStubsAndDyldData = true ;
36- if (settings && settings->Contains (" loader.dsc.autoLoadStubsAndDyldData" ))
37- {
38- autoLoadStubsAndDyldData = settings->Get <bool >(" loader.dsc.autoLoadStubsAndDyldData" , view);
39- }
40- globalWorkflowState[view->GetFile ()->GetSessionId ()]->autoLoadStubsAndDyldData = autoLoadStubsAndDyldData;
41- bool autoLoadObjC = true ;
42- if (settings && settings->Contains (" loader.dsc.autoLoadObjCStubRequirements" ))
43- {
44- autoLoadObjC = settings->Get <bool >(" loader.dsc.autoLoadObjCStubRequirements" , view);
45- }
46- globalWorkflowState[view->GetFile ()->GetSessionId ()]->autoLoadObjCStubRequirements = autoLoadObjC;
45+ autoLoadStubsAndDyldData = settings->Get <bool >(" loader.dsc.autoLoadStubsAndDyldData" , view);
4746 }
48- return globalWorkflowState[view->GetFile ()->GetSessionId ()];
47+ globalWorkflowState[viewId]->autoLoadStubsAndDyldData = autoLoadStubsAndDyldData;
48+ bool autoLoadObjC = true ;
49+ if (settings && settings->Contains (" loader.dsc.autoLoadObjCStubRequirements" ))
50+ {
51+ autoLoadObjC = settings->Get <bool >(" loader.dsc.autoLoadObjCStubRequirements" , view);
52+ }
53+ globalWorkflowState[viewId]->autoLoadObjCStubRequirements = autoLoadObjC;
54+ return globalWorkflowState[viewId];
4955}
5056
5157
@@ -76,15 +82,44 @@ std::vector<std::string> generateArgumentNames(const std::vector<std::string>& c
7682}
7783
7884
79- void SharedCacheWorkflow::ProcessOffImageCall (Ref<AnalysisContext> ctx, Ref<Function> func, Ref<MediumLevelILFunction> mssa, const MediumLevelILInstruction dest, ExprId exprIndex, bool applySymbolIfFoundToCurrentFunction)
85+ void ProcessStubImageCall (const std::shared_ptr<GlobalWorkflowState> &workflowState, Ref<SharedCache> cache, Ref<Function> func,
86+ const Ref<Section>& section, uint64_t target)
8087{
81- auto bv = func->GetView ();
82- WorkerPriorityEnqueue ([bv=bv, dest=dest, func=func, applySymbolIfFoundToCurrentFunction]()
88+ if (!workflowState->imageLoadMutex .try_lock ())
89+ return ;
90+
91+ auto view = func->GetView ();
92+ if (!view->IsValidOffset (target))
93+ {
94+ if (!cache->GetImageNameForAddress (target).empty ())
95+ cache->LoadImageContainingAddress (target);
96+ else
97+ cache->LoadSectionAtAddress (target);
98+
99+ // Check to see if there are any functions inside the newly added image.
100+ bool newFunctions = false ;
101+ for (const auto §Func : view->GetAnalysisFunctionList ())
83102 {
103+ if (section->GetStart () <= sectFunc->GetStart () && sectFunc->GetStart () < section->GetEnd ())
104+ newFunctions = true ;
105+ }
106+
107+ // If there are any new functions we should re-analyze the current function.
108+ if (newFunctions)
109+ func->Reanalyze ();
110+ }
111+
112+ workflowState->imageLoadMutex .unlock ();
113+ }
114+
115+
116+ void SharedCacheWorkflow::ProcessOffImageCall (Ref<AnalysisContext> ctx, Ref<SharedCache> cache, Ref<Function> func,
117+ Ref<MediumLevelILFunction> mssa, const MediumLevelILInstruction dest,
118+ bool applySymbolIfFoundToCurrentFunction)
119+ {
120+ auto bv = func->GetView ();
121+ WorkerPriorityEnqueue ([bv=std::move (bv), cache=std::move (cache), dest=dest, func=func, applySymbolIfFoundToCurrentFunction](){
84122 auto workflowState = GetGlobalWorkflowState (bv);
85- Ref<SharedCacheAPI::SharedCache> cache = new SharedCacheAPI::SharedCache (bv);
86- if (!cache)
87- return ;
88123 if (dest.operation != MLIL_CONST_PTR && dest.operation != MLIL_CONST)
89124 return ;
90125 if (workflowState->autoLoadStubsAndDyldData &&
@@ -122,34 +157,22 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
122157 auto workflowState = GetGlobalWorkflowState (bv);
123158
124159 auto funcStart = func->GetStart ();
125- auto sectionExists = !bv->GetSectionsAt (funcStart).empty ();
126- if (!sectionExists)
127- return ;
128- auto section = bv->GetSectionsAt (funcStart)[0 ];
129-
130- auto imageName = section->GetName ();
131- // remove everything after ::
132- auto pos = imageName.find (" ::" );
133- if (pos != std::string::npos)
134- imageName = imageName.substr (0 , pos);
135-
136- const auto llil = ctx->GetLowLevelILFunction ();
137- if (!llil) {
138- return ;
139- }
140- const auto ssa = llil->GetSSAForm ();
141- if (!ssa) {
160+ auto sections = bv->GetSectionsAt (funcStart);
161+ if (sections.empty ())
142162 return ;
143- }
163+ // Just get the first section
164+ const auto & section = sections.front ();
144165
145166 const auto mlil = ctx->GetMediumLevelILFunction ();
146- if (!mlil) {
167+ if (!mlil)
147168 return ;
148- }
149169 const auto mssa = mlil->GetSSAForm ();
150- if (!mssa) {
170+ if (!mssa)
171+ return ;
172+
173+ Ref<SharedCache> cache = new SharedCache (bv);
174+ if (cache->m_object == nullptr )
151175 return ;
152- }
153176
154177 // Processor that automatically loads the libObjC image when it encounters a stub (so we can do inlining).
155178 if (workflowState->autoLoadObjCStubRequirements && section->GetName ().find (" __objc_stubs" ) != std::string::npos)
@@ -170,99 +193,25 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
170193 for (size_t i = block->GetStart (), end = block->GetEnd (); i < end; ++i)
171194 {
172195 auto instr = mssa->GetInstruction (i);
173- // current_il_function.ssa_form.get_ssa_var_value(current_il_instruction.dest.var)
174196 if (instr.operation == MLIL_JUMP)
175197 {
176198 if (instr.GetDestExpr <MLIL_JUMP>().operation == MLIL_VAR_SSA)
177199 {
178200 auto dest = instr.GetDestExpr <MLIL_JUMP>();
179- // RegisterValue value = mssa->GetSSAVarValue(instr.GetDestExpr().GetSourceSSAVariable())
180- // ExprId def = mssa->GetSSAVarDefinition(instr.GetDestExpr().GetSourceSSAVariable());
181- // MLILInstruction defInstr = mssa->GetInstruction(mssa->GetSSAVarDefinition(instr.GetDestExpr().GetSourceSSAVariable()));
182- // targetOffset = mssa->GetInstruction(mssa->GetSSAVarDefinition(instr.GetDestExpr().GetSourceSSAVariable())).GetSourceExpr().GetSourceExpr().GetConstant();
183201 auto value = mssa->GetSSAVarValue (dest.GetSourceSSAVariable ());
184202 if (value.state == UndeterminedValue)
185203 {
186- bool otherFunctionAlreadyRunning;
187- {
188- otherFunctionAlreadyRunning = !workflowState->imageLoadMutex .try_lock ();
189- if (!otherFunctionAlreadyRunning)
190- workflowState->imageLoadMutex .unlock ();
191- }
192- if (otherFunctionAlreadyRunning)
193- {
194- return ;
195- }
196-
197- std::unique_lock<std::mutex> lock (workflowState->imageLoadMutex );
198204 auto def = mssa->GetSSAVarDefinition (dest.GetSourceSSAVariable ());
199205 auto defInstr = mssa->GetInstruction (def);
200206 auto targetOffset = defInstr.GetSourceExpr ().GetSourceExpr ().GetConstant ();
201-
202- if (bv->IsValidOffset (targetOffset))
203- return ;
204-
205- Ref<SharedCacheAPI::SharedCache> cache = new SharedCacheAPI::SharedCache (bv);
206-
207- if (!cache)
208- return ;
209- if (!cache->GetImageNameForAddress (targetOffset).empty ())
210- {
211- cache->LoadImageContainingAddress (targetOffset);
212- }
213- else
214- {
215- cache->LoadSectionAtAddress (targetOffset);
216- }
217- for (const auto §Func : bv->GetAnalysisFunctionList ())
218- {
219- if (section->GetStart () <= sectFunc->GetStart () && sectFunc->GetStart () < section->GetEnd ())
220- {
221- func->Reanalyze ();
222- }
223- }
207+ ProcessStubImageCall (workflowState, cache, func, section, targetOffset);
224208 }
225209 }
226-
227210 else if (instr.GetDestExpr <MLIL_JUMP>().operation == MLIL_CONST_PTR)
228211 {
229- bool otherFunctionAlreadyRunning;
230- {
231- otherFunctionAlreadyRunning = !workflowState->imageLoadMutex .try_lock ();
232- if (!otherFunctionAlreadyRunning)
233- workflowState->imageLoadMutex .unlock ();
234- }
235- if (otherFunctionAlreadyRunning)
236- {
237- return ;
238- }
239-
240- std::unique_lock<std::mutex> lock (workflowState->imageLoadMutex );
241212 auto dest = instr.GetDestExpr <MLIL_JUMP>();
242213 auto targetOffset = dest.GetConstant ();
243- if (bv->IsValidOffset (targetOffset))
244- return ;
245-
246- Ref<SharedCacheAPI::SharedCache> cache = new SharedCacheAPI::SharedCache (bv);
247-
248- if (!cache)
249- return ;
250-
251- if (!cache->GetImageNameForAddress (targetOffset).empty ())
252- {
253- cache->LoadImageContainingAddress (targetOffset);
254- }
255- else
256- {
257- cache->LoadSectionAtAddress (targetOffset);
258- }
259- for (const auto §Func : bv->GetAnalysisFunctionList ())
260- {
261- if (section->GetStart () <= sectFunc->GetStart () && sectFunc->GetStart () < section->GetEnd ())
262- {
263- func->Reanalyze ();
264- }
265- }
214+ ProcessStubImageCall (workflowState, cache, func, section, targetOffset);
266215 }
267216 }
268217 }
@@ -297,7 +246,7 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
297246 {
298247 if (!bv->IsValidOffset (dest.GetConstant ()))
299248 {
300- ProcessOffImageCall (ctx, func, mssa, dest, firstInstruction. GetSSAExprIndex () , true );
249+ ProcessOffImageCall (ctx, cache, func, mssa, dest, true );
301250 }
302251 }
303252
@@ -308,75 +257,32 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
308257 dest = dest.GetSourceExpr ();
309258 if (!bv->IsValidOffset (dest.GetConstant ()))
310259 {
311- ProcessOffImageCall (ctx, func, mssa, dest, firstInstruction. GetSSAExprIndex () );
260+ ProcessOffImageCall (ctx, cache, func, mssa, dest);
312261 }
313262 }
314263 }
315264 }
316-
317265 else
318266 {
319267 for (const auto & block : mssa->GetBasicBlocks ())
320268 {
321269 for (size_t i = block->GetStart (), end = block->GetEnd (); i < end; ++i)
322270 {
323271 auto instr = mssa->GetInstruction (i);
324- // current_il_function.ssa_form.get_ssa_var_value(current_il_instruction.dest.var)
325272 if (instr.operation == MLIL_JUMP)
326273 {
327274 if (instr.GetDestExpr <MLIL_JUMP>().operation == MLIL_VAR_SSA)
328275 {
329276 auto dest = instr.GetDestExpr <MLIL_JUMP>();
330- // RegisterValue value = mssa->GetSSAVarValue(instr.GetDestExpr().GetSourceSSAVariable()) ExprId def = mssa->GetSSAVarDefinition(instr.GetDestExpr().GetSourceSSAVariable());
331- // MLILInstruction defInstr = mssa->GetInstruction(mssa->GetSSAVarDefinition(instr.GetDestExpr().GetSourceSSAVariable()));
332- // targetOffset = mssa->GetInstruction(mssa->GetSSAVarDefinition(instr.GetDestExpr().GetSourceSSAVariable())).GetSourceExpr().GetSourceExpr().GetConstant();
333277 auto value = mssa->GetSSAVarValue (dest.GetSourceSSAVariable ());
334278 if (value.state == UndeterminedValue)
335279 {
336- bool otherFunctionAlreadyRunning;
337- {
338- otherFunctionAlreadyRunning =
339- !workflowState->imageLoadMutex .try_lock ();
340- if (!otherFunctionAlreadyRunning)
341- workflowState->imageLoadMutex .unlock ();
342- }
343- if (otherFunctionAlreadyRunning)
344- {
345- return ;
346- }
347-
348- std::unique_lock<std::mutex> lock (
349- workflowState->imageLoadMutex );
350280 auto def = mssa->GetSSAVarDefinition (dest.GetSourceSSAVariable ());
351281 auto defInstr = mssa->GetInstruction (def);
352282 auto targetOffset = defInstr.GetSourceExpr ().GetSourceExpr ().GetConstant ();
353-
354- if (bv->IsValidOffset (targetOffset))
355- return ;
356-
357- Ref<SharedCacheAPI::SharedCache> cache = new SharedCacheAPI::SharedCache (bv);
358-
359- if (!cache)
360- return ;
361-
362- if (!cache->GetImageNameForAddress (targetOffset).empty ())
363- {
364- cache->LoadImageContainingAddress (targetOffset);
365- }
366- else
367- {
368- cache->LoadSectionAtAddress (targetOffset);
369- }
370- for (const auto §Func : bv->GetAnalysisFunctionList ())
371- {
372- if (section->GetStart () <= sectFunc->GetStart () && sectFunc->GetStart () < section->GetEnd ())
373- {
374- func->Reanalyze ();
375- }
376- }
283+ ProcessStubImageCall (workflowState, cache, func, section, targetOffset);
377284 }
378285 }
379-
380286 }
381287 }
382288 }
@@ -397,7 +303,7 @@ void SharedCacheWorkflow::FixupStubs(Ref<AnalysisContext> ctx)
397303 auto dest = instr.GetDestExpr <MLIL_CALL_SSA>();
398304 if (!bv->IsValidOffset (dest.GetConstant ()))
399305 {
400- ProcessOffImageCall (ctx, func, mssa, dest, instr. GetSSAExprIndex () );
306+ ProcessOffImageCall (ctx, cache, func, mssa, dest);
401307 }
402308 }
403309 }
0 commit comments