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);