summaryrefslogtreecommitdiff
path: root/view/sharedcache/workflow/ObjCActivity.cpp
diff options
context:
space:
mode:
authorMark Rowe <mrowe@bdash.net.nz>2025-02-19 15:54:58 -0800
committerMason Reed <mason@vector35.com>2025-04-08 13:21:48 -0400
commita6c5c22f08032374481aa060b59ef3492d124200 (patch)
treed8e72a1a7a6c41b61a960dc9b7d33a81d136b1e2 /view/sharedcache/workflow/ObjCActivity.cpp
parent9eba1bb003e65a664367c9bf2b6ed03d418aa3c2 (diff)
[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.
Diffstat (limited to 'view/sharedcache/workflow/ObjCActivity.cpp')
-rw-r--r--view/sharedcache/workflow/ObjCActivity.cpp37
1 files changed, 29 insertions, 8 deletions
diff --git a/view/sharedcache/workflow/ObjCActivity.cpp b/view/sharedcache/workflow/ObjCActivity.cpp
index f620de85..cc1b2256 100644
--- a/view/sharedcache/workflow/ObjCActivity.cpp
+++ b/view/sharedcache/workflow/ObjCActivity.cpp
@@ -42,6 +42,7 @@ void ObjCActivity::AdjustCallType(Ref<AnalysisContext> ctx)
const auto func = ctx->GetFunction();
const auto arch = func->GetArchitecture();
const auto bv = func->GetView();
+ const auto baseAddr = bv->GetStart();
const auto llil = ctx->GetLowLevelILFunction();
if (!llil) {
@@ -52,9 +53,9 @@ void ObjCActivity::AdjustCallType(Ref<AnalysisContext> ctx)
return;
}
- const auto rewriteIfEligible = [bv, ssa](size_t insnIndex) {
+ const auto rewriteIfEligible = [bv, ssa, baseAddr](size_t insnIndex) {
auto insn = ssa->GetInstruction(insnIndex);
- if (insn.operation != LLIL_CALL_SSA)
+ if (insn.operation != LLIL_CALL_SSA && insn.operation != LLIL_TAILCALL_SSA)
return;
enum class MessageSendType {
@@ -64,7 +65,7 @@ void ObjCActivity::AdjustCallType(Ref<AnalysisContext> ctx)
MessageSendType messageSendType = MessageSendType::Normal;
// Filter out calls that aren't to `objc_msgSend`, `objc_msgSendSuper`, or `objc_msgSendSuper2`.
- auto callExpr = insn.GetDestExpr<LLIL_CALL_SSA>();
+ auto callExpr = insn.GetDestExpr();
if (auto symbol = bv->GetSymbolByAddress(callExpr.GetValue().value))
{
std::string_view symbolName = symbol->GetRawNameRef();
@@ -76,7 +77,7 @@ void ObjCActivity::AdjustCallType(Ref<AnalysisContext> ctx)
return;
}
- const auto params = insn.GetParameterExprs<LLIL_CALL_SSA>();
+ const auto params = insn.GetParameterExprs();
// The second parameter passed to the objc_msgSend call is the address of
// either the selector reference or the method's name, which in both cases
// is dereferenced to retrieve a selector.
@@ -95,13 +96,33 @@ void ObjCActivity::AdjustCallType(Ref<AnalysisContext> ctx)
const auto selectorRegister = params[0].GetParameterExprs<LLIL_SEPARATE_PARAM_LIST_SSA>()[1].GetSourceSSARegister<LLIL_REG_SSA>();
rawSelector = ssa->GetSSARegisterValue(selectorRegister).value;
}
- if (!rawSelector || !bv->IsValidOffset(rawSelector))
+
+ // Skip if we don't have a
+ if (!rawSelector || rawSelector < baseAddr)
return;
+ std::string selector;
+ if (bv->IsValidOffset(rawSelector)) {
+ BinaryReader reader(bv);
+ reader.Seek(rawSelector);
+ selector = reader.ReadCString(500);
+ } else {
+ // Look for the `sel_` symbols that ObjCProcessor adds to represent selectors
+ // whose backing regions have not yet been loaded into the view.
+ constexpr std::string_view SelectorPrefix = "sel_";
+
+ auto symbol = bv->GetSymbolByAddress(rawSelector);
+ if (!symbol)
+ return;
+
+ std::string_view name = symbol->GetRawNameRef();
+ if (name.find(SelectorPrefix) != 0)
+ return;
+
+ selector = name.substr(SelectorPrefix.length());
+ }
+
// -- Do callsite override
- auto reader = BinaryReader(bv);
- reader.Seek(rawSelector);
- auto selector = reader.ReadCString(500);
auto additionalArgumentCount = std::count(selector.begin(), selector.end(), ':');
auto retType = bv->GetTypeByName({ "id" });