使用encryptedString替换GlobalVariable
但输入不匹配。
GlobalVariable
一个const char *
字符串。
这样的代码:
GlobalVariable* GV = *it;
//get clear text string
std::string clearstr = getGlobalStringValue(GV);
GlobalVariable::LinkageTypes lt = GV->getLinkage();
//encrypt current string
std::string encryptedString = stringEncryption(clearstr);
//create new global string with the encrypted string
std::ostringstream oss;
oss << ".encstr" << encryptedStringCounter << "_" << sys::Process::GetRandomNumber();
Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, true);
GlobalVariable* gCryptedStr = new GlobalVariable(M, cryptedStr->getType(), true, GV->getLinkage(), cryptedStr, oss.str());
StringMapGlobalVars[oss.str()] = gCryptedStr;
//replace use of clear string with encrypted string
GV->replaceAllUsesWith(gCryptedStr);
但失败了:
断言失败:(New-&gt; getType()== getType()&amp;&amp;&#34; replaceAllUses of 具有不同类型的新值的值!&#34;),
答案 0 :(得分:1)
首先:我建议在LLVM IR中使用正确的类型替换所有内容,这就是为什么这个断言存在的原因。
然而:
你得到这个断言,因为你的字符串长度不匹配。全局字符串表示为字符数组(即i8
值)。因此,字符串的类型为[len x i8]
,其中len
是字符串的长度。
@.str = private unnamed_addr constant [12 x i8] c"hello world\00", align 1
你能做的就是写下你自己的替换函数:
template<typename T>
void ReplaceUnsafe(T *from, T *to) {
while (!from->use_empty()) {
auto &U = *from->use_begin();
U.set(to);
}
from->eraseFromParent();
}
然而,这是(如函数名称所示)不安全的原因,这就是原因:
考虑以下C / C ++代码:
int main() {
return "hello world"[9];
}
将只返回l
的int表示。
编译为IR,它看起来像这样:
@.str = private unnamed_addr constant [12 x i8] c"hello world\00", align 1
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
%retval = alloca i32, align 4
store i32 0, i32* %retval
%0 = load i8* getelementptr inbounds ([12 x i8]* @.str, i32 0, i64 9), align 1
%conv = sext i8 %0 to i32
ret i32 %conv
}
如果字符串现在被替换为不等类型的somiting(例如,[7 x i8]
类型的东西),那么您可能会遇到问题,因为您的GEP指令具有9作为常量索引。这将导致越界访问。我不知道llvm验证通过是否会在查看GEP指令时捕获它(如果运行它)。