llvm传递replaceAllUsesWith类型不匹配?

时间:2015-02-12 07:06:45

标签: c++ llvm llvm-ir

使用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;),

1 个答案:

答案 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指令时捕获它(如果运行它)。