llvm pass replaceAllUsesWith类型不匹配

问题描述:

使用encryptedString替换GlobalVariable但类型不匹配。llvm pass replaceAllUsesWith类型不匹配

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

但失败:

断言失败:(新建 - >的getType()==的getType() 值与不同类型的新值的& &“replaceAllUses !“),

起初:我建议在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]; 
} 

这将只返回的int表示。

编译于红外线它看起来像这样:

@.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作为内容索引。这将导致出界限制访问。我不知道当看到GEP指令(如果你运行它)时,llvm验证通过是否会捕获这个问题。

+0

如果替换类型[7×6-18],和 “getelementptr界外球([12×6-18] * @名为.str,I32 0,I64 9)” 将变为“getelementptr inbounds([7 x i8] * @ .str,i32 0,i64 9)”? – AloneMonkey 2015-02-12 08:48:55

+0

是的,如果你看看Value类的'replaceAllUsesWith'函数,你会看到'ReplaceUnsafe'函数基本上是一样的。 'replaceAllUsesWith'函数后面没有语义检查。你所拥有的只是检查(一些)可以在IR中完成的错误的验证通行证,并且我认为它会告诉你GEP指令有问题,但我不确定。 – 2015-02-12 09:17:57

+0

谢谢你的回答! – AloneMonkey 2015-02-13 01:32:32

Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, true); 

变化到

 
Constant *cryptedStr = ConstantDataArray::getString(M.getContext(), encryptedString, false);