Skip to content

Commit 051ca95

Browse files
committed
[SharedCache] Cleanup SharedCacheWorkflow::FixupStubs
Moved some code to a helper function and removed dead code and other oddities
1 parent c93685e commit 051ca95

File tree

2 files changed

+80
-178
lines changed

2 files changed

+80
-178
lines changed

view/sharedcache/workflow/SharedCacheWorkflow.cpp

Lines changed: 77 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include "mediumlevelilinstruction.h"
1414
#include "../api/sharedcacheapi.h"
1515
#include "thread"
16+
#include <shared_mutex>
1617

18+
using namespace SharedCacheAPI;
1719

1820
struct 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 &sectFunc : 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 &sectFunc : 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 &sectFunc : 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 &sectFunc : 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
}

view/sharedcache/workflow/SharedCacheWorkflow.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
1-
2-
#include "binaryninjaapi.h"
3-
4-
using namespace BinaryNinja;
5-
6-
71
#ifndef SHAREDCACHE_SHAREDCACHEWORKFLOW_H
82
#define SHAREDCACHE_SHAREDCACHEWORKFLOW_H
93

4+
#include "binaryninjaapi.h"
5+
#include "view/sharedcache/api/sharedcacheapi.h"
106

117
class SharedCacheWorkflow
128
{
139
public:
14-
static void ProcessOffImageCall(Ref<AnalysisContext> ctx, Ref<Function> func, Ref<MediumLevelILFunction> il, const MediumLevelILInstruction instr, ExprId exprIndex, bool applySymbolIfFoundToCurrentFunction = false);
10+
static void ProcessOffImageCall(Ref<AnalysisContext> ctx, Ref<SharedCacheAPI::SharedCache> cache, Ref<Function> func, Ref<MediumLevelILFunction> il, const MediumLevelILInstruction instr, bool applySymbolIfFoundToCurrentFunction = false);
1511
static void FixupStubs(Ref<AnalysisContext> ctx);
1612
static void Register();
1713
};

0 commit comments

Comments
 (0)