llvm pass replaceAllUsesWith 类型不匹配?
llvm pass replaceAllUsesWith type not match?
使用 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);
但失败了:
Assertion failed: (New->getType() == getType() && "replaceAllUses of
value with new value of different type!"),
首先:我建议在 LLVM IR 中用正确的类型替换所有内容,这就是存在此断言的原因。
但是:
你得到这个断言是因为你的字符串长度不匹配。全局字符串表示为字符数组(即 i8
值)。所以你的字符串类型是 [len x i8]
其中 len
是你的字符串的长度。
@.str = private unnamed_addr constant [12 x i8] c"hello world[=10=]", 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];
}
这将只是 return l
的 int 表示。
编译为 IR 看起来像这样:
@.str = private unnamed_addr constant [12 x i8] c"hello world[=13=]", 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
}
如果字符串现在被不等类型的体素替换(例如,[7 x i8]
类型的东西),那么您可能会遇到问题,因为您的 GEP 指令将 9 作为常量索引。这将导致越界访问。我不知道 llvm verify pass 在查看 GEP 指令时是否捕捉到了这个(如果你 运行 它)。
Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, true);
改为
Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, false);
使用 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);
但失败了:
Assertion failed: (New->getType() == getType() && "replaceAllUses of value with new value of different type!"),
首先:我建议在 LLVM IR 中用正确的类型替换所有内容,这就是存在此断言的原因。
但是:
你得到这个断言是因为你的字符串长度不匹配。全局字符串表示为字符数组(即 i8
值)。所以你的字符串类型是 [len x i8]
其中 len
是你的字符串的长度。
@.str = private unnamed_addr constant [12 x i8] c"hello world[=10=]", 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];
}
这将只是 return l
的 int 表示。
编译为 IR 看起来像这样:
@.str = private unnamed_addr constant [12 x i8] c"hello world[=13=]", 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
}
如果字符串现在被不等类型的体素替换(例如,[7 x i8]
类型的东西),那么您可能会遇到问题,因为您的 GEP 指令将 9 作为常量索引。这将导致越界访问。我不知道 llvm verify pass 在查看 GEP 指令时是否捕捉到了这个(如果你 运行 它)。
Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, true);
改为
Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, false);