minix/minix/llvm/passes/magic/support/MagicUtil.cpp
David van Moolenbroek 3e457fe321 Import magic pass from llvm-apps
Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8
2015-09-17 13:57:53 +00:00

1138 lines
44 KiB
C++

#include <magic/support/MagicUtil.h>
using namespace llvm;
namespace llvm {
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
static std::map<const std::string, GlobalVariable*> stringRefCache;
unsigned getLabelHash(std::string label) {
unsigned hash = 0;
for(unsigned i=0;i<label.length();i++){
hash ^= (label[i]);
hash = (hash << 9) | (hash >> ((sizeof(unsigned)*8)-9));
}
return hash;
}
unsigned getModuleHash(DIDescriptor DID, const std::string &baseDir, StringRef extraField="") {
std::string relPath;
PassUtil::getDbgLocationInfo(DID, baseDir, NULL, NULL, &relPath);
return getLabelHash(relPath + "/" + extraField.data());
}
StringRef MagicUtil::getGVSourceName(Module &M, GlobalVariable *GV, DIGlobalVariable **DIGVP, const std::string &baseDir) {
static DIGlobalVariable Var;
Value *DIGV = Backports::findDbgGlobalDeclare(GV);
if(DIGV) {
Var = DIGlobalVariable(cast<MDNode>(DIGV));
if(DIGVP) *DIGVP = &Var;
if(GV->getLinkage() == GlobalValue::InternalLinkage){
/* static variable */
StringRef funcName, countStr;
DIScope scope = Var.getContext();
if(scope.isLexicalBlock()){
/* find the subprogram that contains this basic block recursively */
while(!scope.isSubprogram()){
scope = DILexicalBlock(scope).getContext();
}
}
if(scope.isSubprogram()){
/* static function variable */
funcName = DISubprogram(scope).getName();
int count=0;
Module::GlobalListType &globalList = M.getGlobalList();
for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
GlobalVariable *OtherGV = &(*it);
Value *OtherDIGV = Backports::findDbgGlobalDeclare(OtherGV);
if(OtherDIGV) {
DIGlobalVariable OtherVar(cast<MDNode>(OtherDIGV));
DIScope otherScope = OtherVar.getContext();
if(otherScope.isLexicalBlock()){
/* find the subprogram that contains this basic block recursively */
while(!otherScope.isSubprogram()){
otherScope = DILexicalBlock(otherScope).getContext();
}
}
if(otherScope.isSubprogram()){
if(!strcmp(Var.getName().data(), OtherVar.getName().data())){
if(DIGV == OtherDIGV){
break;
}
count++;
}
}
}
}
std::stringstream stm;
if(count > 0){
stm << "." << count;
}
countStr = StringRef(*new std::string(stm.str()));
}else{
/* static global variable */
funcName = "";
countStr = "";
}
std::stringstream stm;
stm << Var.getName().data() << "." << getModuleHash(Var, baseDir, funcName) << countStr.data();
return StringRef(*new std::string(stm.str()));
}else{
/* global variable */
return Var.getName();
}
}else{
/* llvm .str variables and assembly */
if(DIGVP) *DIGVP = NULL;
return GV->getName();
}
}
StringRef MagicUtil::getLVSourceName(Module &M, AllocaInst *V, DIVariable **DIVP) {
static DIVariable Var;
const DbgDeclareInst *DDI = Backports::FindAllocaDbgDeclare(V);
if(DDI && DDI != (const DbgDeclareInst *) -1){
Var = DIVariable(cast<MDNode>(DDI->getVariable()));
if(DIVP) *DIVP = &Var;
int count = 0;
Function *F = V->getParent()->getParent();
for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) {
Instruction *inst = &(*it);
if (DbgDeclareInst *OtherDDI = dyn_cast<DbgDeclareInst>(inst)){
DIVariable otherVar(cast<MDNode>(OtherDDI->getVariable()));
if(!strcmp(Var.getName().data(), otherVar.getName().data())){
if(OtherDDI == DDI){
break;
}
count++;
}
}
}
std::stringstream stm;
stm << Var.getName().data();
if(count > 0){
stm << "." << count;
}
return StringRef(*new std::string(stm.str()));
}else{
if(DIVP) *DIVP = NULL;
return V->getName();
}
}
StringRef MagicUtil::getFunctionSourceName(Module &M, Function *F, DISubprogram **DISP, const std::string &baseDir) {
static DISubprogram Func;
Value *DIF = Backports::findDbgSubprogramDeclare(F);
if(DIF) {
Func = DISubprogram(cast<MDNode>(DIF));
if(DISP) *DISP = &Func;
if(F->getLinkage() == GlobalValue::InternalLinkage){
std::stringstream stm;
stm << Func.getName().data() << "." << getModuleHash(Func, baseDir);
return StringRef(*new std::string(stm.str()));
}else{
return Func.getName();
}
}else{
/* assembly */
if(DISP) *DISP = NULL;
return F->getName();
}
}
void MagicUtil::putStringRefCache(Module &M, const std::string &str, GlobalVariable *GV) {
std::map<const std::string, GlobalVariable*>::iterator it;
it = stringRefCache.find(str);
if(it == stringRefCache.end()) {
stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, GV));
}
}
Constant* MagicUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
return PassUtil::getGetElementPtrConstant(constant, indexes);
}
GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, Instruction *InsertBefore) {
return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertBefore);
}
GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) {
return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertAtEnd);
}
CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
return PassUtil::createCallInstruction(F, args, NameStr, InsertBefore);
}
CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
return PassUtil::createCallInstruction(F, args, NameStr, InsertAtEnd);
}
Function* MagicUtil::getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types, unsigned size) {
return PassUtil::getIntrinsicFunction(M, id, types, size);
}
GlobalVariable *MagicUtil::getStringRef(Module &M, const std::string &str) {
std::map<const std::string, GlobalVariable*>::iterator it;
GlobalVariable *stringRef = NULL;
bool debug = false;
it = stringRefCache.find(str);
if(it != stringRefCache.end()) {
if(debug) magicUtilLog("*** getStringRef: cache hit for " << str);
stringRef = it->second;
}
if(stringRef == NULL) {
stringRef = PassUtil::getStringGlobalVariable(M, str, MAGIC_HIDDEN_STR_PREFIX, MAGIC_STATIC_VARS_SECTION_RO);
stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, stringRef));
}
return stringRef;
}
GlobalVariable *MagicUtil::getIntArrayRef(Module &M, unsigned arrSize, std::vector<int> *arr, bool isConstant) {
static std::map<std::vector<int>, GlobalVariable*> arrayRefCache;
std::map<std::vector<int>, GlobalVariable*>::iterator it;
static std::vector<int> defInitilizer;
//construct an appropriate initializer if we do not have one
if(!arr) {
arr = &defInitilizer;
arr->clear();
for(unsigned i=0;i<arrSize;i++) arr->push_back(0);
}
assert(arrSize == arr->size());
//cache lookup
if(isConstant) {
it = arrayRefCache.find(*arr);
if(it != arrayRefCache.end()) {
return it->second;
}
}
//create a constant internal array reference
std::vector<Constant*> arrayElems;
for(unsigned i=0;i<arr->size();i++) {
arrayElems.push_back(ConstantInt::get(M.getContext(), APInt(32, (*arr)[i], 10)));
}
ArrayType* arrayTy = ArrayType::get(IntegerType::get(M.getContext(), 32), arr->size());
Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
//create the global variable and record it in the module
GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
GlobalValue::InternalLinkage, arrayValue,
MAGIC_HIDDEN_ARRAY_PREFIX);
MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
M.getGlobalList().push_back(arrayRef);
//populate cache
if(isConstant) {
arrayRefCache.insert(std::pair<std::vector<int>, GlobalVariable*>(*arr, arrayRef));
}
return arrayRef;
}
GlobalVariable *MagicUtil::getStringArrayRef(Module &M, unsigned arrSize, std::vector<std::string> *arr, bool isConstant) {
static std::map<std::vector<std::string>, GlobalVariable*> arrayRefCache;
std::map<std::vector<std::string>, GlobalVariable*>::iterator it;
static std::vector<std::string> defInitilizer;
//construct an appropriate initializer if we do not have one
if(!arr) {
arr = &defInitilizer;
arr->clear();
for(unsigned i=0;i<arrSize;i++) arr->push_back("");
}
assert(arrSize == arr->size());
//cache lookup
if(isConstant) {
it = arrayRefCache.find(*arr);
if(it != arrayRefCache.end()) {
return it->second;
}
}
//create a constant internal array reference
std::vector<Constant*> arrayElems;
std::vector<Value*> arrayIndexes;
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
for(unsigned i=0;i<arr->size();i++) {
arrayElems.push_back(getGetElementPtrConstant(getStringRef(M, (*arr)[i]), arrayIndexes));
}
ArrayType* arrayTy = ArrayType::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0), arr->size());
Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
//create the global variable and record it in the module
GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
GlobalValue::InternalLinkage, arrayValue,
MAGIC_HIDDEN_ARRAY_PREFIX);
MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
M.getGlobalList().push_back(arrayRef);
//populate cache
if(isConstant) {
arrayRefCache.insert(std::pair<std::vector<std::string>, GlobalVariable*>(*arr, arrayRef));
}
return arrayRef;
}
GlobalVariable *MagicUtil::getGenericArrayRef(Module &M, std::vector<Constant*> &arrayElems, bool isConstant) {
static std::map<std::vector<Constant*>, GlobalVariable*> arrayRefCache;
std::map<std::vector<Constant*>, GlobalVariable*>::iterator it;
assert(arrayElems.size() > 0);
//cache lookup
if(isConstant) {
it = arrayRefCache.find(arrayElems);
if(it != arrayRefCache.end()) {
return it->second;
}
}
//create a constant internal array reference
ArrayType* arrayTy = ArrayType::get(arrayElems[0]->getType(), arrayElems.size());
Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
//create the global variable and record it in the module
GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
GlobalValue::InternalLinkage, arrayValue,
MAGIC_HIDDEN_ARRAY_PREFIX);
MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
M.getGlobalList().push_back(arrayRef);
//populate cache
if(isConstant) {
arrayRefCache.insert(std::pair<std::vector<Constant*>, GlobalVariable*>(arrayElems, arrayRef));
}
return arrayRef;
}
GlobalVariable *MagicUtil::getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector<Value*> &globalTypeIndexes, GlobalVariable *magicTypeArray) {
int numTypeIndexes = globalTypeIndexes.size();
TYPECONST StructType* magicTypeStructTy = (TYPECONST StructType*) ((TYPECONST ArrayType*)magicTypeArray->getType()->getElementType())->getElementType();
ArrayType* typeIndexesArrTy = ArrayType::get(PointerType::get(magicTypeStructTy, 0), numTypeIndexes+1);
std::vector<Constant*> arrayElems;
for(int i=0;i<numTypeIndexes;i++) {
std::vector<Value*> magicTypeArrayIndexes;
magicTypeArrayIndexes.clear();
magicTypeArrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
magicTypeArrayIndexes.push_back(globalTypeIndexes[i]);
Constant* typePtr = getGetElementPtrConstant(magicTypeArray, magicTypeArrayIndexes);
arrayElems.push_back(typePtr);
}
arrayElems.push_back(ConstantPointerNull::get(PointerType::get(magicTypeStructTy, 0))); //NULL-terminated array
//create the global variable and record it in the module
Constant *arrayValue = ConstantArray::get(typeIndexesArrTy, arrayElems);
GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), true,
GlobalValue::InternalLinkage, arrayValue,
MAGIC_HIDDEN_ARRAY_PREFIX);
MagicUtil::setGlobalVariableSection(arrayRef, MAGIC_STATIC_VARS_SECTION_RO);
M.getGlobalList().push_back(arrayRef);
return arrayRef;
}
GlobalVariable* MagicUtil::getExportedIntGlobalVar(Module &M, std::string name, int value, bool isConstant) {
Constant *intValue = ConstantInt::get(M.getContext(), APInt(32, value, 10));
//create the global variable and record it in the module
GlobalVariable *GV = new GlobalVariable(intValue->getType(), isConstant,
GlobalValue::LinkOnceAnyLinkage, intValue, name);
MagicUtil::setGlobalVariableSection(GV, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
M.getGlobalList().push_back(GV);
return GV;
}
GlobalVariable* MagicUtil::getShadowRef(Module &M, GlobalVariable *GV) {
//create the shadow global variable and record it in the module
TYPECONST Type* type = GV->getType()->getElementType();
GlobalVariable *SGV = new GlobalVariable(type, GV->isConstant(),
GlobalValue::InternalLinkage, 0,
MAGIC_SHADOW_VAR_PREFIX + GV->getName());
SGV->setInitializer(Constant::getNullValue(type));
MagicUtil::setGlobalVariableSection(SGV, GV->isConstant() ? MAGIC_SHADOW_VARS_SECTION_RO : MAGIC_SHADOW_VARS_SECTION_DATA);
M.getGlobalList().push_back(SGV);
if(!GV->hasInitializer()) {
magicUtilLog("Shadowing for extern variable: " << GV->getName());
}
if(GV->isConstant()) {
magicUtilLog("Shadowing for constant variable: " << GV->getName());
}
return SGV;
}
Value* MagicUtil::getMagicStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* var, Value* arrayIndex, const std::string &structFieldName, std::string *structFieldNames) {
//lookup field index
int structFieldIndex;
Value *varPtr;
for(structFieldIndex=0; structFieldName.compare(structFieldNames[structFieldIndex]) != 0; structFieldIndex++) {}
if(arrayIndex) {
//get array ptr
std::vector<Value*> arrayIndexes;
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
arrayIndexes.push_back(arrayIndex);
varPtr = createGetElementPtrInstruction(var, arrayIndexes, "", InsertBefore);
}
else {
varPtr = var;
}
//get struct field ptr
std::vector<Value*> structFieldIndexes;
structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, structFieldIndex, 10)));
Instruction* structFieldPtr = createGetElementPtrInstruction(varPtr, structFieldIndexes, "", InsertBefore);
return structFieldPtr;
}
Value* MagicUtil::getMagicSStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicArray, Value* magicArrayIndex, const std::string &structFieldName) {
static std::string structFieldNames[] = { MAGIC_SSTRUCT_FIELDS };
return getMagicStructFieldPtr(M, InsertBefore, magicArray, magicArrayIndex, structFieldName, structFieldNames);
}
Value* MagicUtil::getMagicTStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicTypeArray, Value* magicTypeArrayIndex, const std::string &structFieldName) {
static std::string structFieldNames[] = { MAGIC_TSTRUCT_FIELDS };
return getMagicStructFieldPtr(M, InsertBefore, magicTypeArray, magicTypeArrayIndex, structFieldName, structFieldNames);
}
Value* MagicUtil::getMagicFStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicFunctionArray, Value* magicFunctionArrayIndex, const std::string &structFieldName) {
static std::string structFieldNames[] = { MAGIC_FSTRUCT_FIELDS };
return getMagicStructFieldPtr(M, InsertBefore, magicFunctionArray, magicFunctionArrayIndex, structFieldName, structFieldNames);
}
Value* MagicUtil::getMagicRStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicVar, const std::string &structFieldName) {
static std::string structFieldNames[] = { MAGIC_RSTRUCT_FIELDS };
return getMagicStructFieldPtr(M, InsertBefore, magicVar, NULL, structFieldName, structFieldNames);
}
Value* MagicUtil::getMagicDStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicDsindexArray, Value* magicDsindexArrayIndex, const std::string &structFieldName) {
static std::string structFieldNames[] = { MAGIC_DSTRUCT_FIELDS };
return getMagicStructFieldPtr(M, InsertBefore, magicDsindexArray, magicDsindexArrayIndex, structFieldName, structFieldNames);
}
Constant* MagicUtil::getArrayPtr(Module &M, GlobalVariable* array) {
//indexes for array
static std::vector<Value*> arrayIndexes;
if(arrayIndexes.empty()) {
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[0]
}
//get array ptr
Constant* arrayPtr = getGetElementPtrConstant(array, arrayIndexes);
return arrayPtr;
}
void MagicUtil::insertMemcpyInst(Module &M, Instruction *InsertBefore, Value *Dst, Value *Src, Value *Len, unsigned Align) {
bool useMemCpyIntrinsics = false;
Function *MemCpy = M.getFunction("memcpy");
if(!MemCpy) {
TYPECONST Type *ArgTys[1] = { IntegerType::getInt32Ty(M.getContext()) };
MemCpy = getIntrinsicFunction(M, Intrinsic::memcpy, ArgTys, 1);
useMemCpyIntrinsics = true;
}
else {
MemCpy = (Function*) M.getOrInsertFunction(MAGIC_MEMCPY_FUNC_NAME, MemCpy->getFunctionType());
}
// Insert the memcpy instruction
std::vector<Value*> MemCpyArgs;
MemCpyArgs.push_back(Dst);
MemCpyArgs.push_back(Src);
MemCpyArgs.push_back(Len);
if(useMemCpyIntrinsics) {
MemCpyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, Align, 10)));
}
createCallInstruction(MemCpy, MemCpyArgs, "", InsertBefore);
}
void MagicUtil::insertCopyInst(Module &M, Instruction *InsertBefore, GlobalVariable *GV, GlobalVariable *SGV, int GVSize, bool forceMemcpy) {
//get type and type size
TYPECONST Type *GVType = GV->getType()->getElementType();
bool isPrimitiveOrPointerType = !GVType->isAggregateType();
//no need for memcpy for primitive types or pointer types
if(isPrimitiveOrPointerType && !forceMemcpy) {
LoadInst* primitiveValue = new LoadInst(GV, "", false, InsertBefore);
new StoreInst(primitiveValue, SGV, false, InsertBefore);
return;
}
//cast pointers to match memcpy prototype
PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
Constant* varAddress = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType);
Constant* varShadowAddress = ConstantExpr::getCast(Instruction::BitCast, SGV, voidPointerType);
//insert the memcpy instruction
MagicUtil::insertMemcpyInst(M, InsertBefore, varShadowAddress, varAddress, ConstantInt::get(M.getContext(), APInt(32, GVSize, 10)), 0);
}
Function* MagicUtil::getCalledFunctionFromCS(const CallSite &CS) {
assert(CS.getInstruction());
Function *function = CS.getCalledFunction();
if(function) {
return function;
}
//handle the weird case of bitcasted function call
//IMPORTANT! function may still be null, if it's an indirect call
ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue());
if (CE) {
assert(CE->getOpcode() == Instruction::BitCast && "Bitcast expected, something else found!");
function = dyn_cast<Function>(CE->getOperand(0));
assert(function);
} else {
errs() << "Warning! Indirect call encountered!\n";
}
return function;
}
void MagicUtil::replaceCallInst(Instruction *originalInst, CallInst *newInst, int argOffset, bool removeUnusedFunction) {
SmallVector< std::pair< unsigned, MDNode * >, 8> MDs;
originalInst->getAllMetadata(MDs);
for(unsigned i=0;i<MDs.size();i++) {
newInst->setMetadata(MDs[i].first, MDs[i].second);
}
CallSite CS = MagicUtil::getCallSiteFromInstruction(originalInst);
assert(CS);
CallingConv::ID CC = CS.getCallingConv();
Function *originalFunction = getCalledFunctionFromCS(CS);
newInst->setCallingConv(CC);
ATTRIBUTE_SET_TY NewAttrs = PassUtil::remapCallSiteAttributes(CS, argOffset);
newInst->setAttributes(NewAttrs);
originalInst->replaceAllUsesWith(newInst);
// If the old instruction was an invoke, add an unconditional branch
// before the invoke, which will become the new terminator.
if (InvokeInst *II = dyn_cast<InvokeInst>(originalInst))
BranchInst::Create(II->getNormalDest(), originalInst);
// Delete the old call site
originalInst->eraseFromParent();
// When asked, remove the original function when nobody uses it any more.
if(removeUnusedFunction && originalFunction->use_empty()) {
originalFunction->eraseFromParent();
}
}
std::vector<Function*> MagicUtil::getGlobalVariablesShadowFunctions(Module &M, std::vector<GlobalVariable*> globalVariables, std::vector<GlobalVariable*> shadowGlobalVariables, std::vector<int> globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag) {
std::vector<Function*> globalVariableShadowFunctions;
for(int i=0;i<magicArraySize;i++) {
Function* func = getGlobalVariableShadowFunction(M, globalVariables[i], shadowGlobalVariables[i], globalVariableSizes[i], magicArray, i, forceShadow, setDirtyFlag);
globalVariableShadowFunctions.push_back(func);
}
return globalVariableShadowFunctions;
}
Function* MagicUtil::getGlobalVariableShadowFunction(Module &M, GlobalVariable* GV, GlobalVariable* SGV, int GVSize, GlobalVariable* magicArray, int magicArrayIndex, bool forceShadow, bool setDirtyFlag) {
static Constant* magicStateDirty = ConstantInt::get(M.getContext(), APInt(32, MAGIC_STATE_DIRTY, 10));
static Function* shadowFunc = NULL;
ConstantInt* magicArrayIndexConst = ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10));
//determine name
std::string name(MAGIC_SHADOW_FUNC_PREFIX);
name.append("_");
if(forceShadow) {
name.append("force_");
}
if(setDirtyFlag) {
name.append("setdf_");
}
name.append(GV->getName());
//create function
std::vector<TYPECONST Type*>shadowFuncArgs;
FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
shadowFunc = Function::Create(shadowFuncType, GlobalValue::InternalLinkage, name, &M);
shadowFunc->setCallingConv(CallingConv::C);
//create blocks
BasicBlock* label_entry = BasicBlock::Create(M.getContext(), "entry",shadowFunc,0);
BasicBlock* label_shadow = BasicBlock::Create(M.getContext(), "shadow",shadowFunc,0);
BasicBlock* label_return = BasicBlock::Create(M.getContext(), "return",shadowFunc,0);
BranchInst::Create(label_shadow, label_entry);
BranchInst::Create(label_return, label_shadow);
Instruction* entryTerm = label_entry->getTerminator();
Instruction* shadowTerm = label_shadow->getTerminator();
if(!forceShadow || setDirtyFlag) {
//get flags
Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, entryTerm, magicArray, magicArrayIndexConst, MAGIC_SSTRUCT_FIELD_FLAGS);
LoadInst* varFlags = new LoadInst(structFlagsField, "", false, entryTerm);
//when not forcing, don't shadow if dirty is already set
if(!forceShadow) {
BinaryOperator* andedVarFlags = BinaryOperator::Create(Instruction::And, varFlags, magicStateDirty, "", entryTerm);
ICmpInst* flagsCmp = new ICmpInst(entryTerm, ICmpInst::ICMP_EQ, andedVarFlags, ConstantInt::get(M.getContext(), APInt(32, 0, 10)), "");
BranchInst::Create(label_shadow, label_return, flagsCmp, entryTerm);
entryTerm->eraseFromParent();
}
//set the dirty flag for the variable
if(setDirtyFlag) {
BinaryOperator* oredVarFlags = BinaryOperator::Create(Instruction::Or, varFlags, magicStateDirty, "", shadowTerm);
new StoreInst(oredVarFlags, structFlagsField, false, shadowTerm);
}
}
//perform a memory copy from the original variable to the shadow variable
MagicUtil::insertCopyInst(M, shadowTerm, GV, SGV, GVSize, /* forceMemcpy */ false);
ReturnInst::Create(M.getContext(), label_return);
return shadowFunc;
}
void MagicUtil::insertGlobalVariableCleanDirtyFlag(Module &M, GlobalVariable* GV, GlobalVariable* magicArray, int magicArrayIndex, Instruction *InsertBefore) {
Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, InsertBefore, magicArray, ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10)), MAGIC_SSTRUCT_FIELD_FLAGS);
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, 0, 10)), structFlagsField, false, InsertBefore);
}
void MagicUtil::insertShadowTag(Module &M, GlobalVariable *GV, Instruction *InsertBefore) {
static Function* shadowFunc = NULL;
PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
//create function
if(!shadowFunc) {
std::vector<TYPECONST Type*>shadowFuncArgs;
shadowFuncArgs.push_back(voidPointerType);
FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
shadowFunc = Function::Create(shadowFuncType, GlobalValue::ExternalLinkage, MAGIC_LAZY_CHECKPOINT_SHADOW_TAG, &M);
shadowFunc->setCallingConv(CallingConv::C);
}
//shadow global variable
std::vector<Value*> args;
args.push_back(new BitCastInst(GV, voidPointerType, "", InsertBefore));
CallInst *callInst = createCallInstruction(shadowFunc, args, "", InsertBefore);
callInst->setCallingConv(CallingConv::C);
}
bool MagicUtil::isShadowTag(Instruction *inst) {
if(dyn_cast<CallInst>(inst)) {
CallInst *callInst = dyn_cast<CallInst>(inst);
Function *function = callInst->getCalledFunction();
if(function == NULL) {
return false;
}
std::string funcName = function->getName();
if(!funcName.compare(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG)) {
return true;
}
}
return false;
}
GlobalVariable* MagicUtil::getGlobalVariableFromShadowTag(Instruction *inst, std::vector<Instruction*> &instructionsToRemove) {
CallSite CS = MagicUtil::getCallSiteFromInstruction(inst);
assert(CS.arg_size() == 1);
instructionsToRemove.push_back(inst);
CallSite::arg_iterator AI = CS.arg_begin();
Value *ActualArg = *AI;
while(true) {
BitCastInst *castInst = dyn_cast<BitCastInst>(ActualArg);
ConstantExpr *castExpr = dyn_cast<ConstantExpr>(ActualArg);
if(castInst) {
assert(castInst->getNumOperands() == 1);
ActualArg = castInst->getOperand(0);
instructionsToRemove.push_back(castInst);
}
else if(castExpr) {
//assert(castExpr->getNumOperands() == 1);
ActualArg = castExpr->getOperand(0);
}
else {
break;
}
}
GlobalVariable *GV = dyn_cast<GlobalVariable>(ActualArg);
if(GV == NULL) {
magicUtilLog("Weird ActualArg: " << *ActualArg);
}
assert(GV != NULL);
return GV;
}
void MagicUtil::cleanupShadowTag(Module &M, std::vector<Instruction*> &instructionsToRemove) {
int i=0;
for(i =0;i<(int)instructionsToRemove.size();i++) {
Instruction *inst = instructionsToRemove[i];
inst->eraseFromParent();
}
Function* func = M.getFunction(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG);
if(func && func->getNumUses() == 0) {
func->eraseFromParent();
}
}
bool MagicUtil::hasAddressTaken(const GlobalValue *GV, bool includeMembers) {
//Most of the code taken from LLVM's SCCP.cpp
// Delete any dead constantexpr klingons.
GV->removeDeadConstantUsers();
std::vector<const User*> sourceUsers;
sourceUsers.push_back(GV);
if(includeMembers && isa<GlobalVariable>(GV)) {
for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end();
UI != E; ++UI) {
const User *U = *UI;
const ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
if(isa<GetElementPtrInst>(U)) {
sourceUsers.push_back(U);
}
else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
sourceUsers.push_back(U);
}
}
}
for(unsigned i=0;i<sourceUsers.size();i++) {
for (Value::const_use_iterator UI = sourceUsers[i]->use_begin(), E = sourceUsers[i]->use_end();
UI != E; ++UI) {
const User *U = *UI;
if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
if (SI->getOperand(0) == sourceUsers[i] || SI->isVolatile())
return true; // Storing addr of sourceUsers[i].
} else if (isa<InvokeInst>(U) || isa<CallInst>(U)) {
// Make sure we are calling the function, not passing the address.
ImmutableCallSite CS(cast<Instruction>(U));
if (!CS.isCallee(UI))
return true;
} else if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
if (LI->isVolatile())
return true;
} else if (isa<BlockAddress>(U)) {
// blockaddress doesn't take the address of the function, it takes addr
// of label.
} else {
return true;
}
}
}
return false;
}
bool MagicUtil::lookupValueSet(const GlobalVariable *GV, std::vector<int> &valueSet) {
//Similar to hasAddressTaken above, but we look for values
if(!isa<IntegerType>(GV->getType()->getElementType())) {
//integers is all we are interested in
return false;
}
if(!GV->hasInitializer()) {
//external variable
return false;
}
// Delete any dead constantexpr klingons.
GV->removeDeadConstantUsers();
std::set<int> set;
for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end();
UI != E; ++UI) {
const User *U = *UI;
if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
if (SI->getOperand(1) == GV) {
Value *value = SI->getOperand(0);
if(ConstantInt *intValue = dyn_cast<ConstantInt>(value)) {
set.insert(intValue->getSExtValue());
}
else {
return false;
}
}
}
}
const Constant *constant = GV->getInitializer();
if(const ConstantInt *intConstant = dyn_cast<const ConstantInt>(constant)) {
set.insert(intConstant->getSExtValue());
}
else {
return false;
}
assert(set.size() > 0);
valueSet.push_back(set.size()); //push length as the first value
for(std::set<int>::iterator it=set.begin() ; it != set.end(); it++) {
valueSet.push_back(*it);
}
return true;
}
Value* MagicUtil::getStringOwner(GlobalVariable *GV)
{
//Similar to hasAddressTaken above, but we look for string owners
assert(GV && GV->isConstant());
// Skip emtpy strings.
if(GV->hasInitializer() && GV->getInitializer()->isNullValue()) {
return NULL;
}
// Delete any dead constantexpr klingons.
GV->removeDeadConstantUsers();
std::vector<User*> sourceUsers;
sourceUsers.push_back(GV);
for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end();
UI != E; ++UI) {
User *U = *UI;
ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
if(isa<GetElementPtrInst>(U)) {
sourceUsers.push_back(U);
}
else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
sourceUsers.push_back(U);
}
}
Value *stringOwner = NULL;
for(unsigned i=0;i<sourceUsers.size();i++) {
for (Value::use_iterator UI = sourceUsers[i]->use_begin(), E = sourceUsers[i]->use_end();
UI != E; ++UI) {
User *U = *UI;
Value *V = U;
if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
V = SI->getPointerOperand();
}
if(isa<GlobalVariable>(V) || isa<AllocaInst>(V)) {
if(stringOwner != NULL && stringOwner != V) {
//no owner in the ambiguous cases
return NULL;
}
stringOwner = V;
}
}
}
return stringOwner;
}
Instruction* MagicUtil::getFirstNonAllocaInst(Function *F, bool skipAllocaPoint)
{
Instruction *I = NULL;
if (skipAllocaPoint) {
PassUtil::getAllocaInfo(F, NULL, &I);
}
else {
PassUtil::getAllocaInfo(F, &I, NULL);
}
assert(I);
return I;
}
void MagicUtil::setGlobalVariableSection(GlobalVariable *GV, const std::string &section)
{
if(GV->isThreadLocal()) {
return;
}
GV->setSection(section);
}
bool MagicUtil::getCallAnnotation(Module &M, const CallSite &CS, int *annotation)
{
static GlobalVariable *magicAnnotationVar = NULL;
bool instFound = false;
bool annotationFound = false;
if(!magicAnnotationVar) {
magicAnnotationVar = M.getNamedGlobal(MAGIC_CALL_ANNOTATION_VAR_NAME);
assert(magicAnnotationVar);
}
Instruction *I = CS.getInstruction();
if(!I) {
return false;
}
BasicBlock *parent = I->getParent();
for (BasicBlock::iterator i = parent->begin(), e = parent->end(); i != e; ++i) {
Instruction *inst = i;
if(inst != I && !instFound) {
continue;
}
instFound = true;
if(inst == I) {
continue;
}
if(StoreInst *SI = dyn_cast<StoreInst>(inst)) {
if(SI->getOperand(1) == magicAnnotationVar) {
ConstantInt *CI = dyn_cast<ConstantInt>(SI->getOperand(0));
assert(CI && "Bad call annotation!");
annotationFound = true;
*annotation = CI->getSExtValue();
break;
}
}
else if(isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
break;
}
}
return annotationFound;
}
bool MagicUtil::getVarAnnotation(Module &M, const GlobalVariable *GV, int *annotation)
{
std::string GVName = GV->getName();
GlobalVariable *annotationGV = M.getNamedGlobal(MAGIC_VAR_ANNOTATION_PREFIX_NAME + GVName);
if(!annotationGV || !annotationGV->hasInitializer()) {
return false;
}
ConstantInt* annotationValue = dyn_cast<ConstantInt>(annotationGV->getInitializer());
if(!annotationValue) {
return false;
}
*annotation = (int) annotationValue->getSExtValue();
return true;
}
CallSite MagicUtil::getCallSiteFromInstruction(Instruction *I)
{
return PassUtil::getCallSiteFromInstruction(I);
}
AllocaInst* MagicUtil::getAllocaInstFromArgument(Argument *argument)
{
Function *parent = argument->getParent();
std::string targetString = argument->getName().str() + "_addr";
std::string targetString2 = argument->getName().str() + ".addr";
StringRef targetName(targetString);
StringRef targetName2(targetString2);
for (inst_iterator it = inst_begin(parent), et = inst_end(parent); it != et; ++it) {
AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
if(!AI) {
break;
}
if(AI->getName().startswith(targetName) || AI->getName().startswith(targetName2)) {
return AI;
}
}
return NULL;
}
// searches for the specified function in module symbol table assuming that its name has been mangled
// returns NULL if the function has not been found
Function* MagicUtil::getMangledFunction(Module &M, StringRef functionName)
{
Function *F = NULL;
char* outbuf;
const char* functionNameString = functionName.data();
int status;
for (Module::iterator it = M.begin(); it != M.end(); ++it) {
StringRef mangledName = (*it).getName();
outbuf = abi::__cxa_demangle(mangledName.data(), NULL, NULL, &status);
if (status == -2) {
continue; // mangledName is not a valid name under the C++ ABI mangling rules
}
assert(status == 0 && outbuf && "Error when trying to demangle a function name.");
// testing whether this is the function we are looking for
// the unmangled name is similar to a function prototype eg my_func(int, void*, int)
char* pos = strstr(outbuf, functionNameString);
if (!pos) {
free(outbuf);
continue;
}
// function names can only contain alpha-numeric characters and '_'
// if the unmangled name refers to the target function, then that substring should not
// be surrounded by characters allowed in a function name
// (to exclude cases such as myfunc vs _myfunc vs myfunc2)
if (pos > outbuf) {
if (isalnum(*(pos - 1)) || (*(pos - 1) == '_')) {
free(outbuf);
continue;
}
}
if (strlen(pos) > strlen(functionNameString)) {
if (isalnum(*(pos + strlen(functionNameString))) || (*(pos + strlen(functionNameString)) == '_')) {
free(outbuf);
continue;
}
}
F = it;
free(outbuf);
break;
}
return F;
}
Function* MagicUtil::getFunction(Module &M, StringRef functionName)
{
Function* F = M.getFunction(functionName);
if (!F) {
F = MagicUtil::getMangledFunction(M, functionName);
}
return F;
}
// can Type1 be represented as Type2 (with no precision loss)
bool MagicUtil::isCompatibleType(const Type* Type1, const Type* Type2)
{
if (Type1 == Type2) {
return true;
}
if (Type1->isIntegerTy() && Type2->isIntegerTy()) {
if (((const IntegerType*)Type1)->getBitWidth() <= ((const IntegerType*)Type2)->getBitWidth()) {
return true;
}
}
return false;
}
// inserts an inlined call to the pre-hook function before any other instruction is executed
// it can forward (some of) the original function's parameters and additional trailing arguments
void MagicUtil::inlinePreHookForwardingCall(Function* function, Function* preHookFunction, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs)
{
std::vector<Value*> callArgs;
assert(preHookFunction->arg_size() == argsMapping.size() + trailingArgs.size() &&
"The number of parameter values specified for the pre-hook function does not match the signature of the function.");
for (std::vector<unsigned>::iterator it = argsMapping.begin(); it != argsMapping.end(); it++) {
callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
}
for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
callArgs.push_back(*it);
}
// insert the call after the alloca instructions so that they remain for sure in the entry block
Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(function);
for (unsigned i = 0; i < callArgs.size(); ++i) {
TYPECONST Type* ArgType = callArgs[i]->getType();
TYPECONST Type* ParamType = preHookFunction->getFunctionType()->getParamType(i);
if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
assert(CastInst::isCastable(ArgType, ParamType) && "The value of the argument cannot be "
"casted to the parameter type required by the function to be called.");
Instruction::CastOps CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", FirstInst);
}
}
CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(preHookFunction, callArgs, "", FirstInst);
InlineFunctionInfo IFI;
InlineFunction(WrapperFuncCall, IFI);
}
// inserts an inlined call to the post-hook function before all return instructions
// forwarded arguments from the first function come first, followed by the trailing ones
// use offsets > 0 for function parameter mappings, and 0 for the return value of the function
void MagicUtil::inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector<unsigned> mapping, std::vector<Value*> trailingArgs)
{
std::vector<CallInst*> wrapperCalls;
assert(postHookFunction->arg_size() == mapping.size() + trailingArgs.size()
&& "The number of parameter values specified for the post-hook function does not match the signature of the function.");
for (Function::iterator BI = function->getBasicBlockList().begin(); BI != function->getBasicBlockList().end(); ++BI) {
ReturnInst *RetInst = dyn_cast<ReturnInst>(BI->getTerminator());
if (RetInst) {
std::vector<Value*> callArgs;
for (std::vector<unsigned>::iterator it = mapping.begin(); it != mapping.end(); it++) {
if (*it > 0) {
callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
} else {
callArgs.push_back(RetInst->getReturnValue());
}
}
for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
callArgs.push_back(*it);
}
for (unsigned i = 0; i < callArgs.size(); i++) {
TYPECONST Type* ArgType = callArgs[i]->getType();
TYPECONST Type* ParamType = postHookFunction->getFunctionType()->getParamType(i);
if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
assert(CastInst::isCastable(ArgType, ParamType) && "The value of the argument cannot be "
"casted to the parameter type required by the function to be called.");
Instruction::CastOps CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", RetInst);
}
}
CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(postHookFunction, callArgs, "", RetInst);
wrapperCalls.push_back(WrapperFuncCall);
}
}
for (std::vector<CallInst*>::iterator it = wrapperCalls.begin(); it != wrapperCalls.end(); ++it) {
InlineFunctionInfo IFI;
InlineFunction(*it, IFI);
}
}
int MagicUtil::getPointerIndirectionLevel(const Type* type)
{
int level = 0;
if (const PointerType* ptr_type = dyn_cast<PointerType>(type)) {
while (ptr_type) {
level++;
ptr_type = dyn_cast<PointerType>(ptr_type->getElementType());
}
}
return level;
}
Value* MagicUtil::getFunctionParam(Function* function, unsigned index)
{
if (index >= function->arg_size()) {
return NULL;
}
Function::arg_iterator AI = function->arg_begin();
while (index --> 0) {
AI++;
}
return AI;
}
bool MagicUtil::isLocalConstant(Module &M, GlobalVariable *GV)
{
if (!GV->isConstant()) {
return false;
}
if (GV->getName().endswith(".v")) {
return true;
}
std::pair<StringRef, StringRef> stringPair = GV->getName().split('.');
StringRef functionName = stringPair.first;
if (!functionName.compare("") || M.getFunction(functionName) == NULL) {
return false;
}
return true;
}
}