2878 lines
142 KiB
C++
2878 lines
142 KiB
C++
#include <magic/MagicPass.h>
|
|
|
|
using namespace llvm;
|
|
|
|
PASS_COMMON_INIT_ONCE();
|
|
|
|
// command-line arguments
|
|
static cl::opt<std::string>
|
|
DLLFName("magic-dll-function",
|
|
cl::desc("Specify the name of the deepest long-lived function whose stack "
|
|
"needs to be instrumented"),
|
|
cl::init(MAGIC_ENTRY_POINT), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
LibPathRegex("magic-lib-path-regex",
|
|
cl::desc("Specify all the colon-separated path regexes that identify directories containing "
|
|
"libraries. Deprecated. Use -magic-ext-lib-sections instead."),
|
|
cl::init(""), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
VoidTypeAlias("magic-void-alias",
|
|
cl::desc("Specify all the colon-separated type names that are to be treated as void, typically "
|
|
"used in custom memory management implementations"),
|
|
cl::init(""), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
MMFuncPrefix("magic-mmfunc-prefix",
|
|
cl::desc("Specify all the colon-separated prefixes that are to be used when extracting "
|
|
"memory management functions used in custom memory management implementations"),
|
|
cl::init(""), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
MMFuncPair("magic-mmfunc-pair",
|
|
cl::desc("Specify all the colon-separated pairs of malloc/free style memory management functions "
|
|
"used in custom memory management implementations. Each function is to be listed together "
|
|
"with a number indicating which of the input parameters is the one corresponding to its "
|
|
"malloc(size)/free(pointer) counterpart. Example: "
|
|
"\"my_smart_alloc/3;my_smart_free/3:my_custom_alloc/2;my_custom_free/1\". "
|
|
"The counter for arguments starts from 1."),
|
|
cl::init(""), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
MMPoolFunc("magic-mm-poolfunc",
|
|
cl::desc("Specify a pool memory management set of functions for creating pools, destroying pools, "
|
|
"managing the pool buffers, reseting (reusing) pools and allocating memory blocks from the pool. "
|
|
"All the functions are to be listed together with a number indicating which of the input parameters"
|
|
"(numbering starts at 1) corresponds to the pool object. For the creation function, the pool object "
|
|
"can be the return value (specify 0 for return value). The block allocation function additionally "
|
|
"requires the number of the parameter denoting the size. Separate sets of functions using ':' and "
|
|
"separate multiple functions of the same type using ';'. "
|
|
"Example: \"my_pool_block_alloc/1/2:my_pool_create/0:my_pool_destroy/1:my_pool_alloc/1;"
|
|
"another_pool_alloc/1;my_pool_free/1:my_pool_reset/1\"."
|
|
"If there are no additional management functions, skip them. "
|
|
"Example: \"pool_block_alloc/1/2:pool_create:pool_destroy/1\"."),
|
|
cl::init(""), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<bool>
|
|
EnablePoolMemReuse("magic-mpool-enable-reuse",
|
|
cl::desc("Enable memory reuse across pools."),
|
|
cl::init(false), cl::NotHidden);
|
|
|
|
static cl::opt<std::string>
|
|
MMAPCtlFunction("magic-mmap-ctlfunc",
|
|
cl::desc("Specify all the colon-separated mmap control functions that change low-level properties"
|
|
"of memory-mapped memory regions taking the start address as an argument"),
|
|
cl::init(""), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
MagicDataSections("magic-data-sections",
|
|
cl::desc("Specify all the colon-separated magic data section regexes not to instrument"),
|
|
cl::init("^" MAGIC_STATIC_VARS_SECTION_PREFIX ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
MagicFunctionSections("magic-function-sections",
|
|
cl::desc("Specify all the colon-separated magic function section regexes not to instrument"),
|
|
cl::init("^" MAGIC_STATIC_FUNCTIONS_SECTION ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
ExtLibSections("magic-ext-lib-sections",
|
|
cl::desc("Specify all the colon-separated external lib section regexes"),
|
|
cl::init(MAGIC_DEFAULT_EXT_LIB_SECTION_REGEX), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<std::string>
|
|
baseBuildDir("magic-base-build-dir",
|
|
cl::desc("Specify the base build directory from which the pass derives relative directories for debug symbols"),
|
|
cl::init(""), cl::NotHidden, cl::ValueRequired);
|
|
|
|
static cl::opt<bool>
|
|
EnableShadowing("magic-enable-shadowing",
|
|
cl::desc("Enable state shadowing"),
|
|
cl::init(false), cl::NotHidden);
|
|
|
|
static cl::opt<bool>
|
|
SkipAll("magic-skip-all",
|
|
cl::desc("Exit immediately"),
|
|
cl::init(false), cl::NotHidden);
|
|
|
|
#if MAGIC_USE_QPROF_INSTRUMENTATION
|
|
QPROF_DECLARE_ALL_OPTS(magic,
|
|
magicLLSitestacks,
|
|
magicDeepestLLLoops,
|
|
magicDeepestLLLibs,
|
|
magicTaskClasses
|
|
);
|
|
#endif
|
|
|
|
#define DEBUG_TYPE_INFOS 0
|
|
#define DEBUG_FILL_TYPE_INFOS 0
|
|
#define DEBUG_FILL_EXT_TYPE_INFOS 0
|
|
#define DEBUG_ALLOC_LEVEL 0
|
|
#define DEBUG_ALLOC_BAD_TYPES 0
|
|
#define DEBUG_CASTS 0
|
|
#define DEBUG_DUPLICATED_TYPE_INFOS 0
|
|
#define DEBUG_VALUE_SET 0
|
|
#define DEBUG_QPROF 0
|
|
|
|
namespace llvm {
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Constructors, destructor, and operators
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
MagicPass::MagicPass() : ModulePass(ID) {}
|
|
|
|
unsigned TypeInfo::maxNameLength = 0;
|
|
unsigned TypeInfo::maxTypeStringLength = 0;
|
|
std::map<TYPECONST Type*, std::set<int> > TypeInfo::intCastTypes;
|
|
std::map<TYPECONST Type*, std::set<TYPECONST Type*> > TypeInfo::bitCastTypes;
|
|
std::map<TYPECONST Type*, std::set<TypeInfo*> > TypeInfo::typeMap;
|
|
|
|
bool SmartType::forceRawUnions = MAGIC_FORCE_RAW_UNIONS;
|
|
bool SmartType::forceRawBitfields = MAGIC_FORCE_RAW_BITFIELDS;
|
|
|
|
Function *MagicMemFunction::lastAllocWrapper = NULL;
|
|
std::map<std::string, Function*> MagicMemFunction::allocWrapperCache;
|
|
std::set<Function*> MagicMemFunction::customWrapperSet;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Public methods
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool MagicPass::runOnModule(Module &M) {
|
|
unsigned i;
|
|
|
|
if (SkipAll) {
|
|
return false;
|
|
}
|
|
|
|
magicPassLog("Running...");
|
|
EDIType::setModule(&M);
|
|
PassUtil::setModule(&M);
|
|
|
|
// initialize qprof instrumentation
|
|
qprofInstrumentationInit(M);
|
|
|
|
//look up magic entry point function
|
|
Function *magicEntryPointFunc = M.getFunction(MAGIC_ENTRY_POINT);
|
|
if( !magicEntryPointFunc ){
|
|
//if no valid entry point, we are not compiling a valid program, skip pass
|
|
magicPassLog("Error: no " << MAGIC_ENTRY_POINT << "() found");
|
|
return false;
|
|
}
|
|
|
|
//look up magic enabled variable
|
|
GlobalVariable* magicEnabled = M.getNamedGlobal(MAGIC_ENABLED);
|
|
if(!magicEnabled) {
|
|
magicPassErr("Error: no " << MAGIC_ENABLED << " variable found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up magic root variable
|
|
GlobalVariable* magicRootVar = M.getNamedGlobal(MAGIC_ROOT_VAR_NAME);
|
|
if(!magicRootVar) {
|
|
magicPassErr("Error: no " << MAGIC_ROOT_VAR_NAME << " variable found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up magic data init function and get the last instruction to add stuff in it
|
|
Function *magicDataInitFunc = M.getFunction(MAGIC_DATA_INIT_FUNC_NAME);
|
|
if(!magicDataInitFunc){
|
|
magicPassErr("Error: no " << MAGIC_DATA_INIT_FUNC_NAME << "() found");
|
|
exit(1);
|
|
}
|
|
Instruction *magicArrayBuildFuncInst = magicDataInitFunc->back().getTerminator();
|
|
|
|
//look up pointer to magic array and magic struct type
|
|
Value* magicArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES);
|
|
if(!magicArrayPtr) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES << " field found");
|
|
exit(1);
|
|
}
|
|
TYPECONST StructType* magicStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicArrayPtr->getType())->getElementType())->getElementType();
|
|
|
|
//look up pointer to magic array size
|
|
Value *magicArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NUM);
|
|
if(!magicArraySize) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NUM << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up pointer to magic array string size
|
|
Value *magicArrayStrSize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM);
|
|
if(!magicArrayStrSize) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up pointer to magic next id
|
|
Value *magicNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID);
|
|
if(!magicNextId) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up pointer to magic dsindex array and magic dsindex struct type
|
|
Value* magicDsindexArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES);
|
|
if(!magicDsindexArrayPtr) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES << " field found");
|
|
exit(1);
|
|
}
|
|
TYPECONST StructType* magicDsindexStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicDsindexArrayPtr->getType())->getElementType())->getElementType();
|
|
|
|
//look up pointer to magic dsindex array size
|
|
Value *magicDsindexArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM);
|
|
if(!magicDsindexArraySize) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up pointer to magic type array and magic type struct type
|
|
Value *magicTypeArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES);
|
|
if(!magicTypeArrayPtr) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES << " field found");
|
|
exit(1);
|
|
}
|
|
TYPECONST StructType* magicTypeStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicTypeArrayPtr->getType())->getElementType())->getElementType();
|
|
|
|
//look up pointer to magic type array size
|
|
Value *magicTypeArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NUM);
|
|
if(!magicTypeArraySize) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NUM << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up pointer to magic type next id
|
|
Value *magicTypeNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID);
|
|
if(!magicTypeNextId) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up pointer to magic function array and magic function struct type
|
|
Value *magicFunctionArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS);
|
|
if(!magicFunctionArrayPtr) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS << " field found");
|
|
exit(1);
|
|
}
|
|
TYPECONST StructType* magicFunctionStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFunctionArrayPtr->getType())->getElementType())->getElementType();
|
|
|
|
//look up pointer to magic function array size
|
|
Value *magicFunctionArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM);
|
|
if(!magicFunctionArraySize) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up pointer to magic function next id
|
|
Value *magicFunctionNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID);
|
|
if(!magicFunctionNextId) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID << " field found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up magic dsentry struct type
|
|
Value *magicFirstDsentyPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY);
|
|
if(!magicFirstDsentyPtr) {
|
|
magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY << " field found");
|
|
exit(1);
|
|
}
|
|
TYPECONST StructType* magicDsentryStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFirstDsentyPtr->getType())->getElementType())->getElementType();
|
|
|
|
//look up magic init function
|
|
Function *magicInitFunc = M.getFunction(MAGIC_INIT_FUNC_NAME);
|
|
if( !magicInitFunc ){
|
|
magicPassErr("Error: no " << MAGIC_INIT_FUNC_NAME << "() found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up magic dsentry stack functions
|
|
Function *magicStackDsentryCreateFunc = M.getFunction(MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME);
|
|
if (!magicStackDsentryCreateFunc) {
|
|
magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME << "() found");
|
|
exit(1);
|
|
}
|
|
Function *magicStackDsentryDestroyFunc = M.getFunction(MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME);
|
|
if (!magicStackDsentryDestroyFunc) {
|
|
magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME << "() found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up deepest long-lived function
|
|
Function *deepestLLFunction = M.getFunction(DLLFName);
|
|
if (!deepestLLFunction) {
|
|
magicPassErr("Error: no " << DLLFName << "() found");
|
|
exit(1);
|
|
}
|
|
|
|
//lookup magic get page size function
|
|
Function *magicGetPageSizeFunc = M.getFunction(MAGIC_GET_PAGE_SIZE_FUNC_NAME);
|
|
if(!magicGetPageSizeFunc){
|
|
magicPassErr("Error: no " << MAGIC_GET_PAGE_SIZE_FUNC_NAME << "() found");
|
|
exit(1);
|
|
}
|
|
|
|
//look up magic void pointer
|
|
GlobalVariable *magicVoidPtr = M.getNamedGlobal(MAGIC_VOID_PTR_NAME);
|
|
if(!magicVoidPtr) {
|
|
magicPassErr("Error: no " << MAGIC_VOID_PTR_NAME << "variable found");
|
|
exit(1);
|
|
}
|
|
assert(!isMagicGV(M, magicVoidPtr));
|
|
|
|
//look up magic void array
|
|
GlobalVariable *magicVoidArr = M.getNamedGlobal(MAGIC_VOID_ARRAY_NAME);
|
|
if(!magicVoidArr) {
|
|
magicPassErr("Error: no " << MAGIC_VOID_ARRAY_NAME << "variable found");
|
|
exit(1);
|
|
}
|
|
assert(!isMagicGV(M, magicVoidArr));
|
|
|
|
//look up magic void * type pointer
|
|
GlobalVariable *magicVoidPtrTypePtr = M.getNamedGlobal(MAGIC_VOID_PTR_TYPE_PTR_NAME);
|
|
if(!magicVoidPtrTypePtr) {
|
|
magicPassErr("Error: no " << MAGIC_VOID_PTR_TYPE_PTR_NAME << "variable found");
|
|
exit(1);
|
|
}
|
|
|
|
//determine lib path regexes
|
|
PassUtil::parseStringListOpt(libPathRegexes, LibPathRegex);
|
|
|
|
//determine void type aliases
|
|
PassUtil::parseStringListOpt(voidTypeAliases, VoidTypeAlias);
|
|
std::copy( voidTypeAliases.begin(), voidTypeAliases.end(), std::inserter( voidTypeAliasesSet, voidTypeAliasesSet.end() ) );
|
|
|
|
//determine mm function prefixes
|
|
PassUtil::parseStringListOpt(mmFuncPrefixes, MMFuncPrefix);
|
|
|
|
//determine custom malloc/free style custom mm functions
|
|
PassUtil::parseStringPairListOpt(mmFuncPairs, MMFuncPair);
|
|
|
|
//determine the pool management sets of functions
|
|
PassUtil::parseStringListOpt(mmPoolFunctions, MMPoolFunc);
|
|
|
|
//determine mmap ctl functions
|
|
PassUtil::parseStringListOpt(mmapCtlFunctions, MMAPCtlFunction);
|
|
|
|
//determine magic data section regexes
|
|
PassUtil::parseRegexListOpt(magicDataSectionRegexes, MagicDataSections);
|
|
|
|
//determine magic function section regexes
|
|
PassUtil::parseRegexListOpt(magicFunctionSectionRegexes, MagicFunctionSections);
|
|
|
|
//determine magic ext lib section regexes
|
|
PassUtil::parseRegexListOpt(extLibSectionRegexes, ExtLibSections);
|
|
|
|
//look up inttoptr type casts
|
|
Module::GlobalListType &globalList = M.getGlobalList();
|
|
Module::FunctionListType &functionList = M.getFunctionList();
|
|
std::vector<TYPECONST Type*> intCastTypes;
|
|
std::vector<int> intCastValues;
|
|
std::map<TYPECONST Type*, std::set<TYPECONST Type*> > bitCastMap;
|
|
for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
|
|
Function *F = it;
|
|
if(isMagicFunction(M, F)) {
|
|
continue;
|
|
}
|
|
for (inst_iterator I2 = inst_begin(F), E2 = inst_end(F); I2 != E2; ++I2) {
|
|
indexCasts(M, &(*I2), intCastTypes, intCastValues, bitCastMap);
|
|
}
|
|
}
|
|
for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
|
|
GlobalVariable *GV = it;
|
|
StringRef GVName = GV->getName();
|
|
if(isMagicGV(M, GV) || GVName.startswith(".str") || GVName.startswith(".arr") || GVName.startswith("C.")) {
|
|
continue;
|
|
}
|
|
if(GV->hasInitializer()) {
|
|
indexCasts(M, GV->getInitializer(), intCastTypes, intCastValues, bitCastMap);
|
|
}
|
|
}
|
|
|
|
//index and set cast maps
|
|
std::map<TYPECONST Type*, std::set<int> > intCastMap;
|
|
std::map<TYPECONST Type*, std::set<int> >::iterator intCastMapIt;
|
|
for(i=0;i<intCastTypes.size();i++) {
|
|
TYPECONST Type* type = intCastTypes[i];
|
|
int value = intCastValues[i];
|
|
intCastMapIt = intCastMap.find(type);
|
|
if(intCastMapIt == intCastMap.end()) {
|
|
std::set<int> valueSet;
|
|
intCastMap.insert(std::pair<TYPECONST Type*, std::set<int> >(type, valueSet));
|
|
intCastMapIt = intCastMap.find(type);
|
|
}
|
|
assert(intCastMapIt != intCastMap.end());
|
|
std::set<int> *setPtr = &(intCastMapIt->second);
|
|
if(setPtr->size() == 1 && *(setPtr->begin()) == 0) {
|
|
continue;
|
|
}
|
|
if(value == 0) {
|
|
setPtr->clear();
|
|
}
|
|
setPtr->insert(value);
|
|
}
|
|
TypeInfo::setIntCastTypes(intCastMap);
|
|
TypeInfo::setBitCastTypes(bitCastMap);
|
|
|
|
#if MAGIC_INSTRUMENT_MEM_FUNCS
|
|
//look up magic memory functions and corresponding wrappers
|
|
#define __X(P) #P
|
|
std::string magicMemFuncNames[] = { MAGIC_MEM_FUNC_NAMES };
|
|
std::string magicMemDeallocFuncNames[] = { MAGIC_MEMD_FUNC_NAMES };
|
|
#undef __X
|
|
int magicMemFuncAllocFlags[] = { MAGIC_MEM_FUNC_ALLOC_FLAGS };
|
|
std::string magicMemPrefixes[] = { MAGIC_MEM_PREFIX_STRS };
|
|
std::vector<std::string> llvmCallPrefixes;
|
|
for (std::vector<std::string>::iterator it = mmFuncPrefixes.begin(); it != mmFuncPrefixes.end(); ++it) {
|
|
llvmCallPrefixes.push_back(*it);
|
|
}
|
|
llvmCallPrefixes.push_back("");
|
|
llvmCallPrefixes.push_back("\01"); //llvm uses odd prefixes for some functions, sometimes (e.g. mmap64)
|
|
std::vector<MagicMemFunction> magicMemFunctions;
|
|
std::set<Function*> originalMagicMemFunctions;
|
|
for(i=0;magicMemFuncNames[i].compare("");i++) {
|
|
int allocFlags = magicMemFuncAllocFlags[i];
|
|
for(unsigned j=0;j<llvmCallPrefixes.size();j++) {
|
|
Function *f = M.getFunction(llvmCallPrefixes[j] + magicMemFuncNames[i]);
|
|
if(!f) {
|
|
continue;
|
|
}
|
|
TYPECONST FunctionType *fType = f->getFunctionType();
|
|
if(fType->getNumParams() == 0 && fType->isVarArg()) {
|
|
//missing function prototype, i.e. no realistic caller. Skip.
|
|
continue;
|
|
}
|
|
if(!magicMemFuncNames[i].compare("brk")) {
|
|
brkFunctions.insert(f);
|
|
}
|
|
if(!magicMemFuncNames[i].compare("sbrk")) {
|
|
sbrkFunctions.insert(f);
|
|
}
|
|
std::string wName, wName2;
|
|
Function *w = NULL, *w2 = NULL;
|
|
for(unsigned k=0;magicMemPrefixes[k].compare("");k++) {
|
|
wName = magicMemPrefixes[k] + magicMemFuncNames[i];
|
|
w = M.getFunction(wName);
|
|
if(w) {
|
|
wName2 = wName + "_";
|
|
break;
|
|
}
|
|
}
|
|
if(!w) {
|
|
magicPassErr("Error: no wrapper function found for " << magicMemFuncNames[i] << "()");
|
|
exit(1);
|
|
}
|
|
while(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType()) && (w2 = M.getFunction(wName2))) {
|
|
w = w2;
|
|
wName2.append("_");
|
|
}
|
|
if(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType())) {
|
|
magicPassErr("Error: wrapper function with incompatible type " << wName << "() found");
|
|
magicPassErr(TypeUtil::getDescription(f->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(w->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
|
|
exit(1);
|
|
}
|
|
bool isDeallocFunction = false;
|
|
for(unsigned j=0;magicMemDeallocFuncNames[j].compare("");j++) {
|
|
if(!magicMemDeallocFuncNames[j].compare(magicMemFuncNames[i])) {
|
|
isDeallocFunction = true;
|
|
break;
|
|
}
|
|
}
|
|
MagicMemFunction memFunction(M, f, w, isDeallocFunction, allocFlags);
|
|
magicMemFunctions.push_back(memFunction);
|
|
originalMagicMemFunctions.insert(f);
|
|
|
|
#if DEBUG_ALLOC_LEVEL >= 1
|
|
magicPassErr("Memory management function/wrapper found: " << f->getName() << "()/" << w->getName() << "()");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//look up custom memory management functions and build the corresponding wrappers
|
|
int stdAllocFlags = 0;
|
|
Function *stdAllocFunc, *stdAllocWrapperFunc;
|
|
stdAllocFunc = M.getFunction(MAGIC_MALLOC_FUNC_NAME);
|
|
assert(stdAllocFunc && "Could not find the standard allocation function.");
|
|
for(i=0;magicMemFuncNames[i].compare("");i++) {
|
|
if (!magicMemFuncNames[i].compare(MAGIC_MALLOC_FUNC_NAME)) {
|
|
stdAllocFlags = magicMemFuncAllocFlags[i];
|
|
break;
|
|
}
|
|
}
|
|
assert(magicMemFuncNames[i].compare("") && "Could not find the flags for the standard allocation function.");
|
|
std::string wName;
|
|
for(i=0;magicMemPrefixes[i].compare("");i++) {
|
|
wName = magicMemPrefixes[i] + MAGIC_MALLOC_FUNC_NAME;
|
|
stdAllocWrapperFunc = M.getFunction(wName);
|
|
if (stdAllocWrapperFunc) {
|
|
break;
|
|
}
|
|
}
|
|
assert(stdAllocWrapperFunc && "Could not find a wrapper for the standard allocation function.");
|
|
for (std::set<std::pair<std::string, std::string> >::iterator it = mmFuncPairs.begin(); it != mmFuncPairs.end(); ++it) {
|
|
std::vector<std::string> allocTokens;
|
|
PassUtil::parseStringListOpt(allocTokens, (*it).first, "/");
|
|
assert((allocTokens.size() == stdAllocFunc->getFunctionType()->getNumParams() + 1) && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping");
|
|
|
|
// build custom wrapper for the allocation function
|
|
Function *allocFunction = MagicUtil::getFunction(M, allocTokens[0]);
|
|
if (!allocFunction) {
|
|
continue;
|
|
}
|
|
std::vector<unsigned> allocArgMapping;
|
|
int param;
|
|
for (unsigned i = 0; i < stdAllocFunc->getFunctionType()->getNumParams(); i++) {
|
|
int ret = StringRef(allocTokens[i + 1]).getAsInteger(10, param);
|
|
assert(!ret && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping");
|
|
assert(param > 0 && "The numbering of function parameters starts from 1.");
|
|
allocArgMapping.push_back(param);
|
|
}
|
|
FunctionType *allocFuncType = getFunctionType(allocFunction->getFunctionType(), allocArgMapping);
|
|
if(!isCompatibleMagicMemFuncType(allocFuncType, stdAllocWrapperFunc->getFunctionType())) {
|
|
magicPassErr("Error: standard wrapper function " << stdAllocWrapperFunc->getName() << " has incompatible type.");
|
|
magicPassErr(TypeUtil::getDescription(allocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(stdAllocWrapperFunc->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
|
|
exit(1);
|
|
}
|
|
Function *allocWrapper = MagicMemFunction::getCustomWrapper(allocFunction, stdAllocFunc, stdAllocWrapperFunc, allocArgMapping, false);
|
|
|
|
// register the wrapper
|
|
MagicMemFunction memFunctionAlloc(M, allocFunction, allocWrapper, false, stdAllocFlags);
|
|
magicMemFunctions.push_back(memFunctionAlloc);
|
|
originalMagicMemFunctions.insert(allocFunction);
|
|
#if DEBUG_ALLOC_LEVEL >= 1
|
|
magicPassErr("Allocation function/custom wrapper added: " << allocFunction->getName() << "()/" << allocWrapper->getName() << "()");
|
|
#endif
|
|
}
|
|
|
|
//lookup memory pool management functions and add the corresponding wrapper calls
|
|
int mempoolAllocFlags = MAGIC_STATE_HEAP;
|
|
Function *mempoolBlockAllocTemplate, *mempoolBlockAllocTemplateWrapper;
|
|
mempoolBlockAllocTemplate = MagicUtil::getFunction(M, MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME);
|
|
assert(mempoolBlockAllocTemplate && "Could not find the pool block allocation template function.");
|
|
for(i = 0; magicMemPrefixes[i].compare(""); i++) {
|
|
wName = magicMemPrefixes[i] + MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME;
|
|
mempoolBlockAllocTemplateWrapper = MagicUtil::getFunction(M, wName);
|
|
if (mempoolBlockAllocTemplateWrapper) {
|
|
break;
|
|
}
|
|
}
|
|
assert(mempoolBlockAllocTemplateWrapper && "Could not find a wrapper for the pool block allocation template function.");
|
|
#define __X(P) #P
|
|
// C++11 Initializer Lists are not yet supported as of Clang 3.0 ...
|
|
std::pair<std::string, std::string> magicMempoolFuncNames[] = {
|
|
std::pair<std::string, std::string>(MAGIC_MEMPOOL_CREATE_FUNCS),
|
|
std::pair<std::string, std::string>(MAGIC_MEMPOOL_DESTROY_FUNCS),
|
|
std::pair<std::string, std::string>(MAGIC_MEMPOOL_MGMT_FUNCS),
|
|
std::pair<std::string, std::string>(MAGIC_MEMPOOL_RESET_FUNCS)
|
|
};
|
|
#undef __X
|
|
int magicMempoolFuncFlags[] = { MAGIC_MEMPOOL_FUNC_FLAGS };
|
|
unsigned numMagicMempoolFuncPairs = sizeof(magicMempoolFuncNames) / sizeof(magicMempoolFuncNames[0]);
|
|
std::vector<std::pair<Function*, Function*> > magicMempoolFuncs(numMagicMempoolFuncPairs, std::pair<Function*, Function*>());
|
|
for (i = 0; i < numMagicMempoolFuncPairs; i++) {
|
|
magicMempoolFuncs[i].first = MagicUtil::getFunction(M, magicMempoolFuncNames[i].first);
|
|
if (!magicMempoolFuncs[i].first) {
|
|
magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].first);
|
|
exit(1);
|
|
}
|
|
magicMempoolFuncs[i].second = MagicUtil::getFunction(M, magicMempoolFuncNames[i].second);
|
|
if (!magicMempoolFuncs[i].second) {
|
|
magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].second);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
std::vector<MagicDebugFunction> magicDebugFunctions;
|
|
if (mmPoolFunctions.size()) {
|
|
assert(mmPoolFunctions.size() >= 3 && mmPoolFunctions.size() <= 5 &&
|
|
"Specify at least 3 and at most 5 of the pool management types of functions: block alloc,pool create,pool destroy,pool management functions,pool reset functions.");
|
|
std::vector<std::string>::iterator mmPoolFuncsIt = mmPoolFunctions.begin();
|
|
std::vector<MagicMemFunction> mempoolMagicMemFunctions;
|
|
|
|
// memory pool block allocation functions
|
|
std::vector<std::string> mempoolBlockAllocFuncs;
|
|
PassUtil::parseStringListOpt(mempoolBlockAllocFuncs, *(mmPoolFuncsIt++), ";");
|
|
|
|
for (std::vector<std::string>::iterator funcIt = mempoolBlockAllocFuncs.begin(); funcIt != mempoolBlockAllocFuncs.end(); ++funcIt) {
|
|
std::vector<std::string> funcTokens;
|
|
PassUtil::parseStringListOpt(funcTokens, *funcIt, "/");
|
|
assert(funcTokens.size() == 3 && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number");
|
|
Function* blockAllocFunc = MagicUtil::getFunction(M, funcTokens[0]);
|
|
if (!blockAllocFunc) {
|
|
magicPassErr("Memory pool block allocation function not found - " + funcTokens[0] + ". Skipping instrumentation!");
|
|
mempoolMagicMemFunctions.clear();
|
|
break;
|
|
}
|
|
std::vector<unsigned> argMapping;
|
|
unsigned param;
|
|
for (unsigned i = 1; i < funcTokens.size(); i++) {
|
|
assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number");
|
|
assert(param > 0 && param <= blockAllocFunc->getFunctionType()->getNumParams()
|
|
&& "Bad option format. The function parameter number is not valid.");
|
|
argMapping.push_back(param);
|
|
}
|
|
FunctionType *blockAllocFuncType = getFunctionType(mempoolBlockAllocTemplate->getFunctionType(), argMapping);
|
|
if(!isCompatibleMagicMemFuncType(blockAllocFuncType, mempoolBlockAllocTemplateWrapper->getFunctionType())) {
|
|
magicPassErr("Error: standard wrapper function " << mempoolBlockAllocTemplateWrapper->getName() << " has incompatible type.");
|
|
magicPassErr(TypeUtil::getDescription(blockAllocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(mempoolBlockAllocTemplateWrapper->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
|
|
exit(1);
|
|
}
|
|
Function *blockAllocWrapper = MagicMemFunction::getCustomWrapper(blockAllocFunc, mempoolBlockAllocTemplate, mempoolBlockAllocTemplateWrapper, argMapping, false);
|
|
MagicMemFunction memFunctionBlockAlloc(M, blockAllocFunc, blockAllocWrapper, false, mempoolAllocFlags);
|
|
mempoolMagicMemFunctions.push_back(memFunctionBlockAlloc);
|
|
}
|
|
if (!mempoolMagicMemFunctions.empty()) { // only if the block allocation functions have been successfully processed
|
|
// continue with the rest of the memory pool management functions, which do not require a magic wrapper
|
|
std::vector<std::vector<Function*> >::iterator magicMempoolFuncIt;
|
|
std::vector<std::vector<int> >::iterator magicMempoolFuncFlagsIt;
|
|
for (unsigned magicMempoolFuncIndex = 1; mmPoolFuncsIt != mmPoolFunctions.end(); ++mmPoolFuncsIt, ++magicMempoolFuncIndex) {
|
|
std::vector<std::string> mempoolMgmtFuncs;
|
|
PassUtil::parseStringListOpt(mempoolMgmtFuncs, *mmPoolFuncsIt, ";");
|
|
for (std::vector<std::string>::iterator funcIt = mempoolMgmtFuncs.begin(); funcIt != mempoolMgmtFuncs.end(); ++funcIt) {
|
|
std::vector<std::string> funcTokens;
|
|
PassUtil::parseStringListOpt(funcTokens, *funcIt, "/");
|
|
assert(funcTokens.size() == 2 && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number");
|
|
Function* mempoolMgmtFunc = MagicUtil::getFunction(M, funcTokens[0]);
|
|
assert(mempoolMgmtFunc && "Bad memory pool configuration, instrumentation aborted!");
|
|
std::vector<unsigned> argMapping;
|
|
unsigned param;
|
|
for (unsigned i = 1; i < funcTokens.size(); i++) {
|
|
assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number");
|
|
assert(param <= mempoolMgmtFunc->getFunctionType()->getNumParams() &&
|
|
"Bad option format. The function parameter number is not valid.");
|
|
argMapping.push_back(param);
|
|
}
|
|
std::vector<Value*> trailingArgs;
|
|
if (magicMempoolFuncIndex == 1) { // pool create funcs
|
|
TYPECONST Type* poolType = mempoolMgmtFunc->getFunctionType()->getContainedType(argMapping[0]);
|
|
int level = MagicUtil::getPointerIndirectionLevel(poolType);
|
|
trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (level > 1)));
|
|
} else if (magicMempoolFuncIndex == 2) { // pool destroy funcs
|
|
trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (EnablePoolMemReuse ? 1 : 0)));
|
|
}
|
|
if (magicMempoolFuncFlags[magicMempoolFuncIndex - 1] & MAGIC_HOOK_DEBUG_MASK) {
|
|
MagicDebugFunction magicDebugFunction(mempoolMgmtFunc);
|
|
magicDebugFunction.addHooks(magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs);
|
|
magicDebugFunctions.push_back(magicDebugFunction);
|
|
} else {
|
|
bool ret = MagicDebugFunction::inlineHookCalls(mempoolMgmtFunc,
|
|
magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs);
|
|
if (!ret) {
|
|
magicPassErr("Unable to inline wrapper function calls for " + funcTokens[0]);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (std::vector<MagicMemFunction>::iterator magicIt = mempoolMagicMemFunctions.begin(); magicIt != mempoolMagicMemFunctions.end(); ++magicIt) {
|
|
magicMemFunctions.push_back(*magicIt);
|
|
originalMagicMemFunctions.insert(magicIt->getFunction());
|
|
}
|
|
}
|
|
}
|
|
|
|
//lookup mmap ctl functions whose call arguments need to be fixed
|
|
std::vector<MagicMmapCtlFunction> magicMmapCtlFunctions;
|
|
for (std::vector<std::string>::iterator it = mmapCtlFunctions.begin(); it != mmapCtlFunctions.end(); ++it) {
|
|
std::vector<std::string> tokens;
|
|
tokens.clear();
|
|
PassUtil::parseStringListOpt(tokens, *it, "/");
|
|
assert(tokens.size() == 3 && "Bad option format, format is: function/[ptr_arg_name]/[len_arg_name]");
|
|
|
|
Function *function = M.getFunction(tokens[0]);
|
|
if(!function) {
|
|
continue;
|
|
}
|
|
std::string &ptrArgName = tokens[1];
|
|
std::string &lenArgName = tokens[2];
|
|
MagicMmapCtlFunction magicMmapCtlFunction(function, PointerType::get(IntegerType::get(M.getContext(), 8), 0), ptrArgName, lenArgName);
|
|
magicMmapCtlFunctions.push_back(magicMmapCtlFunction);
|
|
}
|
|
#endif
|
|
|
|
//everything as expected, set magic enabled variable to TRUE
|
|
magicEnabled->setInitializer(ConstantInt::get(M.getContext(), APInt(32, 1)));
|
|
|
|
//scan the list of global variables
|
|
unsigned strGlobalVariables = 0;
|
|
unsigned constGlobalVariables = 0;
|
|
for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
|
|
GlobalVariable *GV = it;
|
|
StringRef GVName = GV->getName();
|
|
TYPECONST Type *GVType = GV->getType()->getElementType();
|
|
bool isPrimitiveOrPointerType = !GVType->isAggregateType();
|
|
DATA_LAYOUT_TY DL = DATA_LAYOUT_TY(&M);
|
|
bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage();
|
|
int typeSize = isExternal ? 0 : DL.getTypeSizeInBits(GVType)/8;
|
|
int align = MAGIC_FORCE_ALIGN;
|
|
|
|
if(isMagicGV(M, GV)) {
|
|
magicPassLog("Skipping magic variable: " << GVName);
|
|
continue;
|
|
}
|
|
assert(!MAGIC_STRINGREF_HAS_MAGIC_HIDDEN_PREFIX(GVName));
|
|
if(GVName.startswith("C.")) {
|
|
//LLVM code we are not interested in
|
|
continue;
|
|
}
|
|
if(MagicUtil::isLocalConstant(M, GV)) {
|
|
//Local constants we are not interested in
|
|
continue;
|
|
}
|
|
#if GLOBAL_VARS_IN_SECTION
|
|
MagicUtil::setGlobalVariableSection(GV, GV->isConstant() ? GLOBAL_VARS_SECTION_RO : GLOBAL_VARS_SECTION_DATA);
|
|
#endif
|
|
if(GVName.startswith(".str")) {
|
|
assert(GV->hasInitializer());
|
|
#if LLVM_VERSION >= 31
|
|
/* XXX Check. */
|
|
ConstantDataArray *initializer = dyn_cast<ConstantDataArray>(GV->getInitializer());
|
|
#else
|
|
ConstantArray *initializer = dyn_cast<ConstantArray>(GV->getInitializer());
|
|
#endif
|
|
if(initializer) {
|
|
assert(initializer->isString());
|
|
MagicUtil::putStringRefCache(M, initializer->getAsString(), GV);
|
|
}
|
|
else {
|
|
MagicUtil::putStringRefCache(M, "", GV);
|
|
}
|
|
|
|
strGlobalVariables++;
|
|
Value *stringOwner = MagicUtil::getStringOwner(GV);
|
|
if(stringOwner) {
|
|
GlobalVariable *GVOwner = dyn_cast<GlobalVariable>(stringOwner);
|
|
AllocaInst *AIOwner = dyn_cast<AllocaInst>(stringOwner);
|
|
assert(GVOwner || AIOwner);
|
|
bool stringOwnerFound = false;
|
|
std::string ownerName;
|
|
raw_string_ostream ostream(ownerName);
|
|
if(GVOwner && !isMagicGV(M, GVOwner)) {
|
|
ostream << "#" << MagicUtil::getGVSourceName(M, GVOwner, NULL, baseBuildDir);
|
|
stringOwnerFound = true;
|
|
}
|
|
else if(AIOwner && !isMagicFunction(M, AIOwner->getParent()->getParent())) {
|
|
ostream << MagicUtil::getFunctionSourceName(M, AIOwner->getParent()->getParent(), NULL, baseBuildDir) << "#" << MagicUtil::getLVSourceName(M, AIOwner);
|
|
stringOwnerFound = true;
|
|
}
|
|
if(stringOwnerFound) {
|
|
ostream.flush();
|
|
stringOwnerMapIt = stringOwnerMap.find(ownerName);
|
|
if(stringOwnerMapIt == stringOwnerMap.end()) {
|
|
stringOwnerMap.insert(std::pair<std::string, GlobalVariable*>(ownerName, GV));
|
|
stringOwnerInvertedMap.insert(std::pair<GlobalVariable*, std::string>(GV, ownerName));
|
|
}
|
|
else {
|
|
stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(stringOwnerMapIt->second);
|
|
if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) {
|
|
stringOwnerInvertedMap.erase(stringOwnerInvertedMapIt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(GV->isConstant()) {
|
|
constGlobalVariables++;
|
|
}
|
|
if(!isPrimitiveOrPointerType && align) {
|
|
GV->setAlignment(align);
|
|
if(typeSize % align) {
|
|
typeSize = typeSize - (typeSize % align) + align;
|
|
}
|
|
}
|
|
else if(MAGIC_OFF_BY_N_PROTECTION_N && GVType->isArrayTy() && typeSize>0) {
|
|
unsigned alignment = typeSize + (DL.getTypeSizeInBits(GVType->getContainedType(0))/8) * MAGIC_OFF_BY_N_PROTECTION_N;
|
|
unsigned a = 2;
|
|
while(a < alignment) a = a << 1;
|
|
GV->setAlignment(a);
|
|
}
|
|
globalVariableSizes.push_back(typeSize);
|
|
globalVariables.push_back(GV);
|
|
if(MagicUtil::hasAddressTaken(GV)) {
|
|
globalVariablesWithAddressTaken.insert(GV);
|
|
}
|
|
}
|
|
magicPassLog(">>>> Number of global variables found: " << globalVariables.size() << " of which " << strGlobalVariables << " .str variables, " << constGlobalVariables << " constants, and " << globalVariables.size()-strGlobalVariables-constGlobalVariables << " regular variables");
|
|
|
|
//build the list of functions having their address taken (include the last function no matter what to get the function ranges right)
|
|
std::vector<const SmartType *> functionTypes;
|
|
std::vector<GlobalValue *> functionTypeParents;
|
|
std::vector<TYPECONST FunctionType *> externalFunctionTypes;
|
|
std::vector<GlobalValue *> externalFunctionTypeParents;
|
|
for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
|
|
Function *F = it;
|
|
if(F->hasAddressTaken() || it == --functionList.end() || F->getName().startswith(MAGIC_EVAL_FUNC_PREFIX)) {
|
|
if(isMagicFunction(M, F)) {
|
|
continue;
|
|
}
|
|
functions.push_back(F);
|
|
const SmartType *FSmartType = SmartType::getSmartTypeFromFunction(M, F);
|
|
if(FSmartType && !FSmartType->isTypeConsistent()) {
|
|
delete FSmartType;
|
|
//pretend the function is external if an invalid type has been found.
|
|
FSmartType = NULL;
|
|
}
|
|
if(!FSmartType) {
|
|
externalFunctionTypes.push_back(F->getFunctionType());
|
|
externalFunctionTypeParents.push_back(F);
|
|
}
|
|
else {
|
|
functionTypes.push_back(FSmartType);
|
|
functionTypeParents.push_back(F);
|
|
}
|
|
}
|
|
}
|
|
magicPassLog(">>>> Number of functions with address taken found: " << functions.size() << ", of which " << functionTypes.size() << " internal and " << externalFunctionTypes.size() << " external...");
|
|
|
|
//build the list of global types
|
|
std::vector<const SmartType *> smartTypes;
|
|
std::vector<GlobalValue *> smartTypeParents;
|
|
std::vector<TYPECONST Type *> externalTypes;
|
|
std::vector<GlobalValue *> externalTypeParents;
|
|
for(i=0;i<globalVariables.size();i++) {
|
|
GlobalVariable *GV = globalVariables[i];
|
|
TYPECONST Type* GVType = GV->getType()->getElementType();
|
|
|
|
const SmartType *GVSmartType = SmartType::getSmartTypeFromGV(M, GV);
|
|
|
|
if(!GV->hasAppendingLinkage()){
|
|
// llvm.global_ctors and llvm.global_dtors have appending linkage, don't have compile unit debug info, and therefore cannot be linked to GV debug info, and so are skipped.
|
|
if(!GVSmartType) {
|
|
bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage();
|
|
if (!isExternal && !GV->isConstant()) {
|
|
magicPassErr("var is: " << GV->getName());
|
|
magicPassErr("type is: " << TypeUtil::getDescription(GV->getType()->getElementType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
|
|
}
|
|
assert(isExternal || GV->isConstant());
|
|
externalTypes.push_back(GVType);
|
|
externalTypeParents.push_back(GV);
|
|
}
|
|
else {
|
|
smartTypes.push_back(GVSmartType);
|
|
smartTypeParents.push_back(GV);
|
|
}
|
|
}
|
|
}
|
|
magicPassLog(">>>> Number of global types found: " << globalVariables.size() << ", of which " << smartTypes.size() << " internal and " << externalTypes.size() << " external...");
|
|
|
|
//build type infos
|
|
TypeInfo* magicVoidPtrTypeInfo = NULL;
|
|
TypeInfo* magicVoidArrTypeInfo = NULL;
|
|
TypeInfo* magicVoidTypeInfo = NULL;
|
|
for(i=0;i<smartTypes.size();i++) {
|
|
TypeInfo sourceTypeInfo(smartTypes[i]);
|
|
sourceTypeInfo.addParent(smartTypeParents[i]);
|
|
TypeInfo *aTypeInfo = fillTypeInfos(sourceTypeInfo, globalTypeInfos);
|
|
if(smartTypeParents[i] == magicVoidPtr) {
|
|
//get a pointer to void and void* types
|
|
magicVoidPtrTypeInfo = aTypeInfo;
|
|
assert(magicVoidPtrTypeInfo->getTypeID() == MAGIC_TYPE_POINTER);
|
|
magicVoidTypeInfo = magicVoidPtrTypeInfo->getContainedType(0);
|
|
assert(magicVoidTypeInfo->getTypeID() == MAGIC_TYPE_VOID);
|
|
}
|
|
else if(smartTypeParents[i] == magicVoidArr) {
|
|
//get a pointer to void array types
|
|
magicVoidArrTypeInfo = aTypeInfo;
|
|
assert(magicVoidArrTypeInfo->getTypeID() == MAGIC_TYPE_ARRAY);
|
|
}
|
|
}
|
|
assert(magicVoidPtrTypeInfo && magicVoidTypeInfo && magicVoidArrTypeInfo);
|
|
std::vector<TypeInfo*> magicVoidTypeInfoArr;
|
|
magicVoidTypeInfoArr.push_back(magicVoidTypeInfo);
|
|
magicVoidArrTypeInfo->setContainedTypes(magicVoidTypeInfoArr);
|
|
magicPassLog(">>>> Number of types found: " << globalTypeInfos.size());
|
|
for(i=0;i<functionTypes.size();i++) {
|
|
TypeInfo sourceTypeInfo(functionTypes[i]);
|
|
sourceTypeInfo.addParent(functionTypeParents[i]);
|
|
fillTypeInfos(sourceTypeInfo, globalTypeInfos);
|
|
}
|
|
magicPassLog(">>>> Number of types + function types found: " << globalTypeInfos.size());
|
|
|
|
//add external function types
|
|
for(i=0;i<externalFunctionTypes.size();i++) {
|
|
TypeInfo sourceTypeInfo(externalFunctionTypes[i]);
|
|
sourceTypeInfo.addParent(externalFunctionTypeParents[i]);
|
|
fillTypeInfos(sourceTypeInfo, globalTypeInfos);
|
|
}
|
|
magicPassLog(">>>> Number of types + function types + external function types found: " << globalTypeInfos.size());
|
|
|
|
//add external variable types
|
|
for(i=0;i<externalTypes.size();i++) {
|
|
TypeInfo* aTypeInfo = fillExternalTypeInfos(externalTypes[i], externalTypeParents[i], globalTypeInfos);
|
|
if(aTypeInfo == NULL) {
|
|
magicPassErr("var is: " << externalTypeParents[i]->getName());
|
|
magicPassErr("type is: " << TypeUtil::getDescription(externalTypes[i], MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
|
|
}
|
|
assert(aTypeInfo != NULL && "External type not supported!");
|
|
}
|
|
magicPassLog(">>>> Number of types + external types + function types + external function types found: " << globalTypeInfos.size());
|
|
|
|
//process types, split them when some parent has a valid value set
|
|
std::vector<TypeInfo*> splitTypeInfos;
|
|
for(i=0;i<globalTypeInfos.size();i++) {
|
|
bool isTypeInfoSplit = globalTypeInfos[i]->splitByParentValueSet(splitTypeInfos, globalVariablesWithAddressTaken);
|
|
if(isTypeInfoSplit) {
|
|
#if DEBUG_VALUE_SET
|
|
unsigned splitTypeInfosSize = splitTypeInfos.size();
|
|
errs() << "MagicPass: Found type info split with different parents and value sets: original type is: " << globalTypeInfos[i]->getDescription() << ", type splits are:\n";
|
|
for(unsigned j=splitTypeInfosSize;j<splitTypeInfos.size();j++) {
|
|
errs() << " - value set is: [ ";
|
|
std::vector<int> valueSet = splitTypeInfos[j]->getValueSet();
|
|
for(unsigned k=1;k<valueSet.size();k++) {
|
|
errs() << (k==1 ? "" : ", ") << valueSet[k];
|
|
}
|
|
errs() << " ], parents are: [ ";
|
|
std::vector<GlobalValue*> parents = splitTypeInfos[j]->getParents();
|
|
for(unsigned k=0;k<parents.size();k++) {
|
|
errs() << (k==0 ? "" : ", ") << parents[k]->getName();
|
|
}
|
|
errs() << " ]\n";
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//index type parents
|
|
globalTypeInfos.clear();
|
|
for(i=0;i<splitTypeInfos.size();i++) {
|
|
TypeInfo *aTypeInfo = splitTypeInfos[i];
|
|
std::vector<GlobalValue*> parents = aTypeInfo->getParents();
|
|
for(unsigned j=0;j<parents.size();j++) {
|
|
parentMapIt = globalParentMap.find(parents[j]);
|
|
assert(parentMapIt == globalParentMap.end());
|
|
globalParentMap.insert(std::pair<GlobalValue*, TypeInfo*>(parents[j], aTypeInfo));
|
|
}
|
|
globalTypeInfos.push_back(aTypeInfo);
|
|
}
|
|
|
|
std::vector< TypeInfo* > magicDsindexTypeInfoList;
|
|
std::vector< std::pair<std::string,std::string> > magicDsindexNamesList;
|
|
std::vector<int> magicDsindexFlagsList;
|
|
|
|
#if MAGIC_INSTRUMENT_MEM_FUNCS
|
|
//gather magic memory function calls to replace and figure out the type (adding more (local) types if needed)
|
|
std::vector<MagicMemFunction> magicMemFunctionCalls;
|
|
std::map< std::pair<std::string,std::string>, int> namesMap;
|
|
int allocFlags;
|
|
std::set<Function*> extendedMagicMemFunctions;
|
|
for (std::set<Function*>::iterator it = originalMagicMemFunctions.begin(); it != originalMagicMemFunctions.end(); ++it) {
|
|
PassUtil::getFunctionsInDirectBUCallgraph(*it, extendedMagicMemFunctions);
|
|
}
|
|
while(!magicMemFunctions.empty()) {
|
|
MagicMemFunction magicMemFunction = magicMemFunctions.front();
|
|
magicMemFunctions.erase(magicMemFunctions.begin());
|
|
std::vector<User*> Users(magicMemFunction.getFunction()->use_begin(), magicMemFunction.getFunction()->use_end());
|
|
std::vector<Value*> EqPointers;
|
|
while (!Users.empty()) {
|
|
int annotation;
|
|
User *U = Users.back();
|
|
Users.pop_back();
|
|
|
|
if (Instruction *I = dyn_cast<Instruction>(U)) {
|
|
Function *parent = I->getParent()->getParent();
|
|
if (isMagicFunction(M, parent) || MagicMemFunction::isCustomWrapper(parent)) {
|
|
continue;
|
|
}
|
|
CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
|
|
if (CS.getInstruction() &&
|
|
(!CS.arg_empty() || magicMemFunction.getWrapper() == NULL) &&
|
|
(MagicUtil::getCalledFunctionFromCS(CS) == magicMemFunction.getFunction() ||
|
|
std::find(EqPointers.begin(), EqPointers.end(),
|
|
CS.getCalledValue()) != EqPointers.end())) {
|
|
bool isDeallocFunction = magicMemFunction.isDeallocFunction();
|
|
bool wrapParent = false;
|
|
TypeInfo *typeInfo = magicVoidTypeInfo;
|
|
std::string allocName = "";
|
|
std::string allocParentName = "";
|
|
//check if we have to skip
|
|
if(extendedMagicMemFunctions.find(CS.getInstruction()->getParent()->getParent()) != extendedMagicMemFunctions.end()) {
|
|
//this call site is only called from some predefined mem function. skip.
|
|
continue;
|
|
}
|
|
if(sbrkFunctions.find(MagicUtil::getCalledFunctionFromCS(CS)) != sbrkFunctions.end()) {
|
|
ConstantInt *arg = dyn_cast<ConstantInt>(CS.getArgument(0));
|
|
if(arg && arg->getZExtValue() == 0) {
|
|
//ignore sbrk(0) calls. This does not skip calls with a variable argument (when arg == NULL)
|
|
#if DEBUG_ALLOC_LEVEL >= 1
|
|
magicPassErr("Skipping instrumentation of sbrk(0) MM call found in " << parent->getName() << "():");
|
|
I->print(errs());
|
|
errs() << "\n";
|
|
#endif
|
|
continue;
|
|
}
|
|
}
|
|
else if(MagicUtil::getCallAnnotation(M, CS, &annotation)
|
|
&& annotation == MAGIC_CALL_MEM_SKIP_INSTRUMENTATION) {
|
|
//ignore calls we are supposed to skip
|
|
#if DEBUG_ALLOC_LEVEL >= 1
|
|
magicPassErr("Skipping instrumentation of annotated MM call found in " << parent->getName() << "():");
|
|
I->print(errs());
|
|
errs() << "\n";
|
|
#endif
|
|
continue;
|
|
}
|
|
//figure out the type and the names
|
|
if(!isDeallocFunction) {
|
|
int allocCounter = 1;
|
|
int ret;
|
|
std::map< std::pair<std::string,std::string>, int>::iterator namesMapIt;
|
|
//get alloc types and names
|
|
TypeInfo *allocTypeInfo = getAllocTypeInfo(M, magicVoidPtrTypeInfo, CS, allocName, allocParentName);
|
|
#if !MAGIC_INSTRUMENT_MEM_CUSTOM_WRAPPERS
|
|
if(!allocTypeInfo) {
|
|
allocTypeInfo = voidTypeInfo;
|
|
}
|
|
#endif
|
|
if(allocTypeInfo) {
|
|
typeInfo = allocTypeInfo;
|
|
}
|
|
else {
|
|
int pointerParam = MagicMemFunction::getMemFunctionPointerParam(I->getParent()->getParent(), brkFunctions, magicVoidPtrTypeInfo);
|
|
if(pointerParam >= 0 /* && !I->getParent()->getParent()->hasAddressTaken() */) {
|
|
//the parent is a valid magic mem function to wrap
|
|
wrapParent = true;
|
|
}
|
|
}
|
|
if(!wrapParent) {
|
|
assert(allocParentName.compare("") && "Empty parent name!");
|
|
if(!allocName.compare("")) {
|
|
allocName = MAGIC_ALLOC_NONAME;
|
|
}
|
|
|
|
#if (MAGIC_NAMED_ALLOC_USE_DBG_INFO || (MAGIC_MEM_USAGE_OUTPUT_CTL == 1))
|
|
//extend names with debug information when requested
|
|
if (MDNode *N = I->getMetadata("dbg")) {
|
|
DILocation Loc(N);
|
|
std::string string;
|
|
raw_string_ostream ostream(string);
|
|
ostream << allocName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
|
|
ostream.flush();
|
|
allocName = string;
|
|
}
|
|
#endif
|
|
|
|
#if MAGIC_FORCE_ALLOC_EXT_NAMES
|
|
if (isExtLibrary(parent, NULL)) {
|
|
allocName = MAGIC_ALLOC_EXT_NAME;
|
|
allocName = MAGIC_ALLOC_EXT_PARENT_NAME;
|
|
}
|
|
#endif
|
|
|
|
//avoid duplicates
|
|
namesMapIt = namesMap.find(std::pair<std::string, std::string>(allocParentName, allocName));
|
|
if(namesMapIt != namesMap.end()) {
|
|
allocCounter = namesMapIt->second + 1;
|
|
ret = namesMap.erase(std::pair<std::string, std::string>(allocParentName, allocName));
|
|
assert(ret == 1);
|
|
namesMap.insert(std::pair<std::pair<std::string, std::string>, int>(std::pair<std::string, std::string>(allocParentName, allocName), allocCounter));
|
|
std::string string;
|
|
raw_string_ostream ostream(string);
|
|
ostream << allocName << MAGIC_ALLOC_NAME_SUFFIX << allocCounter;
|
|
ostream.flush();
|
|
allocName = string;
|
|
}
|
|
else {
|
|
namesMap.insert(std::pair<std::pair<std::string, std::string>, int>(std::pair<std::string, std::string>(allocParentName, allocName), allocCounter));
|
|
allocName += MAGIC_ALLOC_NAME_SUFFIX;
|
|
}
|
|
magicMemFunction.setInstructionTypeInfo(typeInfo, allocName, allocParentName);
|
|
//add dsindex entries
|
|
magicDsindexTypeInfoList.push_back(typeInfo);
|
|
magicDsindexNamesList.push_back(std::pair<std::string, std::string>(allocParentName, allocName));
|
|
allocFlags = magicMemFunction.getAllocFlags();
|
|
assert(allocFlags);
|
|
magicDsindexFlagsList.push_back(allocFlags);
|
|
}
|
|
}
|
|
magicMemFunction.setInstruction(I);
|
|
Function *instructionParent = I->getParent()->getParent();
|
|
//see if we can find the parent in our lists
|
|
MagicMemFunction *magicMemParent = NULL;
|
|
for(unsigned k=0;k<magicMemFunctions.size();k++) {
|
|
if(magicMemFunctions[k].getFunction() == instructionParent) {
|
|
magicMemParent = &magicMemFunctions[k];
|
|
break;
|
|
}
|
|
}
|
|
if(!magicMemParent) {
|
|
for(unsigned k=0;k<magicMemFunctionCalls.size();k++) {
|
|
if(magicMemFunctionCalls[k].getFunction() == instructionParent) {
|
|
magicMemParent = &magicMemFunctionCalls[k];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(!magicMemParent && wrapParent) {
|
|
//if there is no existing parent but we have to wrap the parent, create a parent now and add it to the function queue
|
|
MagicMemFunction newMagicMemFunction(M, instructionParent, NULL, false, 0);
|
|
magicMemFunctions.push_back(newMagicMemFunction);
|
|
magicMemParent = &magicMemFunctions[magicMemFunctions.size()-1];
|
|
}
|
|
if(magicMemParent) {
|
|
//if we have a parent, add a dependency
|
|
magicMemParent->addInstructionDep(magicMemFunction);
|
|
assert(magicMemParent->getAllocFlags());
|
|
|
|
}
|
|
else {
|
|
//if there is no parent, add it to the call queue
|
|
magicMemFunctionCalls.push_back(magicMemFunction);
|
|
}
|
|
}
|
|
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(U)) {
|
|
Users.insert(Users.end(), GV->use_begin(), GV->use_end());
|
|
EqPointers.push_back(GV);
|
|
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
|
|
if (CE->isCast()) {
|
|
Users.insert(Users.end(), CE->use_begin(), CE->use_end());
|
|
EqPointers.push_back(CE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if MAGIC_INSTRUMENT_STACK
|
|
std::vector<std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > > localTypeInfoMaps;
|
|
std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap;
|
|
std::vector<Function*> stackIntrumentedFuncs;
|
|
fillStackInstrumentedFunctions(stackIntrumentedFuncs, deepestLLFunction);
|
|
std::string stackIntrumentedFuncsStr;
|
|
for(i=0;i<stackIntrumentedFuncs.size();i++) {
|
|
localTypeInfoMap.clear();
|
|
indexLocalTypeInfos(M, stackIntrumentedFuncs[i], localTypeInfoMap);
|
|
localTypeInfoMaps.push_back(localTypeInfoMap);
|
|
stackIntrumentedFuncsStr += (i==0 ? "" : ", ") + stackIntrumentedFuncs[i]->getName().str() + "()";
|
|
}
|
|
magicPassLog(">>>> Set of stack-instrumented functions expanded from function " << deepestLLFunction->getName() << "(): " << stackIntrumentedFuncsStr);
|
|
magicPassLog(">>>> Number of types + external types + function types + external function types + local types found: " << globalTypeInfos.size());
|
|
#endif
|
|
|
|
//add raw types
|
|
std::vector<TypeInfo*> rawTypeInfos;
|
|
for(i=0;i<globalTypeInfos.size();i++) {
|
|
TypeInfo* aTypeInfo = globalTypeInfos[i];
|
|
if(!aTypeInfo->hasRawTypeRepresentation()) {
|
|
continue;
|
|
}
|
|
assert(aTypeInfo->getNumContainedTypes() == 0);
|
|
TypeInfo* aRawTypeInfo = new TypeInfo(*magicVoidArrTypeInfo);
|
|
aRawTypeInfo->setPersistent();
|
|
aRawTypeInfo->removeAllParents();
|
|
rawTypeInfos.push_back(aRawTypeInfo);
|
|
std::vector<TypeInfo*> aTypeInfoContainedTypes;
|
|
aTypeInfoContainedTypes.push_back(aRawTypeInfo);
|
|
aTypeInfo->setContainedTypes(aTypeInfoContainedTypes);
|
|
assert(aTypeInfo->getContainedType(0)->getContainedType(0) == magicVoidTypeInfo);
|
|
}
|
|
for(i=0;i<rawTypeInfos.size();i++) {
|
|
globalTypeInfos.push_back(rawTypeInfos[i]);
|
|
assert(rawTypeInfos[i]->getNumContainedTypes() == 1);
|
|
}
|
|
magicPassLog(">>>> Number of types + external types + function types + external function types + local types found + raw types: " << globalTypeInfos.size());
|
|
|
|
//find max recursive sequence length
|
|
unsigned length, maxRecursiveSequenceLength = 0;
|
|
for(i=0;i<globalTypeInfos.size();i++) {
|
|
if(globalTypeInfos[i]->getParents().size() > 0) {
|
|
length = getMaxRecursiveSequenceLength(globalTypeInfos[i]);
|
|
if(length > maxRecursiveSequenceLength) {
|
|
maxRecursiveSequenceLength = length;
|
|
}
|
|
}
|
|
}
|
|
magicPassLog(">>>> Max recursive sequence length: " << maxRecursiveSequenceLength);
|
|
|
|
//debug type infos when needed
|
|
#if DEBUG_TYPE_INFOS
|
|
for(i=0;i<globalTypeInfos.size();i++) {
|
|
std::vector<GlobalValue*> parents = globalTypeInfos[i]->getParents();
|
|
if(parents.size() > 0) {
|
|
std::string parentString, typeString;
|
|
for(unsigned j=0;j<parents.size();j++) {
|
|
parentString.append((j>0 ? ", " : "") + parents[j]->getName().str());
|
|
}
|
|
typeString = globalTypeInfos[i]->getDescription();
|
|
magicPassErr(" Global type group found, parents=( " << parentString << "), type=" << typeString << ", name=" << globalTypeInfos[i]->getName() << ", names_string=" << globalTypeInfos[i]->getNamesString());
|
|
if(DEBUG_TYPE_INFOS >= 2) {
|
|
printInterestingTypes(globalTypeInfos[i]);
|
|
}
|
|
}
|
|
}
|
|
for(i=0;i<globalTypeInfos.size();i++) {
|
|
std::string name = globalTypeInfos[i]->getName();
|
|
if(name.compare("")) {
|
|
magicPassErr(" Named type found: " << name << " (names string: " << globalTypeInfos[i]->getNamesString() << ", id: " << i << ")");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if DEBUG_DUPLICATED_TYPE_INFOS
|
|
std::map<std::string, TypeInfo*> duplicatedTypeInfoMap;
|
|
std::map<std::string, TypeInfo*>::iterator duplicatedTypeInfoMapIt;
|
|
for(i=0;i<globalTypeInfos.size();i++) {
|
|
if(globalTypeInfos[i]->getType()->isStructTy()) {
|
|
std::string name = globalTypeInfos[i]->getName();
|
|
if(!name.compare("")) {
|
|
continue;
|
|
}
|
|
duplicatedTypeInfoMapIt = duplicatedTypeInfoMap.find(name);
|
|
if(duplicatedTypeInfoMapIt != duplicatedTypeInfoMap.end()) {
|
|
magicPassErr("Duplicated struct name found: " << name << ": " << globalTypeInfos[i]->getVerboseDescription() << " != " << (duplicatedTypeInfoMapIt->second)->getVerboseDescription());
|
|
}
|
|
else {
|
|
duplicatedTypeInfoMap.insert(std::pair<std::string, TypeInfo*>(name, globalTypeInfos[i]));
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//allocate magic type array
|
|
ArrayType* magicTypeArrayType = ArrayType::get(magicTypeStructType, globalTypeInfos.size());
|
|
magicTypeArray = new GlobalVariable(M, magicTypeArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicTypeArrayType), MAGIC_TYPE_ARRAY_NAME);
|
|
MagicUtil::setGlobalVariableSection(magicTypeArray, MAGIC_STATIC_VARS_SECTION_DATA);
|
|
|
|
//allocate magic array
|
|
ArrayType* magicArrayType = ArrayType::get(magicStructType, globalVariables.size());
|
|
magicArray = new GlobalVariable(M, magicArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicArrayType), MAGIC_ARRAY_NAME);
|
|
MagicUtil::setGlobalVariableSection(magicArray, MAGIC_STATIC_VARS_SECTION_DATA);
|
|
|
|
//allocate magic function array
|
|
ArrayType* magicFunctionArrayType = ArrayType::get(magicFunctionStructType, functions.size());
|
|
magicFunctionArray = new GlobalVariable(M, magicFunctionArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicFunctionArrayType), MAGIC_FUNC_ARRAY_NAME);
|
|
MagicUtil::setGlobalVariableSection(magicFunctionArray, MAGIC_STATIC_VARS_SECTION_DATA);
|
|
|
|
//build magic type array in build function
|
|
i=0;
|
|
std::map<TypeInfo*, Constant*> magicArrayTypePtrMap;
|
|
std::map<TypeInfo*, Constant*>::iterator magicArrayTypePtrMapIt;
|
|
std::map<TypeInfo*, unsigned> magicArrayTypeIndexMap;
|
|
std::map<TypeInfo*, unsigned>::iterator magicArrayTypeIndexMapIt;
|
|
std::vector<Value*> arrayIndexes;
|
|
for(;i<globalTypeInfos.size();i++) {
|
|
TypeInfo* aTypeInfo = globalTypeInfos[i];
|
|
TYPECONST Type *aType = aTypeInfo->getType();
|
|
arrayIndexes.clear();
|
|
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
|
|
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, i, 10))); //pointer to A[index]
|
|
Constant* magicTypeArrayPtr = MagicUtil::getGetElementPtrConstant(magicTypeArray, arrayIndexes);
|
|
magicArrayTypePtrMap.insert(std::pair<TypeInfo*, Constant*>(aTypeInfo, magicTypeArrayPtr));
|
|
magicArrayTypeIndexMap.insert(std::pair<TypeInfo*, unsigned>(aTypeInfo, i));
|
|
|
|
//storing id field
|
|
Value* structIdField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_ID);
|
|
Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
|
|
new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing name field
|
|
Value* structNameField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAME);
|
|
Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getName()));
|
|
new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing names field
|
|
std::vector<std::string> names = aTypeInfo->getNames();
|
|
Value* structNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAMES);
|
|
Constant* namesValue;
|
|
if(names.size() > 0) {
|
|
namesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, names.size(), &names));
|
|
}
|
|
else {
|
|
namesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structNamesField->getType())->getElementType());
|
|
}
|
|
new StoreInst(namesValue, structNamesField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing num_names field
|
|
Value* structNumNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_NAMES);
|
|
Constant* numNamesValue = ConstantInt::get(M.getContext(), APInt(32, names.size(), 10));
|
|
new StoreInst(numNamesValue, structNumNamesField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing type_str field
|
|
Value* structTypeStrField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_STR);
|
|
Constant* typeStrValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getTypeString()));
|
|
new StoreInst(typeStrValue, structTypeStrField, false, magicArrayBuildFuncInst);
|
|
|
|
//filling size field
|
|
Value* structSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
|
|
Value* typeSizeValue;
|
|
if(aType->isFunctionTy() || TypeUtil::isOpaqueTy(aType) || aType->isVoidTy()) {
|
|
typeSizeValue = ConstantInt::get(M.getContext(), APInt(32, 1, 10));
|
|
}
|
|
else {
|
|
assert(aType->isSized());
|
|
typeSizeValue = ConstantExpr::getIntegerCast(ConstantExpr::getSizeOf(aType), (TYPECONST IntegerType*)((TYPECONST PointerType*)structSizeField->getType())->getElementType(), true);
|
|
}
|
|
new StoreInst(typeSizeValue, structSizeField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing num_child_types field
|
|
Value* structNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES);
|
|
Constant* numChildTypesValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getNumChildTypes(), 10));
|
|
new StoreInst(numChildTypesValue, structNumChildTypesField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing member_names field
|
|
std::vector<std::string> memberNames = aTypeInfo->getMemberNames();
|
|
Value* structMemberNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_NAMES);
|
|
Constant* memberNamesValue;
|
|
if(memberNames.size() > 0) {
|
|
assert(aType->isStructTy());
|
|
assert(aTypeInfo->getNumContainedTypes() == memberNames.size());
|
|
memberNamesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, memberNames.size(), &memberNames));
|
|
}
|
|
else {
|
|
memberNamesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberNamesField->getType())->getElementType());
|
|
}
|
|
new StoreInst(memberNamesValue, structMemberNamesField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing member_offsets field
|
|
Value* structMemberOffsetsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS);
|
|
Constant* memberOffsetsValue;
|
|
if(memberNames.size() > 0) {
|
|
assert(aType->isStructTy());
|
|
assert(aTypeInfo->getNumContainedTypes() == aTypeInfo->getNumChildTypes());
|
|
bool isConstant = false;
|
|
GlobalVariable *memberOffsetArray = MagicUtil::getIntArrayRef(M, aTypeInfo->getNumChildTypes(), NULL, isConstant);
|
|
for(unsigned j=0;j<aTypeInfo->getNumChildTypes();j++) {
|
|
std::vector<Value*> arrayIndexes;
|
|
arrayIndexes.clear();
|
|
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
|
|
arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, j, 10))); //pointer to A[j]
|
|
Constant* memberOffsetArrayPtr = MagicUtil::getGetElementPtrConstant(memberOffsetArray, arrayIndexes);
|
|
|
|
Value* memberOffsetValue = ConstantExpr::getIntegerCast(ConstantExpr::getOffsetOf((TYPECONST StructType*) aTypeInfo->getType(), j), (TYPECONST IntegerType*)((TYPECONST PointerType*)memberOffsetArrayPtr->getType())->getElementType(), true);
|
|
new StoreInst(memberOffsetValue, memberOffsetArrayPtr, false, magicArrayBuildFuncInst);
|
|
}
|
|
memberOffsetsValue = MagicUtil::getArrayPtr(M, memberOffsetArray);
|
|
}
|
|
else {
|
|
memberOffsetsValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberOffsetsField->getType())->getElementType());
|
|
}
|
|
new StoreInst(memberOffsetsValue, structMemberOffsetsField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing value set field (for enum values and value set analysis)
|
|
std::vector<int> valueSet = aTypeInfo->getValueSet();
|
|
Value* structValueSetField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_VALUE_SET);
|
|
Constant* valueSetValue;
|
|
if(valueSet.size() > 0) {
|
|
valueSetValue = ConstantExpr::getCast(Instruction::BitCast, MagicUtil::getArrayPtr(M, MagicUtil::getIntArrayRef(M, valueSet.size(), &valueSet)), magicVoidPtrTypeInfo->getType());
|
|
}
|
|
else {
|
|
valueSetValue = ConstantPointerNull::get((TYPECONST PointerType*)magicVoidPtrTypeInfo->getType());
|
|
}
|
|
new StoreInst(valueSetValue, structValueSetField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing type_id field
|
|
Value* structTypeIDField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_ID);
|
|
Constant* typeIDValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getTypeID(), 10));
|
|
new StoreInst(typeIDValue, structTypeIDField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing flags field
|
|
Value* structFlagsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_FLAGS);
|
|
Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getFlags(), 10));
|
|
new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing bit_width field
|
|
Value* structBitWidthField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_BIT_WIDTH);
|
|
Constant* bitWidthValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getBitWidth(), 10));
|
|
new StoreInst(bitWidthValue, structBitWidthField, false, magicArrayBuildFuncInst);
|
|
}
|
|
|
|
i=0;
|
|
//build contained types pointers
|
|
unsigned dstIndex, voidTypeIndex;
|
|
magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(magicVoidTypeInfo);
|
|
assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end());
|
|
voidTypeIndex = magicArrayTypeIndexMapIt->second;
|
|
for(;i<globalTypeInfos.size();i++) {
|
|
TypeInfo* aTypeInfo = globalTypeInfos[i];
|
|
std::vector<Constant*> containedTypePtrs;
|
|
for(unsigned j=0;j<aTypeInfo->getNumContainedTypes();j++) {
|
|
TypeInfo* containedType = aTypeInfo->getContainedType(j);
|
|
magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(containedType);
|
|
assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
|
|
|
|
containedTypePtrs.push_back(magicArrayTypePtrMapIt->second);
|
|
}
|
|
Value* structContainedTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES);
|
|
Constant *containedTypesValue;
|
|
if(containedTypePtrs.size() > 0) {
|
|
containedTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, containedTypePtrs));
|
|
}
|
|
else {
|
|
containedTypesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structContainedTypesField->getType())->getElementType());
|
|
}
|
|
new StoreInst(containedTypesValue, structContainedTypesField, false, magicArrayBuildFuncInst);
|
|
if(!aTypeInfo->hasRawTypeRepresentation()) {
|
|
continue;
|
|
}
|
|
|
|
//handle raw array types
|
|
assert(aTypeInfo->getNumContainedTypes() == 1 && aTypeInfo->getContainedType(0)->getType()->isArrayTy());
|
|
magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(aTypeInfo->getContainedType(0));
|
|
assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end());
|
|
dstIndex = magicArrayTypeIndexMapIt->second;
|
|
|
|
//fix size field (inherited by parent type)
|
|
Value* srcStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
|
|
Value* dstStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
|
|
Value* srcStructSizeValue = new LoadInst(srcStructSizeField, "", false, magicArrayBuildFuncInst);
|
|
new StoreInst(srcStructSizeValue, dstStructSizeField, false, magicArrayBuildFuncInst);
|
|
|
|
//fix num_child_types field
|
|
Value* dstStructNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES);
|
|
Value* voidStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, voidTypeIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
|
|
Value* voidStructSizeValue = new LoadInst(voidStructSizeField, "", false, magicArrayBuildFuncInst);
|
|
BinaryOperator* numChildTypesValue = BinaryOperator::Create(Instruction::SDiv, srcStructSizeValue, voidStructSizeValue, "", magicArrayBuildFuncInst);
|
|
new StoreInst(numChildTypesValue, dstStructNumChildTypesField, false, magicArrayBuildFuncInst);
|
|
}
|
|
|
|
i=0;
|
|
//build cast types pointers
|
|
for(;i<globalTypeInfos.size();i++) {
|
|
TypeInfo* aTypeInfo = globalTypeInfos[i];
|
|
std::vector<Constant*> castTypePtrs;
|
|
std::vector<TypeInfo*> castTypes = aTypeInfo->getCastTypes();
|
|
|
|
Value* structCompatibleTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES);
|
|
TYPECONST PointerType* nullArrayType = (TYPECONST PointerType*) ((TYPECONST PointerType*)structCompatibleTypesField->getType())->getElementType();
|
|
for(unsigned j=0;j<castTypes.size();j++) {
|
|
TypeInfo* castType = castTypes[j];
|
|
if(castType == NULL) {
|
|
castTypePtrs.push_back(ConstantPointerNull::get((TYPECONST PointerType*) nullArrayType->getContainedType(0)));
|
|
}
|
|
else {
|
|
magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(castType);
|
|
assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
|
|
|
|
castTypePtrs.push_back(magicArrayTypePtrMapIt->second);
|
|
}
|
|
}
|
|
|
|
Constant *compatibleTypesValue;
|
|
if(castTypePtrs.size() > 0) {
|
|
compatibleTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, castTypePtrs));
|
|
}
|
|
else {
|
|
compatibleTypesValue = ConstantPointerNull::get(nullArrayType);
|
|
}
|
|
new StoreInst(compatibleTypesValue, structCompatibleTypesField, false, magicArrayBuildFuncInst);
|
|
}
|
|
|
|
//build magic array in build function
|
|
i=0;
|
|
strGlobalVariables = 0;
|
|
PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
|
|
for(;i<globalVariables.size();i++) {
|
|
GlobalVariable *GV = globalVariables[i];
|
|
DIGlobalVariable *DIGV = NULL;
|
|
StringRef GVName;
|
|
bool isFromLibrary, hasAddressTaken, isString, isNamedString;
|
|
isString = GV->getName().startswith(".str");
|
|
isNamedString = false;
|
|
if(isString) {
|
|
stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(GV);
|
|
if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) {
|
|
isNamedString = true;
|
|
DIGV = NULL;
|
|
GVName = ".str#" + stringOwnerInvertedMapIt->second;
|
|
}
|
|
}
|
|
if(!isNamedString) {
|
|
GVName = MagicUtil::getGVSourceName(M, GV, &DIGV, baseBuildDir);
|
|
}
|
|
isFromLibrary = isExtLibrary(GV, DIGV);
|
|
hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end();
|
|
std::string GVNameStr(GVName.str());
|
|
|
|
//storing id field
|
|
Value* structIdField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ID);
|
|
Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
|
|
new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing name field
|
|
Value* structNameField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_NAME);
|
|
Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, GVNameStr));
|
|
new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing type field
|
|
parentMapIt = globalParentMap.find(GV);
|
|
if(parentMapIt == globalParentMap.end()) {
|
|
continue;
|
|
}
|
|
assert(parentMapIt != globalParentMap.end());
|
|
TypeInfo* aTypeInfo = parentMapIt->second;
|
|
magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
|
|
assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
|
|
Value* structTypeField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_TYPE);
|
|
Constant* typeValue = magicArrayTypePtrMapIt->second;
|
|
new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
|
|
|
|
//filling flags field
|
|
int annotation, flags = MAGIC_STATE_DATA;
|
|
if(GV->hasExternalLinkage() || GV->hasExternalWeakLinkage()) {
|
|
flags |= MAGIC_STATE_EXTERNAL;
|
|
}
|
|
if(GV->isConstant()) {
|
|
flags |= MAGIC_STATE_CONSTANT;
|
|
}
|
|
if(GV->isThreadLocal()) {
|
|
flags |= MAGIC_STATE_THREAD_LOCAL;
|
|
}
|
|
if(isFromLibrary) {
|
|
flags |= MAGIC_STATE_LIB;
|
|
}
|
|
if(!hasAddressTaken) {
|
|
flags |= MAGIC_STATE_ADDR_NOT_TAKEN;
|
|
}
|
|
if(isString) {
|
|
flags |= MAGIC_STATE_STRING;
|
|
if(isNamedString) {
|
|
flags |= MAGIC_STATE_NAMED_STRING;
|
|
}
|
|
strGlobalVariables++;
|
|
}
|
|
if(MagicUtil::getVarAnnotation(M, GV, &annotation)) {
|
|
magicPassLog("Magic annotation found for global variable: " << GV->getName());
|
|
flags |= (annotation & MAGIC_STATE_ANNOTATION_MASK);
|
|
}
|
|
Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_FLAGS);
|
|
Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10));
|
|
new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
|
|
|
|
//filling address field
|
|
Value* structAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ADDRESS);
|
|
Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType);
|
|
new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst);
|
|
|
|
//filling shadow address field
|
|
Value* structShadowAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS);
|
|
Constant* varShadowAddressValue;
|
|
if(EnableShadowing && !GV->isConstant()) {
|
|
GlobalVariable* varShadow = MagicUtil::getShadowRef(M, GV);
|
|
shadowGlobalVariables.push_back(varShadow);
|
|
varShadowAddressValue = ConstantExpr::getCast(Instruction::BitCast, varShadow, voidPointerType);
|
|
}
|
|
else {
|
|
varShadowAddressValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structShadowAddressField->getType())->getElementType());
|
|
}
|
|
new StoreInst(varShadowAddressValue, structShadowAddressField, false, magicArrayBuildFuncInst);
|
|
}
|
|
|
|
//build magic function array in build function
|
|
i=0;
|
|
for(;i<functions.size();i++) {
|
|
Function *F = functions[i];
|
|
DISubprogram *DIS = NULL;
|
|
StringRef FName = MagicUtil::getFunctionSourceName(M, F, &DIS, baseBuildDir);
|
|
std::string FNameStr(FName.str());
|
|
bool isFromLibrary = isExtLibrary(F, DIS);
|
|
|
|
//storing id field
|
|
Value* structIdField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_ID);
|
|
Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
|
|
new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing name field
|
|
Value* structNameField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_NAME);
|
|
Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, FNameStr));
|
|
new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing type field
|
|
parentMapIt = globalParentMap.find(F);
|
|
assert(parentMapIt != globalParentMap.end());
|
|
TypeInfo* aTypeInfo = parentMapIt->second;
|
|
magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
|
|
assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
|
|
Value* structTypeField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_TYPE);
|
|
Constant* typeValue = magicArrayTypePtrMapIt->second;
|
|
new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
|
|
|
|
//filling flags field
|
|
int flags = MAGIC_STATE_TEXT|MAGIC_STATE_CONSTANT;
|
|
if(isFromLibrary) {
|
|
flags |= MAGIC_STATE_LIB;
|
|
}
|
|
if(!F->hasAddressTaken()) {
|
|
flags |= MAGIC_STATE_ADDR_NOT_TAKEN;
|
|
}
|
|
Value* structFlagsField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_FLAGS);
|
|
Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10));
|
|
new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
|
|
|
|
//filling address field
|
|
Value* structAddressField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_ADDRESS);
|
|
Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, F, voidPointerType);
|
|
new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst);
|
|
}
|
|
|
|
#if MAGIC_INSTRUMENT_MEM_FUNCS
|
|
//replace magic memory function calls with their wrappers
|
|
for(i=0;i<magicMemFunctionCalls.size();i++) {
|
|
MagicMemFunction *magicMemFunctionCall = &magicMemFunctionCalls[i];
|
|
magicMemFunctionCall->replaceInstruction(magicArrayTypePtrMap, magicVoidPtrTypeInfo);
|
|
}
|
|
|
|
//fix debug function calls and their arguments
|
|
for (i=0;i<magicDebugFunctions.size();i++) {
|
|
MagicDebugFunction *magicDebugFunction = &magicDebugFunctions[i];
|
|
magicDebugFunction->fixCalls(M, baseBuildDir);
|
|
}
|
|
|
|
//fix mmap ctl function calls and their arguments
|
|
for (i=0;i<magicMmapCtlFunctions.size();i++) {
|
|
MagicMmapCtlFunction *magicMmapCtlFunction = &magicMmapCtlFunctions[i];
|
|
magicMmapCtlFunction->fixCalls(M, magicGetPageSizeFunc);
|
|
}
|
|
#endif
|
|
|
|
#if MAGIC_INSTRUMENT_STACK
|
|
//instrument the stack for the relevant set of functions and add dsindex entries
|
|
for(i=0;i<stackIntrumentedFuncs.size();i++) {
|
|
addMagicStackDsentryFuncCalls(M, stackIntrumentedFuncs[i], stackIntrumentedFuncs[i], magicStackDsentryCreateFunc, magicStackDsentryDestroyFunc,
|
|
magicDsentryStructType, localTypeInfoMaps[i], magicArrayTypePtrMap, magicVoidPtrTypeInfo, magicDsindexTypeInfoList, magicDsindexNamesList, magicDsindexFlagsList);
|
|
}
|
|
#endif
|
|
|
|
//allocate magic dsindex array
|
|
ArrayType* magicDsindexArrayType = ArrayType::get(magicDsindexStructType, magicDsindexTypeInfoList.size());
|
|
magicDsindexArray = new GlobalVariable(M, magicDsindexArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicDsindexArrayType), MAGIC_DSINDEX_ARRAY_NAME);
|
|
MagicUtil::setGlobalVariableSection(magicDsindexArray, MAGIC_STATIC_VARS_SECTION_DATA);
|
|
|
|
//build magic dsindex array in build function
|
|
i=0;
|
|
for(;i<magicDsindexTypeInfoList.size();i++) {
|
|
//storing type field
|
|
TypeInfo* aTypeInfo = magicDsindexTypeInfoList[i];
|
|
magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
|
|
assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
|
|
Value* structTypeField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_TYPE);
|
|
Constant* typeValue = magicArrayTypePtrMapIt->second;
|
|
new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing name field
|
|
Value* structNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_NAME);
|
|
Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].second));
|
|
new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing parent name field
|
|
Value* structParentNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_PARENT_NAME);
|
|
Constant* parentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].first));
|
|
new StoreInst(parentNameValue, structParentNameField, false, magicArrayBuildFuncInst);
|
|
|
|
//storing flags field
|
|
Value* structFlagsField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_FLAGS);
|
|
Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, magicDsindexFlagsList[i], 10));
|
|
new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
|
|
}
|
|
|
|
// apply qprof instrumentation
|
|
qprofInstrumentationApply(M);
|
|
|
|
//set pointer to magic type array in build function
|
|
new StoreInst(MagicUtil::getArrayPtr(M, magicTypeArray), magicTypeArrayPtr, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic type array size in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size())), magicTypeArraySize, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic type next id in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size()+1)), magicTypeNextId, false, magicArrayBuildFuncInst);
|
|
|
|
//set pointer to magic array in build function
|
|
new StoreInst(MagicUtil::getArrayPtr(M, magicArray), magicArrayPtr, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic array size in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size())), magicArraySize, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic array string size in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, strGlobalVariables)), magicArrayStrSize, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic next id in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size()+1)), magicNextId, false, magicArrayBuildFuncInst);
|
|
|
|
//set pointer to magic function array in build function
|
|
new StoreInst(MagicUtil::getArrayPtr(M, magicFunctionArray), magicFunctionArrayPtr, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic function array size in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size())), magicFunctionArraySize, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic function next id in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size()+1)), magicFunctionNextId, false, magicArrayBuildFuncInst);
|
|
|
|
//set pointer to magic dsindex array in build function
|
|
new StoreInst(MagicUtil::getArrayPtr(M, magicDsindexArray), magicDsindexArrayPtr, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic dsindex array size in build function
|
|
new StoreInst(ConstantInt::get(M.getContext(), APInt(32, magicDsindexTypeInfoList.size())), magicDsindexArraySize, false, magicArrayBuildFuncInst);
|
|
|
|
//set magic void type pointer in build function
|
|
magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(magicVoidPtrTypeInfo);
|
|
assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
|
|
Constant* magicVoidPtrTypeValue = magicArrayTypePtrMapIt->second;
|
|
new StoreInst(magicVoidPtrTypeValue, magicVoidPtrTypePtr, false, magicArrayBuildFuncInst);
|
|
|
|
//inject magic init call at the beginning of magic entry point function
|
|
std::vector<Value*> args;
|
|
MagicUtil::createCallInstruction(magicInitFunc, args, "", magicEntryPointFunc->getBasicBlockList().begin()->begin());
|
|
|
|
//check invariants
|
|
#if MAGIC_CHECK_INVARIANTS
|
|
if(maxRecursiveSequenceLength > MAGIC_MAX_RECURSIVE_TYPES) {
|
|
magicPassErr("Max recursive sequence length is: " << maxRecursiveSequenceLength);
|
|
}
|
|
assert(maxRecursiveSequenceLength <= MAGIC_MAX_RECURSIVE_TYPES && "MAGIC_MAX_RECURSIVE_TYPES is too small!");
|
|
if(TypeInfo::getMaxNameLength() > MAGIC_MAX_NAME_LEN) {
|
|
magicPassErr("Max name length is: " << TypeInfo::getMaxNameLength());
|
|
}
|
|
assert(TypeInfo::getMaxNameLength() <= MAGIC_MAX_NAME_LEN && "MAGIC_MAX_NAME_LEN is too small!");
|
|
if(TypeInfo::getMaxTypeStringLength() > MAGIC_MAX_TYPE_STR_LEN) {
|
|
magicPassErr("Max type string length is: " << TypeInfo::getMaxTypeStringLength());
|
|
}
|
|
assert(TypeInfo::getMaxTypeStringLength() <= MAGIC_MAX_TYPE_STR_LEN && "MAGIC_MAX_TYPE_STR_LEN is too small!");
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Private methods
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
static std::vector<int> currPtrVarIndexes;
|
|
static std::set< std::pair<Value*,std::vector<int> > > visitedValues;
|
|
|
|
bool MagicPass::checkPointerVariableIndexes(TYPECONST Type *type, std::vector<int> &ptrVarIndexes, unsigned offset)
|
|
{
|
|
if(offset >= ptrVarIndexes.size()) {
|
|
return true;
|
|
}
|
|
unsigned ptrVarIndex = (unsigned) ptrVarIndexes[ptrVarIndexes.size()-1 - offset];
|
|
if(ptrVarIndex >= type->getNumContainedTypes()) {
|
|
return false;
|
|
}
|
|
return checkPointerVariableIndexes(type->getContainedType(ptrVarIndex), ptrVarIndexes, offset+1);
|
|
}
|
|
|
|
void MagicPass::findPointerVariables(Function* function, Value *value, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, Value *parent, bool isUser)
|
|
{
|
|
|
|
#define RETURN_IF(X) do{ if(X){ return; } } while(0)
|
|
#define DEBUG_VALUE(M, V) do{ if(DEBUG_ALLOC_LEVEL >= 2) { errs() << M; V->print(errs()); errs() << "\n"; } } while(0)
|
|
#define DEBUG_INDEXES() do{ if(DEBUG_ALLOC_LEVEL >= 3) { errs() << ">>> Indexes: "; for(unsigned i=0;i<currPtrVarIndexes.size();i++) errs() << currPtrVarIndexes[i] << " "; errs() << "\n"; } } while(0)
|
|
|
|
std::pair<Value*,std::vector<int> > visitedPair(value, currPtrVarIndexes);
|
|
if(visitedValues.find(visitedPair) != visitedValues.end()) {
|
|
return;
|
|
}
|
|
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Value is: ", value);
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Parent value is: ", parent);
|
|
DEBUG_INDEXES();
|
|
std::vector<int> savedPtrVarIndexes;
|
|
visitedValues.insert(visitedPair);
|
|
ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(value);
|
|
if(currPtrVarIndexes.size() == 0) {
|
|
if(DEBUG_ALLOC_LEVEL >= 2) {
|
|
magicPassErr("Empty indexes, skipping search path!");
|
|
}
|
|
RETURN_IF(true);
|
|
}
|
|
else if(GlobalVariable *GV = dyn_cast<GlobalVariable>(value)) {
|
|
if(DEBUG_ALLOC_LEVEL >= 2) {
|
|
magicPassErr("Found global variable!");
|
|
}
|
|
ptrVars.push_back(GV);
|
|
ptrVarIndexes.push_back(currPtrVarIndexes);
|
|
assert(!isUser);
|
|
if(GV->getType()->getElementType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) {
|
|
RETURN_IF(true);
|
|
}
|
|
}
|
|
else if(AllocaInst *AI = dyn_cast<AllocaInst>(value)) {
|
|
if(DEBUG_ALLOC_LEVEL >= 2) {
|
|
magicPassErr("Found local variable!");
|
|
}
|
|
ptrVars.push_back(AI);
|
|
ptrVarIndexes.push_back(currPtrVarIndexes);
|
|
assert(!isUser);
|
|
if(AI->getAllocatedType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) {
|
|
RETURN_IF(true);
|
|
}
|
|
}
|
|
else if(dyn_cast<ReturnInst>(value)) {
|
|
if(DEBUG_ALLOC_LEVEL >= 2) {
|
|
magicPassErr("Found return variable!");
|
|
}
|
|
assert(isUser);
|
|
RETURN_IF(true);
|
|
}
|
|
else if(StoreInst *SI = dyn_cast<StoreInst>(value)) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging store instruction: ", value);
|
|
assert(isUser);
|
|
if(parent == SI->getOperand(1)) {
|
|
assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
|
|
currPtrVarIndexes.pop_back();
|
|
findPointerVariables(function, SI->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
currPtrVarIndexes.push_back(0);
|
|
}
|
|
else {
|
|
currPtrVarIndexes.push_back(0);
|
|
findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value);
|
|
currPtrVarIndexes.pop_back();
|
|
}
|
|
}
|
|
else if(LoadInst *LI = dyn_cast<LoadInst>(value)) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging load instruction: ", value);
|
|
if(isUser) {
|
|
assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
|
|
savedPtrVarIndexes.push_back(currPtrVarIndexes.back());
|
|
currPtrVarIndexes.pop_back();
|
|
}
|
|
else {
|
|
currPtrVarIndexes.push_back(0);
|
|
findPointerVariables(function, LI->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
currPtrVarIndexes.pop_back();
|
|
}
|
|
}
|
|
else if(GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(value)) {
|
|
if(GEPI->getNumIndices() == 1) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value);
|
|
findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
}
|
|
else {
|
|
RETURN_IF(isUser);
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value);
|
|
unsigned k = 0;
|
|
int index;
|
|
assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
|
|
currPtrVarIndexes.pop_back(); //pop 0
|
|
for(GetElementPtrInst::const_op_iterator i=GEPI->idx_end()-1, b=GEPI->idx_begin();i>b;i--,k++) {
|
|
index = 0;
|
|
if(ConstantInt *CI = dyn_cast<ConstantInt>(*i)) {
|
|
index = CI->getSExtValue();
|
|
}
|
|
currPtrVarIndexes.push_back(index);
|
|
}
|
|
currPtrVarIndexes.push_back(0); //push 0
|
|
findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
currPtrVarIndexes.pop_back(); //pop 0
|
|
while(k-->0) {
|
|
currPtrVarIndexes.pop_back();
|
|
}
|
|
currPtrVarIndexes.push_back(0); //push 0
|
|
}
|
|
}
|
|
else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
|
|
assert(constantExpr->getNumOperands() >= 2);
|
|
if(constantExpr->getNumOperands() == 2) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value);
|
|
findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
}
|
|
else {
|
|
RETURN_IF(isUser);
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value);
|
|
unsigned k = 0;
|
|
int index;
|
|
assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
|
|
currPtrVarIndexes.pop_back(); //pop 0
|
|
for(unsigned i=constantExpr->getNumOperands()-1;i>1;i--,k++) {
|
|
index = 0;
|
|
if(ConstantInt *CI = dyn_cast<ConstantInt>(constantExpr->getOperand(i))) {
|
|
index = CI->getSExtValue();
|
|
}
|
|
currPtrVarIndexes.push_back(index);
|
|
}
|
|
currPtrVarIndexes.push_back(0); //push 0
|
|
findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
currPtrVarIndexes.pop_back(); //pop 0
|
|
while(k-->0) {
|
|
currPtrVarIndexes.pop_back();
|
|
}
|
|
currPtrVarIndexes.push_back(0); //push 0
|
|
}
|
|
}
|
|
else if(BitCastInst *CI = dyn_cast<BitCastInst>(value)) {
|
|
if((isUser && !checkPointerVariableIndexes(CI->getType(), currPtrVarIndexes))
|
|
|| (!isUser && !checkPointerVariableIndexes(CI->getOperand(0)->getType(), currPtrVarIndexes))) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Skipping unsafe cast instruction: ", value);
|
|
RETURN_IF(true);
|
|
}
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging cast instruction: ", value);
|
|
findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
}
|
|
else if(dyn_cast<CallInst>(value) || dyn_cast<InvokeInst>(value)) {
|
|
RETURN_IF(isUser);
|
|
DEBUG_VALUE(" >>>> findPointerVariables: found call instruction: ", value);
|
|
}
|
|
else if(CmpInst *CI = dyn_cast<CmpInst>(value)) {
|
|
assert(isUser);
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging cmp instruction: ", value);
|
|
findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value);
|
|
findPointerVariables(function, CI->getOperand(1), ptrVars, ptrVarIndexes, value);
|
|
RETURN_IF(true);
|
|
}
|
|
else if(SelectInst *SI = dyn_cast<SelectInst>(value)) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging select instruction: ", value);
|
|
findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value);
|
|
findPointerVariables(function, SI->getOperand(2), ptrVars, ptrVarIndexes, value);
|
|
}
|
|
else if(constantExpr && constantExpr->getOpcode() == Instruction::Select) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging select expression: ", value);
|
|
findPointerVariables(function, constantExpr->getOperand(1), ptrVars, ptrVarIndexes, value);
|
|
findPointerVariables(function, constantExpr->getOperand(2), ptrVars, ptrVarIndexes, value);
|
|
}
|
|
else if(PHINode *PN = dyn_cast<PHINode>(value)) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging PHI instruction: ", value);
|
|
for(unsigned i=0;i<PN->getNumIncomingValues();i++) {
|
|
findPointerVariables(function, PN->getIncomingValue(i), ptrVars, ptrVarIndexes, value);
|
|
}
|
|
}
|
|
else if(Argument *ARG = dyn_cast<Argument>(value)) {
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Digging Argument: ", value);
|
|
AllocaInst *AI = MagicUtil::getAllocaInstFromArgument(ARG);
|
|
assert(AI);
|
|
currPtrVarIndexes.push_back(0);
|
|
findPointerVariables(function, AI, ptrVars, ptrVarIndexes, value);
|
|
currPtrVarIndexes.pop_back();
|
|
RETURN_IF(true);
|
|
}
|
|
else {
|
|
DEBUG_VALUE(" ************************************************************ findPointerVariables: Unknown value: ", value);
|
|
RETURN_IF(true);
|
|
}
|
|
for (Value::use_iterator i = value->use_begin(), e = value->use_end(); i != e; ++i) {
|
|
User *user = *i;
|
|
Instruction *instruction = dyn_cast<Instruction>(user);
|
|
if(!instruction || instruction->getParent()->getParent() != function) {
|
|
continue;
|
|
}
|
|
DEBUG_VALUE(" >>>> findPointerVariables: Found user: ", user);
|
|
findPointerVariables(function, user, ptrVars, ptrVarIndexes, value, true);
|
|
}
|
|
while(savedPtrVarIndexes.size() > 0) {
|
|
currPtrVarIndexes.push_back(savedPtrVarIndexes.back());
|
|
savedPtrVarIndexes.pop_back();
|
|
}
|
|
}
|
|
|
|
TypeInfo* MagicPass::typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, std::string &allocName)
|
|
{
|
|
std::vector<TypeInfo*> validTypeInfos;
|
|
std::set<TypeInfo*> validTypeInfoSet;
|
|
std::vector<unsigned> validTypeTags;
|
|
std::vector<unsigned> voidTypeTags;
|
|
std::vector<int> indexes;
|
|
TypeInfo *aTypeInfo = NULL;
|
|
TypeInfo *voidTypeInfo = voidPtrTypeInfo->getContainedType(0);
|
|
allocName = "";
|
|
if(ptrVars.size()==0) {
|
|
return voidTypeInfo;
|
|
}
|
|
|
|
for(unsigned i=0;i<ptrVars.size();i++) {
|
|
DIVariable DIV;
|
|
unsigned tag = 0;
|
|
std::string varName = "";
|
|
if(GlobalVariable *GV = dyn_cast<GlobalVariable>(ptrVars[i])) {
|
|
parentMapIt = globalParentMap.find(GV);
|
|
assert(parentMapIt != globalParentMap.end());
|
|
aTypeInfo = parentMapIt->second;
|
|
tag = dwarf::DW_TAG_variable;
|
|
varName = MagicUtil::getGVSourceName(M, GV, NULL, baseBuildDir);
|
|
}
|
|
else {
|
|
AllocaInst *AI = dyn_cast<AllocaInst>(ptrVars[i]);
|
|
assert(AI);
|
|
if(DEBUG_ALLOC_LEVEL >= 4) {
|
|
AI->print(errs()); errs() << "\n";
|
|
}
|
|
const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV);
|
|
if(aSmartType == (const SmartType *)-1) {
|
|
//a temporary variable
|
|
if(DEBUG_ALLOC_LEVEL >= 4) {
|
|
magicPassErr("typeInfoFromPointerVariables: Skipping temporary variable");
|
|
}
|
|
continue;
|
|
}
|
|
else if(!aSmartType) {
|
|
//a return variable
|
|
if(DEBUG_ALLOC_LEVEL >= 4) {
|
|
magicPassErr("typeInfoFromPointerVariables: Processing return variable");
|
|
}
|
|
if(AI->getAllocatedType() == voidPtrTypeInfo->getType()) {
|
|
aTypeInfo = voidPtrTypeInfo;
|
|
}
|
|
else {
|
|
aTypeInfo = fillExternalTypeInfos(AI->getAllocatedType(), NULL, globalTypeInfos);
|
|
if(aTypeInfo == NULL) {
|
|
magicPassErr("typeInfoFromPointerVariables: type is: " << TypeUtil::getDescription(AI->getAllocatedType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
|
|
if(!MAGIC_ABORT_ON_UNSUPPORTED_LOCAL_EXTERNAL_TYPE) {
|
|
magicPassErr("typeInfoFromPointerVariables: Warning: Local external type not supported, resorting to void* type...");
|
|
aTypeInfo = voidPtrTypeInfo;
|
|
}
|
|
else {
|
|
assert(aTypeInfo != NULL && "Local external type not supported!");
|
|
}
|
|
}
|
|
}
|
|
tag = dwarf::DW_TAG_unspecified_type;
|
|
}
|
|
else {
|
|
//a regular variable (potentially returning a value to the caller)
|
|
if(DEBUG_ALLOC_LEVEL >= 4) {
|
|
magicPassErr("typeInfoFromPointerVariables: Processing regular variable");
|
|
}
|
|
TypeInfo newTypeInfo(aSmartType);
|
|
aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos);
|
|
if(aTypeInfo->getSmartType() != aSmartType) {
|
|
delete aSmartType;
|
|
}
|
|
if (PassUtil::isReturnedValue(AI->getParent()->getParent(), AI)) {
|
|
// treat this variable as a return variable
|
|
tag = dwarf::DW_TAG_unspecified_type;
|
|
}
|
|
else {
|
|
tag = DIV.getTag();
|
|
}
|
|
}
|
|
varName = DIV.getName();
|
|
}
|
|
//see if the target type is an alias for void*
|
|
assert(aTypeInfo);
|
|
if(aTypeInfo->getType()->isPointerTy()) {
|
|
stringSetIt = voidTypeAliasesSet.find(aTypeInfo->getContainedType(0)->getName());
|
|
if(stringSetIt != voidTypeAliasesSet.end()) {
|
|
aTypeInfo = voidPtrTypeInfo;
|
|
}
|
|
}
|
|
//fix tag if needed
|
|
if(tag == dwarf::DW_TAG_unspecified_type) {
|
|
TYPECONST Type *type = aTypeInfo->getType();
|
|
if(!type->isPointerTy() || type->getContainedType(0)->isPointerTy()) {
|
|
//not a good return type, switch to a regular variable
|
|
tag = dwarf::DW_TAG_auto_variable;
|
|
}
|
|
}
|
|
if(tag == dwarf::DW_TAG_arg_variable) {
|
|
TYPECONST Type *type = aTypeInfo->getType();
|
|
if(!type->isPointerTy() || !type->getContainedType(0)->isPointerTy() || type->getContainedType(0)->getContainedType(0)->isPointerTy()) {
|
|
//not a good arg type, switch to a regular variable
|
|
tag = dwarf::DW_TAG_auto_variable;
|
|
}
|
|
}
|
|
if(DEBUG_ALLOC_LEVEL >= 3) {
|
|
switch(tag) {
|
|
case dwarf::DW_TAG_unspecified_type:
|
|
magicPassErr("typeInfoFromPointerVariables: Found return variable: " << varName);
|
|
break;
|
|
case dwarf::DW_TAG_variable:
|
|
magicPassErr("typeInfoFromPointerVariables: Found global variable:" << varName);
|
|
break;
|
|
case dwarf::DW_TAG_auto_variable:
|
|
magicPassErr("typeInfoFromPointerVariables: Found local variable:" << varName);
|
|
break;
|
|
case dwarf::DW_TAG_arg_variable:
|
|
magicPassErr("typeInfoFromPointerVariables: Found argument variable:" << varName);
|
|
break;
|
|
default:
|
|
assert(0 && "Should never get here!");
|
|
break;
|
|
}
|
|
}
|
|
indexes = ptrVarIndexes[i];
|
|
assert(indexes.back() == 0);
|
|
indexes.pop_back();
|
|
if(DEBUG_ALLOC_LEVEL >= 4) {
|
|
magicPassErr("typeInfoFromPointerVariables: " << indexes.size() << " indexes to process.");
|
|
}
|
|
while(!indexes.empty()) {
|
|
int index = indexes.back();
|
|
if(aTypeInfo->hasRawTypeRepresentation()) {
|
|
if(DEBUG_ALLOC_LEVEL >= 4) {
|
|
magicPassErr("typeInfoFromPointerVariables: Skipping index (raw type representation): " << index << ", type is: " << aTypeInfo->getVerboseDescription());
|
|
}
|
|
aTypeInfo = voidTypeInfo;
|
|
break;
|
|
}
|
|
if(!aTypeInfo->getType()->isStructTy()) {
|
|
index = 0;
|
|
}
|
|
aTypeInfo = aTypeInfo->getContainedType(index);
|
|
if(DEBUG_ALLOC_LEVEL >= 4) {
|
|
magicPassErr("typeInfoFromPointerVariables: Processing index: " << index << ", type is: " << aTypeInfo->getVerboseDescription());
|
|
}
|
|
indexes.pop_back();
|
|
}
|
|
if(aTypeInfo == voidTypeInfo) {
|
|
voidTypeTags.push_back(tag);
|
|
}
|
|
else {
|
|
validTypeInfos.push_back(aTypeInfo);
|
|
validTypeInfoSet.insert(aTypeInfo);
|
|
validTypeTags.push_back(tag);
|
|
}
|
|
if(!allocName.compare("")) {
|
|
allocName = varName;
|
|
}
|
|
}
|
|
//see if we have a valid void return type
|
|
bool hasValidVoidReturnType = false;
|
|
for(unsigned i=0;i<voidTypeTags.size();i++) {
|
|
if(voidTypeTags[i] == dwarf::DW_TAG_unspecified_type || voidTypeTags[i] == dwarf::DW_TAG_arg_variable) {
|
|
hasValidVoidReturnType = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//count the number of weak local types
|
|
unsigned numWeakLocalTypes = 0;
|
|
unsigned nonWeakTypeIndex = 0;
|
|
unsigned index = 0;
|
|
for (std::set<TypeInfo*>::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) {
|
|
if((*it)->getType() == voidTypeInfo->getType()) {
|
|
numWeakLocalTypes++;
|
|
} else {
|
|
nonWeakTypeIndex = index;
|
|
}
|
|
index++;
|
|
}
|
|
bool hasOnlyWeakLocalTypes = (numWeakLocalTypes == validTypeInfoSet.size());
|
|
bool hasOnlyOneNonWeakLocalType = (validTypeInfoSet.size() - numWeakLocalTypes == 1);
|
|
|
|
if(DEBUG_ALLOC_LEVEL >= 3) {
|
|
magicPassErr("typeInfoFromPointerVariables: Status: voidTypeTagsSize=" << voidTypeTags.size() << ", hasValidVoidReturnType=" << hasValidVoidReturnType << ", hasOnlyWeakLocalTypes=" << hasOnlyWeakLocalTypes << ", hasOnlyOneNonWeakLocalType=" << hasOnlyOneNonWeakLocalType);
|
|
}
|
|
|
|
//return NULL (treat the function as a wrapper) if we have a valid return type and only weak local types
|
|
if(hasValidVoidReturnType && hasOnlyWeakLocalTypes) {
|
|
if(DEBUG_ALLOC_LEVEL >= 3) {
|
|
magicPassErr("typeInfoFromPointerVariables: Returning no type at all: treat the function as a wrapper");
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//a single valid type has been found, return it
|
|
if(hasOnlyOneNonWeakLocalType || (hasOnlyWeakLocalTypes && validTypeInfoSet.size() > 0)) {
|
|
if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_unspecified_type) {
|
|
if(DEBUG_ALLOC_BAD_TYPES) {
|
|
magicPassErr("typeInfoFromPointerVariables: warning: non-void return type");
|
|
}
|
|
}
|
|
if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_arg_variable) {
|
|
if(DEBUG_ALLOC_BAD_TYPES) {
|
|
magicPassErr("typeInfoFromPointerVariables: warning: non-void arg type");
|
|
}
|
|
}
|
|
if(DEBUG_ALLOC_LEVEL >= 3) {
|
|
magicPassErr("typeInfoFromPointerVariables: Returning single valid type");
|
|
}
|
|
return validTypeInfos[nonWeakTypeIndex];
|
|
}
|
|
//multiple valid types found, print warning and resort to void
|
|
else if(validTypeInfoSet.size() > 1 && DEBUG_ALLOC_BAD_TYPES) {
|
|
magicPassErr("typeInfoFromPointerVariables: warning: multiple valid types found:");
|
|
for (std::set<TypeInfo*>::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) {
|
|
magicPassErr(" - " << (*it)->getVerboseDescription());
|
|
}
|
|
if(DEBUG_ALLOC_LEVEL >= 3) {
|
|
magicPassErr("typeInfoFromPointerVariables: Multiple valid types found");
|
|
}
|
|
}
|
|
|
|
if(DEBUG_ALLOC_LEVEL >= 3) {
|
|
magicPassErr("typeInfoFromPointerVariables: Returning default void type");
|
|
}
|
|
return voidTypeInfo;
|
|
}
|
|
|
|
TypeInfo* MagicPass::getAllocTypeInfo(Module &M, TypeInfo *voidPtrTypeInfo, const CallSite &CS, std::string &allocName, std::string &allocParentName)
|
|
{
|
|
Value *allocPointer = NULL;
|
|
Function *function = MagicUtil::getCalledFunctionFromCS(CS);
|
|
Function *parentFunction = CS.getInstruction()->getParent()->getParent();
|
|
if(DEBUG_ALLOC_LEVEL >= 1) {
|
|
magicPassErr("Function is: " << function->getName());
|
|
magicPassErr("Parent is: " << parentFunction->getName());
|
|
}
|
|
std::vector<Value*> ptrVars;
|
|
std::vector<std::vector<int> > ptrVarIndexes;
|
|
currPtrVarIndexes.clear();
|
|
visitedValues.clear();
|
|
int pointerParam = MagicMemFunction::getMemFunctionPointerParam(function, brkFunctions, voidPtrTypeInfo);
|
|
assert(pointerParam >= 0 && "Invalid wrapper function!");
|
|
if(pointerParam == 0) {
|
|
allocPointer = CS.getInstruction();
|
|
currPtrVarIndexes.push_back(0);
|
|
}
|
|
else {
|
|
allocPointer = CS.getArgument(pointerParam-1);
|
|
currPtrVarIndexes.push_back(0);
|
|
//brk is a special case and takes the pointer by value
|
|
if(brkFunctions.find(function) == brkFunctions.end()) {
|
|
currPtrVarIndexes.push_back(0);
|
|
}
|
|
}
|
|
findPointerVariables(parentFunction, allocPointer, ptrVars, ptrVarIndexes);
|
|
TypeInfo* aTypeInfo = typeInfoFromPointerVariables(M, voidPtrTypeInfo, ptrVars, ptrVarIndexes, allocName);
|
|
allocParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseBuildDir);
|
|
if(DEBUG_ALLOC_LEVEL >= 1) {
|
|
magicPassErr("**************** type found: " << (aTypeInfo ? aTypeInfo->getType()->isStructTy() ? "struct " + aTypeInfo->getName() : aTypeInfo->getVerboseDescription() : "NULL"));
|
|
}
|
|
return aTypeInfo;
|
|
}
|
|
|
|
TypeInfo* MagicPass::fillTypeInfos(TypeInfo &sourceTypeInfo, std::vector<TypeInfo*> &typeInfos) {
|
|
static std::vector<TypeInfo*> nestedTypes;
|
|
static unsigned level = 0;
|
|
if(DEBUG_FILL_TYPE_INFOS) {
|
|
magicPassErr("Entering level: " << level << ", Examining type: " << sourceTypeInfo.getDescription() << ", types so far: " << typeInfos.size());
|
|
}
|
|
|
|
if(sourceTypeInfo.getType()) {
|
|
TYPECONST Type* type = sourceTypeInfo.getType();
|
|
for(unsigned i=0;i<nestedTypes.size();i++) {
|
|
if(type == nestedTypes[i]->getType()) {
|
|
const SmartType *nestedSType = nestedTypes[i]->getSmartType();
|
|
const SmartType *sourceSType = sourceTypeInfo.getSmartType();
|
|
if((!nestedSType && !sourceSType) || (nestedSType && sourceSType && nestedSType->getEDIType()->equals(sourceSType->getEDIType()))) {
|
|
nestedTypes[i]->addParents(sourceTypeInfo.getParents());
|
|
return nestedTypes[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
assert(sourceTypeInfo.getParents().size() <= 1);
|
|
for(unsigned i=0;i<typeInfos.size();i++) {
|
|
if(typeInfos[i]->equals(&sourceTypeInfo)) {
|
|
typeInfos[i]->addParents(sourceTypeInfo.getParents());
|
|
return typeInfos[i];
|
|
}
|
|
}
|
|
TypeInfo *aTypeInfo = new TypeInfo(sourceTypeInfo);
|
|
aTypeInfo->setPersistent();
|
|
const SmartType *aSmartType = aTypeInfo->getSmartType();
|
|
unsigned numContainedTypes = aSmartType ? aSmartType->getNumContainedTypes() : 0;
|
|
const SmartType* containedSmartType = NULL;
|
|
TypeInfo* addedTypeInfo = NULL;
|
|
std::vector<TypeInfo*> aTypeInfoContainedTypes;
|
|
nestedTypes.push_back(aTypeInfo);
|
|
level++;
|
|
for(unsigned i=0;i<numContainedTypes;i++) {
|
|
containedSmartType = aSmartType->getContainedType(i);
|
|
if(!containedSmartType->isFunctionTy() || containedSmartType->isTypeConsistent()) {
|
|
TypeInfo containedTypeInfo(containedSmartType);
|
|
addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos);
|
|
}
|
|
else {
|
|
TYPECONST FunctionType* type = (TYPECONST FunctionType*) containedSmartType->getType();
|
|
TypeInfo containedTypeInfo(type);
|
|
addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos);
|
|
}
|
|
if(addedTypeInfo->getSmartType() != containedSmartType) {
|
|
delete containedSmartType;
|
|
}
|
|
aTypeInfoContainedTypes.push_back(addedTypeInfo);
|
|
}
|
|
level--;
|
|
nestedTypes.pop_back();
|
|
aTypeInfo->setContainedTypes(aTypeInfoContainedTypes);
|
|
typeInfos.push_back(aTypeInfo);
|
|
if(DEBUG_FILL_TYPE_INFOS) {
|
|
magicPassErr("Exiting level: " << level << ", types so far: " << typeInfos.size());
|
|
}
|
|
return aTypeInfo;
|
|
}
|
|
|
|
TypeInfo* MagicPass::fillExternalTypeInfos(TYPECONST Type *sourceType, GlobalValue* parent, std::vector<TypeInfo*> &typeInfos) {
|
|
static std::map<TYPECONST Type *, TypeInfo*> externalTypeInfoCache;
|
|
std::map<TYPECONST Type*, TypeInfo*>::iterator externalTypeInfoCacheIt;
|
|
TypeInfo* aTypeInfo = NULL;
|
|
std::vector<TypeInfo*> compatibleTypeInfos;
|
|
//see if we already have the type in the cache first
|
|
externalTypeInfoCacheIt = externalTypeInfoCache.find(sourceType);
|
|
if(externalTypeInfoCacheIt != externalTypeInfoCache.end()) {
|
|
aTypeInfo = externalTypeInfoCacheIt->second;
|
|
if(parent) {
|
|
aTypeInfo->addParent(parent);
|
|
}
|
|
return aTypeInfo;
|
|
}
|
|
|
|
for(unsigned i=0;i<typeInfos.size();i++) {
|
|
if(typeInfos[i]->getSmartType() && typeInfos[i]->getSmartType()->getType() == sourceType && (!sourceType->isArrayTy() || typeInfos[i]->getTypeID() == MAGIC_TYPE_ARRAY)) {
|
|
compatibleTypeInfos.push_back(typeInfos[i]);
|
|
}
|
|
}
|
|
if(compatibleTypeInfos.size() > 0) {
|
|
unsigned minStringTypeInfo = 0;
|
|
if(compatibleTypeInfos.size() > 1) {
|
|
/* Select the first type in alphabetical order to ensure deterministic behavior. */
|
|
for(unsigned i=1;i<compatibleTypeInfos.size();i++) {
|
|
if(compatibleTypeInfos[i]->getSmartType()->getEDIType()->getDescription().compare(compatibleTypeInfos[minStringTypeInfo]->getSmartType()->getEDIType()->getDescription()) < 0) {
|
|
minStringTypeInfo = i;
|
|
}
|
|
}
|
|
}
|
|
aTypeInfo = compatibleTypeInfos[minStringTypeInfo];
|
|
}
|
|
if(DEBUG_FILL_EXT_TYPE_INFOS && compatibleTypeInfos.size() > 1) {
|
|
std::string typeString;
|
|
for(unsigned i=0;i<compatibleTypeInfos.size();i++) {
|
|
assert(compatibleTypeInfos[i]->getSmartType());
|
|
typeString += (i==0 ? "" : ", ") + compatibleTypeInfos[i]->getSmartType()->getEDIType()->getDescription();
|
|
}
|
|
magicPassErr("Multiple compatible types found for external type " << TypeUtil::getDescription(sourceType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << ": " << typeString << "; selecting the first type in alphabetical order: " << aTypeInfo->getSmartType()->getEDIType()->getDescription());
|
|
}
|
|
if(aTypeInfo == NULL) {
|
|
TypeInfo *targetTypeInfo = NULL;
|
|
if(TypeUtil::isOpaqueTy(sourceType)) {
|
|
aTypeInfo = new TypeInfo((TYPECONST StructType*) sourceType, TYPEINFO_PERSISTENT);
|
|
typeInfos.push_back(aTypeInfo);
|
|
}
|
|
else if(sourceType->isPointerTy()) {
|
|
TYPECONST Type *targetType = sourceType->getContainedType(0);
|
|
targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos);
|
|
if(targetTypeInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
aTypeInfo = new TypeInfo((TYPECONST PointerType*) sourceType, TYPEINFO_PERSISTENT);
|
|
}
|
|
else if(sourceType->isArrayTy()) {
|
|
TYPECONST Type *targetType = sourceType->getContainedType(0);
|
|
targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos);
|
|
if(targetTypeInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
aTypeInfo = new TypeInfo((TYPECONST ArrayType*) sourceType, TYPEINFO_PERSISTENT);
|
|
}
|
|
else if(sourceType->isIntegerTy()) {
|
|
aTypeInfo = new TypeInfo((TYPECONST IntegerType*) sourceType, TYPEINFO_PERSISTENT);
|
|
typeInfos.push_back(aTypeInfo);
|
|
}
|
|
else if(sourceType->isFunctionTy()) {
|
|
aTypeInfo = new TypeInfo((TYPECONST FunctionType*) sourceType, TYPEINFO_PERSISTENT);
|
|
typeInfos.push_back(aTypeInfo);
|
|
}
|
|
if(targetTypeInfo != NULL) {
|
|
std::vector<TypeInfo*> containedTypes;
|
|
containedTypes.push_back(targetTypeInfo);
|
|
aTypeInfo->setContainedTypes(containedTypes);
|
|
typeInfos.push_back(aTypeInfo);
|
|
}
|
|
}
|
|
if(aTypeInfo && parent) {
|
|
aTypeInfo->addParent(parent);
|
|
}
|
|
externalTypeInfoCache.insert(std::pair<TYPECONST Type*, TypeInfo*>(sourceType, aTypeInfo));
|
|
return aTypeInfo;
|
|
}
|
|
|
|
void MagicPass::printInterestingTypes(TYPECONST TypeInfo *aTypeInfo) {
|
|
static std::vector<TYPECONST TypeInfo*> nestedTypes;
|
|
static std::vector<unsigned> nestedIndexes;
|
|
static std::vector<TYPECONST TypeInfo*> interestingTypesSoFar;
|
|
static std::string typeName;
|
|
static unsigned level = 0;
|
|
for(unsigned i=0;i<nestedTypes.size();i++) {
|
|
if(aTypeInfo == nestedTypes[i]) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool isInterestingType = false;
|
|
const SmartType *aSmartType = aTypeInfo->getSmartType();
|
|
if(aSmartType) {
|
|
if(aSmartType->isStructTy() && !aTypeInfo->getName().compare("")) {
|
|
isInterestingType = true;
|
|
typeName = "Anonymous";
|
|
}
|
|
if(aSmartType->getEDIType()->isEnumTy()) {
|
|
isInterestingType = true;
|
|
typeName = "Enum";
|
|
}
|
|
if(aSmartType->isOpaqueTy()) {
|
|
isInterestingType = true;
|
|
typeName = "Opaque";
|
|
}
|
|
}
|
|
if(isInterestingType) {
|
|
bool isNewInterestingType = true;
|
|
for(unsigned i=0;i<interestingTypesSoFar.size();i++) {
|
|
if(aTypeInfo == interestingTypesSoFar[i]) {
|
|
isNewInterestingType = false;
|
|
break;
|
|
}
|
|
}
|
|
if(isNewInterestingType) {
|
|
interestingTypesSoFar.push_back(aTypeInfo);
|
|
if(nestedTypes.size() == 0) {
|
|
dbgs() << "**** " << typeName << " top type found, printing it: \n";
|
|
dbgs() << aSmartType->getDescription();
|
|
aSmartType->getEDIType()->getDIType()->print(dbgs());
|
|
}
|
|
else {
|
|
dbgs() << "**** " << typeName << " type found, printing path: \n";
|
|
dbgs() << "**************** LEVEL 0\n";
|
|
dbgs() << "**************** NAME: " << nestedTypes[0]->getName() << "\n";
|
|
dbgs() << nestedTypes[0]->getSmartType()->getDescription();
|
|
unsigned i;
|
|
for(i=1;i<nestedTypes.size();i++) {
|
|
dbgs() << "**************** LEVEL " << i << "\n";
|
|
dbgs() << "**************** NAME: " << nestedTypes[i]->getName() << "\n";
|
|
dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n";
|
|
dbgs() << nestedTypes[i]->getSmartType()->getDescription();
|
|
}
|
|
dbgs() << "**************** LAST LEVEL " << i << "\n";
|
|
dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n";
|
|
dbgs() << aSmartType->getDescription();
|
|
aSmartType->getEDIType()->getDIType()->print(dbgs());
|
|
dbgs() << "*****************************************\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned numContainedTypes = aTypeInfo->getNumContainedTypes();
|
|
nestedTypes.push_back(aTypeInfo);
|
|
level++;
|
|
for(unsigned i=0;i<numContainedTypes;i++) {
|
|
nestedIndexes.push_back(i);
|
|
printInterestingTypes(aTypeInfo->getContainedType(i));
|
|
nestedIndexes.pop_back();
|
|
}
|
|
level--;
|
|
nestedTypes.pop_back();
|
|
}
|
|
|
|
unsigned MagicPass::getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo) {
|
|
static std::vector<TYPECONST TypeInfo*> nestedTypes;
|
|
static unsigned level = 0;
|
|
for(unsigned i=0;i<nestedTypes.size();i++) {
|
|
if(aTypeInfo == nestedTypes[i]) {
|
|
return nestedTypes.size()+1;
|
|
}
|
|
}
|
|
|
|
unsigned numContainedTypes = aTypeInfo->getNumContainedTypes();
|
|
unsigned length, maxLength = 0;
|
|
nestedTypes.push_back(aTypeInfo);
|
|
level++;
|
|
for(unsigned i=0;i<numContainedTypes;i++) {
|
|
length = getMaxRecursiveSequenceLength(aTypeInfo->getContainedType(i));
|
|
if(length > maxLength) {
|
|
maxLength = length;
|
|
}
|
|
}
|
|
level--;
|
|
nestedTypes.pop_back();
|
|
return maxLength;
|
|
}
|
|
|
|
FunctionType* MagicPass::getFunctionType(TYPECONST FunctionType *baseType, std::vector<unsigned> selectedArgs) {
|
|
std::vector<TYPECONST Type*> ArgTypes;
|
|
for (unsigned i = 0; i < selectedArgs.size(); i++) {
|
|
ArgTypes.push_back(baseType->getParamType(selectedArgs[i] - 1));
|
|
}
|
|
// Create a new function type...
|
|
FunctionType *FTy = FunctionType::get(baseType->getReturnType(), ArgTypes, baseType->isVarArg());
|
|
return FTy;
|
|
}
|
|
|
|
bool MagicPass::isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType) {
|
|
if(type->getReturnType() != magicType->getReturnType()) {
|
|
return false;
|
|
}
|
|
unsigned numContainedTypes = type->getNumContainedTypes();
|
|
unsigned numContainedMagicTypes = magicType->getNumContainedTypes();
|
|
if(numContainedTypes > numContainedMagicTypes) {
|
|
return false;
|
|
}
|
|
for(unsigned i=0;i<numContainedTypes-1;i++) {
|
|
TYPECONST Type* cType = type->getContainedType(numContainedTypes-1-i);
|
|
TYPECONST Type* cMagicType = magicType->getContainedType(numContainedMagicTypes-1-i);
|
|
if (!MagicUtil::isCompatibleType(cType, cMagicType)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void MagicPass::indexCasts(Module &M, User *U, std::vector<TYPECONST Type*> &intCastTypes, std::vector<int> &intCastValues, std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastMap) {
|
|
unsigned i;
|
|
std::map<TYPECONST Type*, std::set<TYPECONST Type*> >::iterator bitCastMapIt;
|
|
TYPECONST Type* voidPtrType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
|
|
|
|
//look at instructions first
|
|
#if MAGIC_INDEX_INT_CAST
|
|
if(CastInst* CI = dyn_cast<IntToPtrInst>(U)) {
|
|
TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy());
|
|
TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
|
|
if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) {
|
|
if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) {
|
|
intCastTypes.push_back(type);
|
|
ConstantInt *value = dyn_cast<ConstantInt>(CI->getOperand(0));
|
|
intCastValues.push_back(value ? value->getSExtValue() : 0);
|
|
#if DEBUG_CASTS
|
|
CI->print(errs()); errs() << "\n";
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if MAGIC_INDEX_BIT_CAST
|
|
if(BitCastInst* CI = dyn_cast<BitCastInst>(U)) {
|
|
TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy());
|
|
TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
|
|
if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) {
|
|
if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) {
|
|
TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CI->getSrcTy());
|
|
if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) {
|
|
#if DEBUG_CASTS
|
|
CI->print(errs()); errs() << "\n";
|
|
#endif
|
|
bitCastMapIt = bitCastMap.find(type);
|
|
if(bitCastMapIt == bitCastMap.end()) {
|
|
std::set<TYPECONST Type*> typeSet;
|
|
typeSet.insert(srcType);
|
|
bitCastMap.insert(std::pair<TYPECONST Type*, std::set<TYPECONST Type*> >(type, typeSet));
|
|
}
|
|
else {
|
|
std::set<TYPECONST Type*> *typeSet = &(bitCastMapIt->second);
|
|
typeSet->insert(srcType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//now dig looking for constant expressions
|
|
std::vector<User*> users;
|
|
users.push_back(U);
|
|
while(!users.empty()) {
|
|
User *user = users.front();
|
|
users.erase(users.begin());
|
|
ConstantExpr *CE = dyn_cast<ConstantExpr>(user);
|
|
|
|
#if MAGIC_INDEX_INT_CAST
|
|
if(CE && CE->getOpcode() == Instruction::IntToPtr) {
|
|
TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType());
|
|
TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
|
|
if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) {
|
|
if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) {
|
|
#if DEBUG_CASTS
|
|
CE->print(errs()); errs() << "\n";
|
|
#endif
|
|
intCastTypes.push_back(type);
|
|
ConstantInt *value = dyn_cast<ConstantInt>(CE->getOperand(0));
|
|
intCastValues.push_back(value ? value->getSExtValue() : 0);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if MAGIC_INDEX_BIT_CAST
|
|
if(CE && CE->getOpcode() == Instruction::BitCast) {
|
|
TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType());
|
|
TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
|
|
if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) {
|
|
if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) {
|
|
TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CE->getOperand(0)->getType());
|
|
if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) {
|
|
#if DEBUG_CASTS
|
|
CE->print(errs()); errs() << "\n";
|
|
#endif
|
|
bitCastMapIt = bitCastMap.find(type);
|
|
if(bitCastMapIt == bitCastMap.end()) {
|
|
std::set<TYPECONST Type*> typeSet;
|
|
typeSet.insert(srcType);
|
|
bitCastMap.insert(std::pair<TYPECONST Type*, std::set<TYPECONST Type*> >(type, typeSet));
|
|
}
|
|
else {
|
|
std::set<TYPECONST Type*> *typeSet = &(bitCastMapIt->second);
|
|
typeSet->insert(srcType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
for(i=0;i<user->getNumOperands();i++) {
|
|
User *operand = dyn_cast<User>(user->getOperand(i));
|
|
if(operand && !isa<Instruction>(operand) && !isa<GlobalVariable>(operand)) {
|
|
users.push_back(operand);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MagicPass::fillStackInstrumentedFunctions(std::vector<Function*> &stackIntrumentedFuncs, Function *deepestLLFunction) {
|
|
assert(!deepestLLFunction->hasAddressTaken() && "Indirect calls not supported for detection of long-lived functions");
|
|
for(unsigned i=0;i<stackIntrumentedFuncs.size();i++) {
|
|
if(stackIntrumentedFuncs[i] == deepestLLFunction) {
|
|
return;
|
|
}
|
|
}
|
|
stackIntrumentedFuncs.push_back(deepestLLFunction);
|
|
for (Value::use_iterator i = deepestLLFunction->use_begin(), e = deepestLLFunction->use_end(); i != e; ++i) {
|
|
User *user = *i;
|
|
if(Instruction *I = dyn_cast<Instruction>(user)) {
|
|
fillStackInstrumentedFunctions(stackIntrumentedFuncs, I->getParent()->getParent());
|
|
}
|
|
}
|
|
}
|
|
|
|
void MagicPass::indexLocalTypeInfos(Module &M, Function *F, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > &localMap) {
|
|
DIVariable DIV;
|
|
for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) {
|
|
AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
|
|
if(!AI) {
|
|
break;
|
|
}
|
|
const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV);
|
|
if(!aSmartType || aSmartType == (const SmartType *)-1) {
|
|
// skip return and temporary variables
|
|
continue;
|
|
}
|
|
TypeInfo newTypeInfo(aSmartType);
|
|
TypeInfo *aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos);
|
|
if(aTypeInfo->getSmartType() != aSmartType) {
|
|
delete aSmartType;
|
|
}
|
|
std::string name = MagicUtil::getLVSourceName(M, AI).data();
|
|
std::pair<TypeInfo*, std::string> infoNamePair(aTypeInfo, name);
|
|
localMap.insert(std::pair<AllocaInst*, std::pair<TypeInfo*, std::string> >(AI, infoNamePair));
|
|
}
|
|
}
|
|
|
|
void MagicPass::addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap, std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector<TypeInfo*> &typeInfoList, std::vector<std::pair<std::string, std::string> > &namesList, std::vector<int> &flagsList) {
|
|
std::vector<Value*> locals;
|
|
std::map<AllocaInst*, std::pair<TypeInfo*, std::string> >::iterator localTypeInfoMapIt;
|
|
std::map<TypeInfo*, Constant*>::iterator magicArrayTypePtrMapIt;
|
|
std::vector<TypeInfo*> localTypeInfos;
|
|
std::vector<Value*> localTypeInfoValues;
|
|
std::vector<Value*> localDsentryValues;
|
|
std::string allocName, allocParentName;
|
|
Instruction *allocaI = NULL, *dsentryCreateI = NULL, *dsentryDestroyI = NULL;
|
|
// find local variables and types
|
|
for (inst_iterator it = inst_begin(localsFromFunc), et = inst_end(localsFromFunc); it != et; ++it) {
|
|
AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
|
|
if(!AI) {
|
|
break;
|
|
}
|
|
localTypeInfoMapIt = localTypeInfoMap.find(AI);
|
|
if(localTypeInfoMapIt != localTypeInfoMap.end()) {
|
|
assert(AI->hasName());
|
|
TypeInfo *aTypeInfo = localTypeInfoMapIt->second.first;
|
|
magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
|
|
assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
|
|
Constant *aTypeInfoValue = magicArrayTypePtrMapIt->second;
|
|
localTypeInfos.push_back(aTypeInfo);
|
|
localTypeInfoValues.push_back(aTypeInfoValue);
|
|
locals.push_back(AI);
|
|
}
|
|
}
|
|
// find the first and the last valid instruction to place a call and the alloca point
|
|
dsentryCreateI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc);
|
|
dsentryDestroyI = insertCallsInFunc->back().getTerminator();
|
|
allocaI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc, false);
|
|
|
|
// create one dsentry for each local variable
|
|
for(unsigned i=0;i<locals.size();i++) {
|
|
AllocaInst *AI = new AllocaInst(dsentryStructType, "dsentry_" + (locals[i]->hasName() ? locals[i]->getName() : "anon"), allocaI);
|
|
localDsentryValues.push_back(AI);
|
|
}
|
|
assert(localTypeInfoValues.size() == localDsentryValues.size());
|
|
|
|
// create one dsentry and value set array for the return address
|
|
localTypeInfos.push_back(voidPtrTypeInfo);
|
|
localTypeInfoValues.push_back(new AllocaInst(ArrayType::get(IntegerType::get(M.getContext(), 32), 2), "dsentry_ret_addr_value_set", allocaI)); //pass the value set pointer as though it were a type pointer
|
|
localDsentryValues.push_back(new AllocaInst(dsentryStructType, "dsentry_ret_addr", allocaI));
|
|
|
|
// create one dsentry pointer to remember the last stack dsentry
|
|
AllocaInst *prevLastStackDsentry = new AllocaInst(PointerType::get(dsentryStructType, 0), "prev_last_stack_dsentry", allocaI);
|
|
|
|
// get the frame address of the function and pass the value as though it were a data pointer
|
|
Function *frameAddrIntrinsic = MagicUtil::getIntrinsicFunction(M, Intrinsic::frameaddress);
|
|
std::vector<Value*> frameAddrArgs;
|
|
frameAddrArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, 0)));
|
|
CallInst *callInst = MagicUtil::createCallInstruction(frameAddrIntrinsic, frameAddrArgs, "", dsentryCreateI);
|
|
locals.push_back(callInst);
|
|
|
|
// place calls
|
|
std::vector<Value*> dsentryCreateArgs;
|
|
std::vector<Value*> dsentryDestroyArgs;
|
|
dsentryCreateArgs.push_back(prevLastStackDsentry);
|
|
dsentryDestroyArgs.push_back(prevLastStackDsentry);
|
|
dsentryCreateArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size())));
|
|
dsentryDestroyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size())));
|
|
allocParentName = MagicUtil::getFunctionSourceName(M, insertCallsInFunc, NULL, baseBuildDir);
|
|
int allocFlags = MAGIC_STATE_STACK;
|
|
for(unsigned i=0;i<locals.size();i++) {
|
|
//get name
|
|
if(AllocaInst *AI = dyn_cast<AllocaInst>(locals[i])) {
|
|
// local variable
|
|
localTypeInfoMapIt = localTypeInfoMap.find(AI);
|
|
assert(localTypeInfoMapIt != localTypeInfoMap.end());
|
|
allocName = localTypeInfoMapIt->second.second;
|
|
}
|
|
else {
|
|
// return address
|
|
allocName = MAGIC_ALLOC_RET_ADDR_NAME;
|
|
}
|
|
//add args
|
|
dsentryCreateArgs.push_back(localDsentryValues[i]);
|
|
dsentryCreateArgs.push_back(localTypeInfoValues[i]);
|
|
dsentryCreateArgs.push_back(locals[i]);
|
|
dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocParentName));
|
|
dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocName));
|
|
dsentryDestroyArgs.push_back(localDsentryValues[i]);
|
|
//add elements to type and names lists
|
|
typeInfoList.push_back(localTypeInfos[i]);
|
|
namesList.push_back(std::pair<std::string, std::string>(allocParentName, allocName));
|
|
flagsList.push_back(allocFlags);
|
|
}
|
|
MagicUtil::createCallInstruction(dsentryCreateFunc, dsentryCreateArgs, "", dsentryCreateI);
|
|
if(isa<ReturnInst>(dsentryDestroyI)) {
|
|
MagicUtil::createCallInstruction(dsentryDestroyFunc, dsentryDestroyArgs, "", dsentryDestroyI);
|
|
}
|
|
}
|
|
|
|
bool MagicPass::isExtLibrary(GlobalValue *GV, DIDescriptor *DID)
|
|
{
|
|
static bool regexesInitialized = false;
|
|
static std::vector<Regex*> regexes;
|
|
if(!regexesInitialized) {
|
|
std::vector<std::string>::iterator it;
|
|
for (it = libPathRegexes.begin(); it != libPathRegexes.end(); ++it) {
|
|
Regex* regex = new Regex(*it, 0);
|
|
std::string error;
|
|
assert(regex->isValid(error));
|
|
regexes.push_back(regex);
|
|
}
|
|
regexesInitialized = true;
|
|
}
|
|
if (DID) {
|
|
std::string relPath;
|
|
PassUtil::getDbgLocationInfo(*DID, baseBuildDir, NULL, NULL, &relPath);
|
|
for(unsigned i=0;i<regexes.size();i++) {
|
|
if(regexes[i]->match(relPath, NULL)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return PassUtil::matchRegexes(GV->getSection(), extLibSectionRegexes);
|
|
}
|
|
|
|
bool MagicPass::isMagicGV(Module &M, GlobalVariable *GV)
|
|
{
|
|
if (GV->isThreadLocal() && (GV->getName().startswith(MAGIC_PREFIX_STR) || GV->getName().startswith("rcu"))) {
|
|
return true;
|
|
}
|
|
if (!GV->getSection().compare(MAGIC_LLVM_METADATA_SECTION)) {
|
|
return true;
|
|
}
|
|
if (GV->getName().startswith("__start") || GV->getName().startswith("__stop") || GV->getName().startswith("llvm.")) {
|
|
return true;
|
|
}
|
|
return PassUtil::matchRegexes(GV->getSection(), magicDataSectionRegexes);
|
|
}
|
|
|
|
bool MagicPass::isMagicFunction(Module &M, Function *F)
|
|
{
|
|
if (F->getName().startswith("llvm.")) return true;
|
|
return PassUtil::matchRegexes(F->getSection(), magicFunctionSectionRegexes);
|
|
}
|
|
|
|
#if MAGIC_USE_QPROF_INSTRUMENTATION
|
|
|
|
void MagicPass::qprofInstrumentationInit(Module &M)
|
|
{
|
|
// look up qprof configuration
|
|
qprofConf = QProfConf::get(M, &magicLLSitestacks,
|
|
&magicDeepestLLLoops,
|
|
&magicDeepestLLLibs,
|
|
&magicTaskClasses);
|
|
qprofConf->mergeAllTaskClassesWithSameDeepestLLLoops();
|
|
|
|
#if DEBUG_QPROF
|
|
qprofConf->print(errs());
|
|
#endif
|
|
}
|
|
|
|
void MagicPass::qprofInstrumentationApply(Module &M)
|
|
{
|
|
Function *hook;
|
|
std::vector<Value*> hookParams;
|
|
QProfSite* site;
|
|
std::vector<TYPECONST Type*>functionTyArgs;
|
|
FunctionType *hookFunctionTy;
|
|
|
|
/*
|
|
* Instrument deepest long-lived loops. This creates a function
|
|
* pointer of the form void (*MAGIC_DEEPEST_LL_LOOP_HOOK_NAME)(char*, int)
|
|
* called (if set by instrumentation libraries) at the top of every loop.
|
|
*/
|
|
functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0));
|
|
functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
|
|
hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false);
|
|
std::vector<QProfSite*> deepestLLLoops = qprofConf->getDeepestLLLoops();
|
|
hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LOOP_HOOK_NAME, hookFunctionTy,
|
|
PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
|
|
assert(hook);
|
|
for (unsigned i=0;i<deepestLLLoops.size();i++) {
|
|
site = deepestLLLoops[i];
|
|
hookParams.clear();
|
|
Constant* siteString = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, site->toString()));
|
|
hookParams.push_back(siteString);
|
|
hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10)));
|
|
PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction);
|
|
}
|
|
|
|
/*
|
|
* Instrument deepest long-lived library calls. This creates a function
|
|
* pointer of the form void (*MAGIC_DEEPEST_LL_LIB_HOOK_NAME)(char*, int, int, int)
|
|
* called (if set by instrumentation libraries) before every library call.
|
|
*/
|
|
functionTyArgs.clear();
|
|
functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0));
|
|
functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
|
|
functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
|
|
functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
|
|
hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false);
|
|
std::vector<QProfSite*> deepestLLLibs = qprofConf->getDeepestLLLibs();
|
|
hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LIB_HOOK_NAME, hookFunctionTy,
|
|
PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
|
|
assert(hook);
|
|
for (unsigned i=0;i<deepestLLLibs.size();i++) {
|
|
site = deepestLLLibs[i];
|
|
hookParams.clear();
|
|
Constant* siteString = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, site->toString()));
|
|
hookParams.push_back(siteString);
|
|
hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10)));
|
|
hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskSiteID, 10)));
|
|
hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->libFlags, 10)));
|
|
PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction);
|
|
}
|
|
|
|
/*
|
|
* Create relevant exported variables in use by the libraries.
|
|
*/
|
|
MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_TASK_CLASSES_NAME, qprofConf->getNumLLTaskClasses());
|
|
MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockExtTaskClasses());
|
|
MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockIntTaskClasses());
|
|
MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_LIBS_NAME, qprofConf->getNumLLBlockExtLibs());
|
|
MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_LIBS_NAME, qprofConf->getNumLLBlockIntLibs());
|
|
}
|
|
|
|
#else
|
|
|
|
void MagicPass::qprofInstrumentationInit(Module &M) {}
|
|
void MagicPass::qprofInstrumentationApply(Module &M) {}
|
|
|
|
#endif
|
|
|
|
} // end namespace
|
|
|
|
char MagicPass::ID = 0;
|
|
RegisterPass<MagicPass> MP("magic", "Magic Pass to Build a Table of Global Variables");
|
|
|