LLVM Pass开发:如何在LLVM IR中获取Objective-C Selector名称?
解决LLVM Pass中获取Objective-C方法Selector的问题
在Objective-C的LLVM IR中,所有方法调用都会被编译为objc_msgSend(或其变体,比如objc_msgSend_stret)的调用,你要找的currentGameID是作为selector参数传递给objc_msgSend的,不是函数名本身。所以你需要从objc_msgSend的调用参数里提取selector字符串,而不是直接拿函数名。
具体步骤和代码修改:
- 确认当前
CallInst是objc_msgSend的调用 - 获取
objc_msgSend的第二个参数(第一个参数是self,第二个就是selector) - 解析这个参数对应的常量字符串,得到真实的selector名称
修改你现有的handleComp函数,在处理CallInst的部分加入以下逻辑:
bool handleComp(ICmpInst *cmpInst) { if (!cmpInst->hasOneUse()) { return false; } // 先确认右操作数是2007 auto *rhs = dyn_cast<ConstantInt>(cmpInst->getOperand(1)); if (!rhs || rhs->getSExtValue() != 2007) { return false; } auto *preInstruction = cmpInst->getPrevNode(); if (!isa<CallInst>(preInstruction)) { return false; } CallInst *ci = cast<CallInst>(preInstruction); Value *calledOp = ci->getCalledOperand()->stripPointerCasts(); Function *calledFunc = dyn_cast<Function>(calledOp); if (!calledFunc || calledFunc->getName() != "objc_msgSend") { return false; } // 获取objc_msgSend的第二个参数:selector Value *selArg = ci->getOperand(1); // 解析selector常量 if (ConstantExpr *selExpr = dyn_cast<ConstantExpr>(selArg)) { Value *selConst = selExpr->getOperand(0)->stripPointerCasts(); if (ConstantDataArray *selStr = dyn_cast<ConstantDataArray>(selConst)) { StringRef selectorName = selStr->getAsString(); // 匹配目标selector if (selectorName == "currentGameID") { // 将比较结果替换为true cmpInst->replaceAllUsesWith(ConstantInt::getTrue(cmpInst->getContext())); cmpInst->eraseFromParent(); return true; } } } return false; }
关键细节说明:
objc_msgSend的参数顺序固定:第一个是接收者(self),第二个是selector,后面是方法的参数(如果有的话)- Selector在IR中通常是通过
getelementptr指令指向一个字符串常量,需要逐层剥离指针转换来获取原始的字符串数据 - 如果你的代码需要处理更多objc_msgSend变体(比如带结构体返回值的
objc_msgSend_stret),可以扩展函数名的判断逻辑
内容的提问来源于stack exchange,提问作者Maxwell
相关产品推荐
相关产品推荐

