Skip to content

Commit 5457e3a

Browse files
committed
[SharedCache] Apply objc_msgSend call type overrides in more places
`fixObjCCallTypes` is updated to handle tail calls as well as regular calls. Additionally, if the selector address is not valid it now looks for the `sel_` symbols that `DSCObjCProcessor::ReadMethodList` adds for selectors whose names reside in regions that are not yet mapped. This allows call type overrides to be applied even when a selector's name is defined in a different image.
1 parent 67e5ac0 commit 5457e3a

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

view/sharedcache/workflow/ObjCActivity.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,16 @@ void ObjCActivity::AdjustCallType(Ref<AnalysisContext> ctx)
5454

5555
const auto rewriteIfEligible = [bv, ssa](size_t insnIndex) {
5656
auto insn = ssa->GetInstruction(insnIndex);
57-
if (insn.operation != LLIL_CALL_SSA)
57+
if (insn.operation != LLIL_CALL_SSA && insn.operation != LLIL_TAILCALL_SSA)
5858
return;
5959

6060
// Filter out calls that aren't to `objc_msgSend`.
61-
auto callExpr = insn.GetDestExpr<LLIL_CALL_SSA>();
61+
auto callExpr = insn.GetDestExpr();
6262
if (auto symbol = bv->GetSymbolByAddress(callExpr.GetValue().value))
6363
if (symbol->GetRawName() != "_objc_msgSend")
6464
return;
6565

66-
const auto params = insn.GetParameterExprs<LLIL_CALL_SSA>();
66+
const auto params = insn.GetParameterExprs();
6767
// The second parameter passed to the objc_msgSend call is the address of
6868
// either the selector reference or the method's name, which in both cases
6969
// is dereferenced to retrieve a selector.
@@ -82,13 +82,31 @@ void ObjCActivity::AdjustCallType(Ref<AnalysisContext> ctx)
8282
const auto selectorRegister = params[0].GetParameterExprs<LLIL_SEPARATE_PARAM_LIST_SSA>()[1].GetSourceSSARegister<LLIL_REG_SSA>();
8383
rawSelector = ssa->GetSSARegisterValue(selectorRegister).value;
8484
}
85-
if (!rawSelector || !bv->IsValidOffset(rawSelector))
85+
if (!rawSelector)
8686
return;
8787

88+
std::string selector;
89+
if (bv->IsValidOffset(rawSelector)) {
90+
BinaryReader reader(bv);
91+
reader.Seek(rawSelector);
92+
selector = reader.ReadCString(500);
93+
} else {
94+
// Look for the `sel_` symbols that ObjCProcessor adds to represent selectors
95+
// whose backing regions have not yet been loaded into the view.
96+
constexpr std::string_view SelectorPrefix = "sel_";
97+
98+
auto symbol = bv->GetSymbolByAddress(rawSelector);
99+
if (!symbol)
100+
return;
101+
102+
std::string_view name = symbol->GetRawNameRef();
103+
if (name.find(SelectorPrefix) != 0)
104+
return;
105+
106+
selector = name.substr(SelectorPrefix.length());
107+
}
108+
88109
// -- Do callsite override
89-
auto reader = BinaryReader(bv);
90-
reader.Seek(rawSelector);
91-
auto selector = reader.ReadCString(500);
92110
auto additionalArgumentCount = std::count(selector.begin(), selector.end(), ':');
93111

94112
auto retType = bv->GetTypeByName({ "id" });

0 commit comments

Comments
 (0)