1*0b98e8aaSDavid van Moolenbroek #include <asr/ASRPass.h> 2*0b98e8aaSDavid van Moolenbroek #include <magic_common.h> 3*0b98e8aaSDavid van Moolenbroek #include <magic/support/MagicUtil.h> 4*0b98e8aaSDavid van Moolenbroek #include <llvm/Transforms/Utils/BasicBlockUtils.h> 5*0b98e8aaSDavid van Moolenbroek 6*0b98e8aaSDavid van Moolenbroek #define MAGIC_IS_MAGIC_FUNC(M, F) (!(F)->getSection().compare(MAGIC_STATIC_FUNCTIONS_SECTION)) 7*0b98e8aaSDavid van Moolenbroek 8*0b98e8aaSDavid van Moolenbroek using namespace llvm; 9*0b98e8aaSDavid van Moolenbroek 10*0b98e8aaSDavid van Moolenbroek 11*0b98e8aaSDavid van Moolenbroek // command-line arguments 12*0b98e8aaSDavid van Moolenbroek 13*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 14*0b98e8aaSDavid van Moolenbroek seed("asr-seed", 15*0b98e8aaSDavid van Moolenbroek cl::desc("Random seed integer value for ASRPass. '0' will use current time as seed"), 16*0b98e8aaSDavid van Moolenbroek cl::init(DEFAULT_SEED), cl::NotHidden, cl::ValueRequired); 17*0b98e8aaSDavid van Moolenbroek 18*0b98e8aaSDavid van Moolenbroek 19*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 20*0b98e8aaSDavid van Moolenbroek gv_max_offset("asr-gv-max-offset", 21*0b98e8aaSDavid van Moolenbroek cl::desc(""), 22*0b98e8aaSDavid van Moolenbroek cl::init(GV_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired); 23*0b98e8aaSDavid van Moolenbroek 24*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 25*0b98e8aaSDavid van Moolenbroek gv_max_padding("asr-gv-max-padding", 26*0b98e8aaSDavid van Moolenbroek cl::desc(""), 27*0b98e8aaSDavid van Moolenbroek cl::init(GV_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired); 28*0b98e8aaSDavid van Moolenbroek 29*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 30*0b98e8aaSDavid van Moolenbroek gv_do_permutate("asr-gv-do-permutate", 31*0b98e8aaSDavid van Moolenbroek cl::desc(""), 32*0b98e8aaSDavid van Moolenbroek cl::init(GV_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired); 33*0b98e8aaSDavid van Moolenbroek 34*0b98e8aaSDavid van Moolenbroek 35*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 36*0b98e8aaSDavid van Moolenbroek func_max_offset("asr-func-max-offset", 37*0b98e8aaSDavid van Moolenbroek cl::desc(""), 38*0b98e8aaSDavid van Moolenbroek cl::init(FUNC_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired); 39*0b98e8aaSDavid van Moolenbroek 40*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 41*0b98e8aaSDavid van Moolenbroek func_max_padding("asr-func-max-padding", 42*0b98e8aaSDavid van Moolenbroek cl::desc(""), 43*0b98e8aaSDavid van Moolenbroek cl::init(FUNC_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired); 44*0b98e8aaSDavid van Moolenbroek 45*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 46*0b98e8aaSDavid van Moolenbroek func_max_bb_shift("asr-func-max-bb-shift", 47*0b98e8aaSDavid van Moolenbroek cl::desc(""), 48*0b98e8aaSDavid van Moolenbroek cl::init(FUNC_DEFAULT_MAX_BB_SHIFT), cl::NotHidden, cl::ValueRequired); 49*0b98e8aaSDavid van Moolenbroek 50*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 51*0b98e8aaSDavid van Moolenbroek func_do_permutate("asr-func-do-permutate", 52*0b98e8aaSDavid van Moolenbroek cl::desc(""), 53*0b98e8aaSDavid van Moolenbroek cl::init(FUNC_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired); 54*0b98e8aaSDavid van Moolenbroek 55*0b98e8aaSDavid van Moolenbroek 56*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 57*0b98e8aaSDavid van Moolenbroek stack_do_offset("asr-stack-do-offset", 58*0b98e8aaSDavid van Moolenbroek cl::desc(""), 59*0b98e8aaSDavid van Moolenbroek cl::init(STACK_DEFAULT_DO_OFFSET), cl::NotHidden, cl::ValueRequired); 60*0b98e8aaSDavid van Moolenbroek 61*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 62*0b98e8aaSDavid van Moolenbroek stack_max_offset("asr-stack-max-offset", 63*0b98e8aaSDavid van Moolenbroek cl::desc(""), 64*0b98e8aaSDavid van Moolenbroek cl::init(STACK_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired); 65*0b98e8aaSDavid van Moolenbroek 66*0b98e8aaSDavid van Moolenbroek 67*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 68*0b98e8aaSDavid van Moolenbroek stackframe_do_offset("asr-stackframe-do-offset", 69*0b98e8aaSDavid van Moolenbroek cl::desc(""), 70*0b98e8aaSDavid van Moolenbroek cl::init(STACKFRAME_DEFAULT_DO_OFFSET), cl::NotHidden, cl::ValueRequired); 71*0b98e8aaSDavid van Moolenbroek 72*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 73*0b98e8aaSDavid van Moolenbroek stackframe_max_offset("asr-stackframe-max-offset", 74*0b98e8aaSDavid van Moolenbroek cl::desc(""), 75*0b98e8aaSDavid van Moolenbroek cl::init(STACKFRAME_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired); 76*0b98e8aaSDavid van Moolenbroek 77*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 78*0b98e8aaSDavid van Moolenbroek stackframe_max_padding("asr-stackframe-max-padding", 79*0b98e8aaSDavid van Moolenbroek cl::desc(""), 80*0b98e8aaSDavid van Moolenbroek cl::init(STACKFRAME_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired); 81*0b98e8aaSDavid van Moolenbroek 82*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 83*0b98e8aaSDavid van Moolenbroek stackframe_do_permutate("asr-stackframe-do-permutate", 84*0b98e8aaSDavid van Moolenbroek cl::desc(""), 85*0b98e8aaSDavid van Moolenbroek cl::init(STACKFRAME_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired); 86*0b98e8aaSDavid van Moolenbroek 87*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 88*0b98e8aaSDavid van Moolenbroek stackframe_static_padding("asr-stackframe-static-padding", 89*0b98e8aaSDavid van Moolenbroek cl::desc(""), 90*0b98e8aaSDavid van Moolenbroek cl::init(STACKFRAME_DEFAULT_STATIC_PADDING), cl::NotHidden, cl::ValueRequired); 91*0b98e8aaSDavid van Moolenbroek 92*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 93*0b98e8aaSDavid van Moolenbroek stackframe_caller_padding("asr-stackframe-caller-padding", 94*0b98e8aaSDavid van Moolenbroek cl::desc(""), 95*0b98e8aaSDavid van Moolenbroek cl::init(STACKFRAME_DEFAULT_CALLER_PADDING), cl::NotHidden, cl::ValueRequired); 96*0b98e8aaSDavid van Moolenbroek 97*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 98*0b98e8aaSDavid van Moolenbroek heap_map_do_permutate("asr-heap-map-do-permutate", 99*0b98e8aaSDavid van Moolenbroek cl::desc(""), 100*0b98e8aaSDavid van Moolenbroek cl::init(HEAP_MAP_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired); 101*0b98e8aaSDavid van Moolenbroek 102*0b98e8aaSDavid van Moolenbroek 103*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 104*0b98e8aaSDavid van Moolenbroek heap_max_offset("asr-heap-max-offset", 105*0b98e8aaSDavid van Moolenbroek cl::desc(""), 106*0b98e8aaSDavid van Moolenbroek cl::init(HEAP_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired); 107*0b98e8aaSDavid van Moolenbroek 108*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 109*0b98e8aaSDavid van Moolenbroek heap_max_padding("asr-heap-max-padding", 110*0b98e8aaSDavid van Moolenbroek cl::desc(""), 111*0b98e8aaSDavid van Moolenbroek cl::init(HEAP_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired); 112*0b98e8aaSDavid van Moolenbroek 113*0b98e8aaSDavid van Moolenbroek 114*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 115*0b98e8aaSDavid van Moolenbroek map_max_offset_pages("asr-map-max-offset-pages", 116*0b98e8aaSDavid van Moolenbroek cl::desc(""), 117*0b98e8aaSDavid van Moolenbroek cl::init(MAP_DEFAULT_MAX_OFFSET_PAGES), cl::NotHidden, cl::ValueRequired); 118*0b98e8aaSDavid van Moolenbroek 119*0b98e8aaSDavid van Moolenbroek static cl::opt<int> 120*0b98e8aaSDavid van Moolenbroek map_max_padding_pages("asr-map-max-padding-pages", 121*0b98e8aaSDavid van Moolenbroek cl::desc(""), 122*0b98e8aaSDavid van Moolenbroek cl::init(MAP_DEFAULT_MAX_PADDING_PAGES), cl::NotHidden, cl::ValueRequired); 123*0b98e8aaSDavid van Moolenbroek 124*0b98e8aaSDavid van Moolenbroek 125*0b98e8aaSDavid van Moolenbroek #define __X(P) #P 126*0b98e8aaSDavid van Moolenbroek std::string magicMemFuncNames[] = { MAGIC_MEM_FUNC_NAMES }; 127*0b98e8aaSDavid van Moolenbroek #undef __X 128*0b98e8aaSDavid van Moolenbroek 129*0b98e8aaSDavid van Moolenbroek namespace llvm { 130*0b98e8aaSDavid van Moolenbroek 131*0b98e8aaSDavid van Moolenbroek PASS_COMMON_INIT_ONCE(); 132*0b98e8aaSDavid van Moolenbroek 133*0b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===// 134*0b98e8aaSDavid van Moolenbroek // Constructors, destructor, and operators 135*0b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===// 136*0b98e8aaSDavid van Moolenbroek 137*0b98e8aaSDavid van Moolenbroek ASRPass::ASRPass() : ModulePass(ID) {} 138*0b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===// 139*0b98e8aaSDavid van Moolenbroek // Public methods 140*0b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===// 141*0b98e8aaSDavid van Moolenbroek 142*0b98e8aaSDavid van Moolenbroek void fillPermutationGenerator(std::vector<unsigned> &permutationGenerator){ 143*0b98e8aaSDavid van Moolenbroek // This function returns a list of indices. In order to create a permutation of a list of elements, for each index, remove that element and place it at the end of the list. 144*0b98e8aaSDavid van Moolenbroek unsigned size = permutationGenerator.size(); 145*0b98e8aaSDavid van Moolenbroek for (unsigned i = 0; i < size; ++i) { 146*0b98e8aaSDavid van Moolenbroek unsigned j = rand() % (size - i); 147*0b98e8aaSDavid van Moolenbroek permutationGenerator[i] = j; 148*0b98e8aaSDavid van Moolenbroek } 149*0b98e8aaSDavid van Moolenbroek } 150*0b98e8aaSDavid van Moolenbroek 151*0b98e8aaSDavid van Moolenbroek Function* getCalledFunctionFromCS(const CallSite &CS) { 152*0b98e8aaSDavid van Moolenbroek assert(CS.getInstruction()); 153*0b98e8aaSDavid van Moolenbroek Function *function = CS.getCalledFunction(); 154*0b98e8aaSDavid van Moolenbroek if(function) { 155*0b98e8aaSDavid van Moolenbroek return function; 156*0b98e8aaSDavid van Moolenbroek } 157*0b98e8aaSDavid van Moolenbroek 158*0b98e8aaSDavid van Moolenbroek //handle the weird case of bitcasted function call 159*0b98e8aaSDavid van Moolenbroek ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue()); 160*0b98e8aaSDavid van Moolenbroek if(!CE) { 161*0b98e8aaSDavid van Moolenbroek return NULL; 162*0b98e8aaSDavid van Moolenbroek } 163*0b98e8aaSDavid van Moolenbroek assert(CE && CE->getOpcode() == Instruction::BitCast && "Bitcast expected, something else found!"); 164*0b98e8aaSDavid van Moolenbroek function = dyn_cast<Function>(CE->getOperand(0)); 165*0b98e8aaSDavid van Moolenbroek assert(function); 166*0b98e8aaSDavid van Moolenbroek 167*0b98e8aaSDavid van Moolenbroek return function; 168*0b98e8aaSDavid van Moolenbroek } 169*0b98e8aaSDavid van Moolenbroek 170*0b98e8aaSDavid van Moolenbroek #define ADVANCE_ITERATOR(IT, N_POS) for(unsigned __adv_it_count=0; __adv_it_count< N_POS; __adv_it_count++){ IT++;} 171*0b98e8aaSDavid van Moolenbroek 172*0b98e8aaSDavid van Moolenbroek GlobalVariable *create_padding_gv(Module &M, GlobalVariable *InsertBefore, int n_bytes){ 173*0b98e8aaSDavid van Moolenbroek 174*0b98e8aaSDavid van Moolenbroek ArrayType* ArrayTy = ArrayType::get(IntegerType::get(M.getContext(), 8), n_bytes); 175*0b98e8aaSDavid van Moolenbroek 176*0b98e8aaSDavid van Moolenbroek GlobalVariable* padding_char_arr = new GlobalVariable(/*Module=*/M, 177*0b98e8aaSDavid van Moolenbroek /*Type=*/ArrayTy, 178*0b98e8aaSDavid van Moolenbroek /*isConstant=*/false, 179*0b98e8aaSDavid van Moolenbroek /*Linkage=*/GlobalValue::InternalLinkage, 180*0b98e8aaSDavid van Moolenbroek /*Initializer=*/ConstantAggregateZero::get(ArrayTy), 181*0b98e8aaSDavid van Moolenbroek /*Name=*/"magic_asr_padding_gv", 182*0b98e8aaSDavid van Moolenbroek /*InsertBefore=*/InsertBefore); 183*0b98e8aaSDavid van Moolenbroek padding_char_arr->setAlignment(1); 184*0b98e8aaSDavid van Moolenbroek padding_char_arr->setSection(InsertBefore->getSection()); 185*0b98e8aaSDavid van Moolenbroek return padding_char_arr; 186*0b98e8aaSDavid van Moolenbroek 187*0b98e8aaSDavid van Moolenbroek } 188*0b98e8aaSDavid van Moolenbroek 189*0b98e8aaSDavid van Moolenbroek AllocaInst *create_padding_lv(Module &M, Instruction *InsertBefore, int n_bytes){ 190*0b98e8aaSDavid van Moolenbroek 191*0b98e8aaSDavid van Moolenbroek ArrayType* ArrayTy = ArrayType::get(IntegerType::get(M.getContext(), 8), n_bytes); 192*0b98e8aaSDavid van Moolenbroek AllocaInst* ptr_x = new AllocaInst(ArrayTy, "magic_asr_padding_lv", InsertBefore); 193*0b98e8aaSDavid van Moolenbroek ptr_x->setAlignment(16); 194*0b98e8aaSDavid van Moolenbroek 195*0b98e8aaSDavid van Moolenbroek /* Seems not to be necessary 196*0b98e8aaSDavid van Moolenbroek 197*0b98e8aaSDavid van Moolenbroek ConstantInt* const_int64_0 = ConstantInt::get(M.getContext(), APInt(64, StringRef("0"), 10)); 198*0b98e8aaSDavid van Moolenbroek ConstantInt* const_int8_0 = ConstantInt::get(M.getContext(), APInt(8, StringRef("97"), 10)); 199*0b98e8aaSDavid van Moolenbroek 200*0b98e8aaSDavid van Moolenbroek std::vector<Value*> ptr_indices; 201*0b98e8aaSDavid van Moolenbroek ptr_indices.push_back(const_int64_0); 202*0b98e8aaSDavid van Moolenbroek ptr_indices.push_back(const_int64_0); 203*0b98e8aaSDavid van Moolenbroek 204*0b98e8aaSDavid van Moolenbroek Instruction* ptr_8 = GetElementPtrInst::Create(ptr_x, ptr_indices.begin(), ptr_indices.end(), "", ptr_x->getParent()); 205*0b98e8aaSDavid van Moolenbroek ptr_8->removeFromParent(); 206*0b98e8aaSDavid van Moolenbroek ptr_8->insertAfter(ptr_x); 207*0b98e8aaSDavid van Moolenbroek 208*0b98e8aaSDavid van Moolenbroek StoreInst* void_9 = new StoreInst(const_int8_0, ptr_8, true, ptr_x->getParent()); 209*0b98e8aaSDavid van Moolenbroek void_9->setAlignment(16); 210*0b98e8aaSDavid van Moolenbroek void_9->removeFromParent(); 211*0b98e8aaSDavid van Moolenbroek void_9->insertAfter(ptr_8); 212*0b98e8aaSDavid van Moolenbroek 213*0b98e8aaSDavid van Moolenbroek */ 214*0b98e8aaSDavid van Moolenbroek 215*0b98e8aaSDavid van Moolenbroek return ptr_x; 216*0b98e8aaSDavid van Moolenbroek 217*0b98e8aaSDavid van Moolenbroek } 218*0b98e8aaSDavid van Moolenbroek 219*0b98e8aaSDavid van Moolenbroek Function *create_padding_func(Module &M, int n_ops){ 220*0b98e8aaSDavid van Moolenbroek /* Places a padding function at the end of the function list */ 221*0b98e8aaSDavid van Moolenbroek 222*0b98e8aaSDavid van Moolenbroek std::vector<TYPECONST Type*>FuncTy_0_args; 223*0b98e8aaSDavid van Moolenbroek TYPECONST FunctionType* FuncTy_0 = FunctionType::get(Type::getVoidTy(M.getContext()), FuncTy_0_args, false); 224*0b98e8aaSDavid van Moolenbroek 225*0b98e8aaSDavid van Moolenbroek Function* func_padding_func = Function::Create(FuncTy_0, GlobalValue::ExternalLinkage, "magic_asr_padding_func", &M); 226*0b98e8aaSDavid van Moolenbroek func_padding_func->setCallingConv(CallingConv::C); 227*0b98e8aaSDavid van Moolenbroek BasicBlock* bb = BasicBlock::Create(M.getContext(), "",func_padding_func,0); 228*0b98e8aaSDavid van Moolenbroek 229*0b98e8aaSDavid van Moolenbroek ConstantInt* const_int32_0 = ConstantInt::get(M.getContext(), APInt(32, StringRef("0"), 10)); 230*0b98e8aaSDavid van Moolenbroek ConstantInt* const_int32_1 = ConstantInt::get(M.getContext(), APInt(32, StringRef("1"), 10)); 231*0b98e8aaSDavid van Moolenbroek 232*0b98e8aaSDavid van Moolenbroek AllocaInst* ptr_x = new AllocaInst(IntegerType::get(M.getContext(), 32), "x", bb); 233*0b98e8aaSDavid van Moolenbroek ptr_x->setAlignment(4); 234*0b98e8aaSDavid van Moolenbroek 235*0b98e8aaSDavid van Moolenbroek StoreInst* void_1 = new StoreInst(const_int32_0, ptr_x, true, bb); 236*0b98e8aaSDavid van Moolenbroek void_1->setAlignment(4); 237*0b98e8aaSDavid van Moolenbroek 238*0b98e8aaSDavid van Moolenbroek for(int i=0; i< n_ops; i++){ 239*0b98e8aaSDavid van Moolenbroek LoadInst* load_x = new LoadInst(ptr_x, "", true, bb); 240*0b98e8aaSDavid van Moolenbroek load_x->setAlignment(4); 241*0b98e8aaSDavid van Moolenbroek 242*0b98e8aaSDavid van Moolenbroek BinaryOperator* add_x = BinaryOperator::Create(Instruction::Add, load_x, const_int32_1, "", bb); 243*0b98e8aaSDavid van Moolenbroek 244*0b98e8aaSDavid van Moolenbroek StoreInst* void_2 = new StoreInst(add_x, ptr_x, true, bb); 245*0b98e8aaSDavid van Moolenbroek void_2->setAlignment(4); 246*0b98e8aaSDavid van Moolenbroek } 247*0b98e8aaSDavid van Moolenbroek 248*0b98e8aaSDavid van Moolenbroek ReturnInst::Create(M.getContext(), bb); 249*0b98e8aaSDavid van Moolenbroek 250*0b98e8aaSDavid van Moolenbroek return func_padding_func; 251*0b98e8aaSDavid van Moolenbroek } 252*0b98e8aaSDavid van Moolenbroek 253*0b98e8aaSDavid van Moolenbroek StringRef getStringRefFromInt(int i){ 254*0b98e8aaSDavid van Moolenbroek std::stringstream stm; 255*0b98e8aaSDavid van Moolenbroek stm << i; 256*0b98e8aaSDavid van Moolenbroek return StringRef(*new std::string(stm.str())); 257*0b98e8aaSDavid van Moolenbroek } 258*0b98e8aaSDavid van Moolenbroek 259*0b98e8aaSDavid van Moolenbroek bool ASRPass::runOnModule(Module &M) { 260*0b98e8aaSDavid van Moolenbroek 261*0b98e8aaSDavid van Moolenbroek Module::GlobalListType &globalList = M.getGlobalList(); 262*0b98e8aaSDavid van Moolenbroek Module::FunctionListType &functionList = M.getFunctionList(); 263*0b98e8aaSDavid van Moolenbroek int runtime_seed = seed; 264*0b98e8aaSDavid van Moolenbroek 265*0b98e8aaSDavid van Moolenbroek Function *magicEntryPointFunc = M.getFunction(MAGIC_ENTRY_POINT); 266*0b98e8aaSDavid van Moolenbroek if( !magicEntryPointFunc ){ 267*0b98e8aaSDavid van Moolenbroek //if no valid entry point, we are not compiling a valid program, skip pass 268*0b98e8aaSDavid van Moolenbroek return false; 269*0b98e8aaSDavid van Moolenbroek } 270*0b98e8aaSDavid van Moolenbroek 271*0b98e8aaSDavid van Moolenbroek Function *magicInitFunc = M.getFunction(MAGIC_INIT_FUNC_NAME); 272*0b98e8aaSDavid van Moolenbroek if( !magicInitFunc ){ 273*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_INIT_FUNC_NAME << "() found"; 274*0b98e8aaSDavid van Moolenbroek exit(1); 275*0b98e8aaSDavid van Moolenbroek } 276*0b98e8aaSDavid van Moolenbroek 277*0b98e8aaSDavid van Moolenbroek { 278*0b98e8aaSDavid van Moolenbroek // get random seed number, or use the current time if the seed number is set to 0. 279*0b98e8aaSDavid van Moolenbroek if(!seed){ 280*0b98e8aaSDavid van Moolenbroek seed = time(NULL); 281*0b98e8aaSDavid van Moolenbroek } 282*0b98e8aaSDavid van Moolenbroek srand(seed); 283*0b98e8aaSDavid van Moolenbroek 284*0b98e8aaSDavid van Moolenbroek }{ 285*0b98e8aaSDavid van Moolenbroek 286*0b98e8aaSDavid van Moolenbroek /* Randomly offset and permutate list of global variables, and insert random padding between neighbouring global variables */ 287*0b98e8aaSDavid van Moolenbroek 288*0b98e8aaSDavid van Moolenbroek std::vector<unsigned> pg(globalList.size()); 289*0b98e8aaSDavid van Moolenbroek fillPermutationGenerator(pg); 290*0b98e8aaSDavid van Moolenbroek 291*0b98e8aaSDavid van Moolenbroek for(unsigned i=0; i < pg.size(); i++){ 292*0b98e8aaSDavid van Moolenbroek Module::global_iterator it = globalList.begin(); 293*0b98e8aaSDavid van Moolenbroek // get the next random global variable 294*0b98e8aaSDavid van Moolenbroek ADVANCE_ITERATOR(it, pg[i]); 295*0b98e8aaSDavid van Moolenbroek // skip certain variables 296*0b98e8aaSDavid van Moolenbroek if(it->getName().startswith("llvm.") 297*0b98e8aaSDavid van Moolenbroek || it->getLinkage() == GlobalValue::ExternalWeakLinkage){ 298*0b98e8aaSDavid van Moolenbroek continue; 299*0b98e8aaSDavid van Moolenbroek } 300*0b98e8aaSDavid van Moolenbroek if(it->getLinkage() != GlobalValue::ExternalLinkage && it->getName().compare("environ")){ 301*0b98e8aaSDavid van Moolenbroek // This prevents most public global variables (common linkage, but not external linkage) to be kept in the same order 302*0b98e8aaSDavid van Moolenbroek it->setLinkage(GlobalValue::InternalLinkage); 303*0b98e8aaSDavid van Moolenbroek } 304*0b98e8aaSDavid van Moolenbroek if(gv_do_permutate){ 305*0b98e8aaSDavid van Moolenbroek // randomize the order of variables, by removing the global variable, and putting it at the end of globalList 306*0b98e8aaSDavid van Moolenbroek GlobalVariable *gv = globalList.remove(it); 307*0b98e8aaSDavid van Moolenbroek globalList.push_back(gv); 308*0b98e8aaSDavid van Moolenbroek it = --globalList.end(); 309*0b98e8aaSDavid van Moolenbroek } 310*0b98e8aaSDavid van Moolenbroek // put a padding variable between each two adjacent global variables, and place a big offset before the first global variable 311*0b98e8aaSDavid van Moolenbroek int max_padding = i == 0 ? gv_max_offset : gv_max_padding; 312*0b98e8aaSDavid van Moolenbroek if(max_padding > 0){ 313*0b98e8aaSDavid van Moolenbroek create_padding_gv(M, it, (rand () % max_padding) + 1); 314*0b98e8aaSDavid van Moolenbroek } 315*0b98e8aaSDavid van Moolenbroek } 316*0b98e8aaSDavid van Moolenbroek 317*0b98e8aaSDavid van Moolenbroek }{ 318*0b98e8aaSDavid van Moolenbroek 319*0b98e8aaSDavid van Moolenbroek /* Randomly offset and permutate function list, and insert random padding between neighbouring functions. */ 320*0b98e8aaSDavid van Moolenbroek 321*0b98e8aaSDavid van Moolenbroek std::vector<unsigned> pg(functionList.size()); 322*0b98e8aaSDavid van Moolenbroek fillPermutationGenerator(pg); 323*0b98e8aaSDavid van Moolenbroek 324*0b98e8aaSDavid van Moolenbroek for(unsigned i=0; i < pg.size(); i++){ 325*0b98e8aaSDavid van Moolenbroek Module::iterator it = functionList.begin(); 326*0b98e8aaSDavid van Moolenbroek if(func_do_permutate){ 327*0b98e8aaSDavid van Moolenbroek /* randomize the order of functions, just like we did with the global variables if permutions is disabled, we end up with the same order of functions */ 328*0b98e8aaSDavid van Moolenbroek ADVANCE_ITERATOR(it, pg[i]); 329*0b98e8aaSDavid van Moolenbroek } 330*0b98e8aaSDavid van Moolenbroek Function *F = functionList.remove(it); 331*0b98e8aaSDavid van Moolenbroek functionList.push_back(F); 332*0b98e8aaSDavid van Moolenbroek /* place a padding function at the end of the function list, behind the current function */ 333*0b98e8aaSDavid van Moolenbroek int max_padding = i == 0 ? func_max_offset : func_max_padding; 334*0b98e8aaSDavid van Moolenbroek if(max_padding > 0){ 335*0b98e8aaSDavid van Moolenbroek create_padding_func(M, (rand () % (max_padding/2)) + (max_padding/2)); 336*0b98e8aaSDavid van Moolenbroek } 337*0b98e8aaSDavid van Moolenbroek } 338*0b98e8aaSDavid van Moolenbroek 339*0b98e8aaSDavid van Moolenbroek }{ 340*0b98e8aaSDavid van Moolenbroek 341*0b98e8aaSDavid van Moolenbroek 342*0b98e8aaSDavid van Moolenbroek /* permutate and pad local function variables, and create dynamically randomized stack and stack frame offsets */ 343*0b98e8aaSDavid van Moolenbroek 344*0b98e8aaSDavid van Moolenbroek for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) { 345*0b98e8aaSDavid van Moolenbroek Function *F = it; 346*0b98e8aaSDavid van Moolenbroek 347*0b98e8aaSDavid van Moolenbroek /* skip certain functions */ 348*0b98e8aaSDavid van Moolenbroek if(F->getBasicBlockList().size() == 0){ 349*0b98e8aaSDavid van Moolenbroek continue; 350*0b98e8aaSDavid van Moolenbroek } 351*0b98e8aaSDavid van Moolenbroek if(MAGIC_IS_MAGIC_FUNC(M, F)){ 352*0b98e8aaSDavid van Moolenbroek continue; 353*0b98e8aaSDavid van Moolenbroek } 354*0b98e8aaSDavid van Moolenbroek if(!F->getName().compare("rand")){ 355*0b98e8aaSDavid van Moolenbroek continue; 356*0b98e8aaSDavid van Moolenbroek } 357*0b98e8aaSDavid van Moolenbroek 358*0b98e8aaSDavid van Moolenbroek 359*0b98e8aaSDavid van Moolenbroek /* find all allocation instructions in order to pad them. */ 360*0b98e8aaSDavid van Moolenbroek 361*0b98e8aaSDavid van Moolenbroek /* Helper vectors to store all alloca instructions temporarily. 362*0b98e8aaSDavid van Moolenbroek * Make two collections, depending on whether the address of the variable is taken and used as a pointer. 363*0b98e8aaSDavid van Moolenbroek * (Because pointer dereferencing, buffer overflow, etc. add extra risks to those variables that have their addresses taken) 364*0b98e8aaSDavid van Moolenbroek * We order the allocation instructions as follows: 365*0b98e8aaSDavid van Moolenbroek * - First, we allocate the ones that don't have their address taken, only permutated. 366*0b98e8aaSDavid van Moolenbroek * - Then, we allocate an stack frame offset (dynamically randomly sized). 367*0b98e8aaSDavid van Moolenbroek * - After the stack frame offset, we allocate those that have their address taken, with permutation and padding. 368*0b98e8aaSDavid van Moolenbroek * Because the majority doesn't have its address taken, most variables are allocated in the first basic block, before the stack frame offset allocation. 369*0b98e8aaSDavid van Moolenbroek * This gives the extra advantages that those allocations are folded into the prolog/epilog code by the code generator, for extra performance. 370*0b98e8aaSDavid van Moolenbroek * (See AllocaInst::isStaticAlloca() in llvm/Instructions.h) 371*0b98e8aaSDavid van Moolenbroek * */ 372*0b98e8aaSDavid van Moolenbroek std::vector<Instruction *> allocaAddressTaken, allocaNoAddressTaken; 373*0b98e8aaSDavid van Moolenbroek 374*0b98e8aaSDavid van Moolenbroek /* Only the first basic block contains alloca instructions */ 375*0b98e8aaSDavid van Moolenbroek BasicBlock *BB = F->getBasicBlockList().begin(); 376*0b98e8aaSDavid van Moolenbroek 377*0b98e8aaSDavid van Moolenbroek /* with each iteration, one of these integers will be incremented/decremented */ 378*0b98e8aaSDavid van Moolenbroek unsigned bb_size = BB->getInstList().size(); 379*0b98e8aaSDavid van Moolenbroek unsigned pos = 0; 380*0b98e8aaSDavid van Moolenbroek while(pos < bb_size){ 381*0b98e8aaSDavid van Moolenbroek 382*0b98e8aaSDavid van Moolenbroek /* check if instruction at position <pos> is an allocation instruction. 383*0b98e8aaSDavid van Moolenbroek * If, so remove and put in one of the helper vectors 384*0b98e8aaSDavid van Moolenbroek * */ 385*0b98e8aaSDavid van Moolenbroek 386*0b98e8aaSDavid van Moolenbroek BasicBlock::iterator it = BB->getInstList().begin(); 387*0b98e8aaSDavid van Moolenbroek /* move to current position in instruction list */ 388*0b98e8aaSDavid van Moolenbroek ADVANCE_ITERATOR(it, pos); 389*0b98e8aaSDavid van Moolenbroek Instruction *inst = &(*it); 390*0b98e8aaSDavid van Moolenbroek if (AllocaInst *allocaInst = dyn_cast<AllocaInst>(inst)){ 391*0b98e8aaSDavid van Moolenbroek /* this is an allocation instruction. insert it at the front of of the right helper vector 392*0b98e8aaSDavid van Moolenbroek * (last found allocation instruction will be at the front), and remove it from the basic block. 393*0b98e8aaSDavid van Moolenbroek * */ 394*0b98e8aaSDavid van Moolenbroek int hasAddressTaken = 0; 395*0b98e8aaSDavid van Moolenbroek for (Value::use_iterator UI = allocaInst->use_begin(), E = allocaInst->use_end(); UI != E; ++UI) { 396*0b98e8aaSDavid van Moolenbroek 397*0b98e8aaSDavid van Moolenbroek /* Loop through all the Uses of this allocation function. */ 398*0b98e8aaSDavid van Moolenbroek 399*0b98e8aaSDavid van Moolenbroek User *U = *UI; 400*0b98e8aaSDavid van Moolenbroek if(dyn_cast<LoadInst>(U) || dyn_cast<StoreInst>(U)){ 401*0b98e8aaSDavid van Moolenbroek /* This is a load or store instruction, which does not 402*0b98e8aaSDavid van Moolenbroek * indicate that a pointer of this variable is generated 403*0b98e8aaSDavid van Moolenbroek * */ 404*0b98e8aaSDavid van Moolenbroek continue; 405*0b98e8aaSDavid van Moolenbroek }else if(CallInst *cInst = dyn_cast<CallInst>(U)){ 406*0b98e8aaSDavid van Moolenbroek if(cInst->getCalledFunction() && MAGIC_IS_MAGIC_FUNC(M, cInst->getCalledFunction())){ 407*0b98e8aaSDavid van Moolenbroek /* This is a function call instruction, but this 408*0b98e8aaSDavid van Moolenbroek * concerns a magic library function, so it does not count as a generated pointer. 409*0b98e8aaSDavid van Moolenbroek * Any other functions calls would have set hasAddressTaken to 1 */ 410*0b98e8aaSDavid van Moolenbroek continue; 411*0b98e8aaSDavid van Moolenbroek } 412*0b98e8aaSDavid van Moolenbroek } 413*0b98e8aaSDavid van Moolenbroek /* This instruction will (likely) create a pointer, because it is not a load, store or magic-function-call instruction */ 414*0b98e8aaSDavid van Moolenbroek hasAddressTaken = 1; 415*0b98e8aaSDavid van Moolenbroek break; 416*0b98e8aaSDavid van Moolenbroek } 417*0b98e8aaSDavid van Moolenbroek 418*0b98e8aaSDavid van Moolenbroek /* Put the alloca instruction in the right helper vector, and remove from the basic block. */ 419*0b98e8aaSDavid van Moolenbroek if(hasAddressTaken){ 420*0b98e8aaSDavid van Moolenbroek allocaAddressTaken.insert(allocaAddressTaken.begin(), it); 421*0b98e8aaSDavid van Moolenbroek }else{ 422*0b98e8aaSDavid van Moolenbroek allocaNoAddressTaken.insert(allocaNoAddressTaken.begin(), it); 423*0b98e8aaSDavid van Moolenbroek } 424*0b98e8aaSDavid van Moolenbroek it->removeFromParent(); 425*0b98e8aaSDavid van Moolenbroek bb_size--; 426*0b98e8aaSDavid van Moolenbroek }else{ 427*0b98e8aaSDavid van Moolenbroek pos++; 428*0b98e8aaSDavid van Moolenbroek } 429*0b98e8aaSDavid van Moolenbroek } 430*0b98e8aaSDavid van Moolenbroek 431*0b98e8aaSDavid van Moolenbroek /* Permutate and pad the alloca instructions whose addresses are taken. */ 432*0b98e8aaSDavid van Moolenbroek 433*0b98e8aaSDavid van Moolenbroek std::vector<unsigned> pg(allocaAddressTaken.size()); 434*0b98e8aaSDavid van Moolenbroek fillPermutationGenerator(pg); 435*0b98e8aaSDavid van Moolenbroek for(unsigned i=0; i<pg.size(); i++){ 436*0b98e8aaSDavid van Moolenbroek /* get the iterator for the first element of the helper vector */ 437*0b98e8aaSDavid van Moolenbroek std::vector<Instruction *>::iterator it = allocaAddressTaken.begin(); 438*0b98e8aaSDavid van Moolenbroek if(stackframe_do_permutate){ 439*0b98e8aaSDavid van Moolenbroek /* get the iterator for the next random element. When permutation is disabled, it keeps pointing to the first element */ 440*0b98e8aaSDavid van Moolenbroek ADVANCE_ITERATOR(it, pg[i]); 441*0b98e8aaSDavid van Moolenbroek } 442*0b98e8aaSDavid van Moolenbroek /* put the variable at the front of the basic block, and remove it from the helper vector. 443*0b98e8aaSDavid van Moolenbroek * This way, the variable that is added last will be at the front 444*0b98e8aaSDavid van Moolenbroek * */ 445*0b98e8aaSDavid van Moolenbroek BB->getInstList().push_front(*it); 446*0b98e8aaSDavid van Moolenbroek allocaAddressTaken.erase(it); 447*0b98e8aaSDavid van Moolenbroek 448*0b98e8aaSDavid van Moolenbroek /* put a padding variable between each two adjacent local variables 449*0b98e8aaSDavid van Moolenbroek * this is done by inserting a padding var at the front each time a 450*0b98e8aaSDavid van Moolenbroek * var has been put at the front with push_front(). 451*0b98e8aaSDavid van Moolenbroek * */ 452*0b98e8aaSDavid van Moolenbroek int max_padding = (i==pg.size()-1 ? 0 : stackframe_max_padding); 453*0b98e8aaSDavid van Moolenbroek if(max_padding > 0){ 454*0b98e8aaSDavid van Moolenbroek create_padding_lv(M, BB->getInstList().begin(), (rand () % max_padding) + 1); 455*0b98e8aaSDavid van Moolenbroek } 456*0b98e8aaSDavid van Moolenbroek } 457*0b98e8aaSDavid van Moolenbroek 458*0b98e8aaSDavid van Moolenbroek 459*0b98e8aaSDavid van Moolenbroek /* Create a global stack offset, and an offset for each stack frame. Both have a dynamic random size */ 460*0b98e8aaSDavid van Moolenbroek 461*0b98e8aaSDavid van Moolenbroek /* Determine if we must pad or offset, and how much */ 462*0b98e8aaSDavid van Moolenbroek int max_offset, do_offset=1; 463*0b98e8aaSDavid van Moolenbroek if(F->getName().equals(MAGIC_ENTRY_POINT)){ 464*0b98e8aaSDavid van Moolenbroek if(!stack_do_offset){ 465*0b98e8aaSDavid van Moolenbroek do_offset=0; 466*0b98e8aaSDavid van Moolenbroek } 467*0b98e8aaSDavid van Moolenbroek /* give the entry function (first function) a large offset instead of an padding */ 468*0b98e8aaSDavid van Moolenbroek max_offset = stack_max_offset; 469*0b98e8aaSDavid van Moolenbroek }else{ 470*0b98e8aaSDavid van Moolenbroek if(!stackframe_do_offset){ 471*0b98e8aaSDavid van Moolenbroek do_offset=0; 472*0b98e8aaSDavid van Moolenbroek } 473*0b98e8aaSDavid van Moolenbroek max_offset = stackframe_max_offset; 474*0b98e8aaSDavid van Moolenbroek } 475*0b98e8aaSDavid van Moolenbroek 476*0b98e8aaSDavid van Moolenbroek /* Create a new block before the first block. Now, all the variable allocations whose addresses are taken are no longer 477*0b98e8aaSDavid van Moolenbroek * in the first block, so CallInst::isStaticAlloca() does no longer apply to them. 478*0b98e8aaSDavid van Moolenbroek * When isStaticAlloca() == true, the code generator will fold it into the prolog/epilog code, so it is basically free. 479*0b98e8aaSDavid van Moolenbroek * This means that we now get less efficient code. 480*0b98e8aaSDavid van Moolenbroek * This is necessary to prevent the variables whose address is taken from being allocated before the stack frame offset is allocated. 481*0b98e8aaSDavid van Moolenbroek * Alternatively, we could allocate before the function call, instead of after. */ 482*0b98e8aaSDavid van Moolenbroek 483*0b98e8aaSDavid van Moolenbroek BasicBlock *OldFirstBB = F->getBasicBlockList().begin(); 484*0b98e8aaSDavid van Moolenbroek BasicBlock *NewFirstBB = BasicBlock::Create(M.getContext(), "newBB", F, OldFirstBB); 485*0b98e8aaSDavid van Moolenbroek 486*0b98e8aaSDavid van Moolenbroek 487*0b98e8aaSDavid van Moolenbroek /* Permutate and insert the allocation instructions whose addresses are NOT taken into the new first block (dont apply padding). 488*0b98e8aaSDavid van Moolenbroek * These must be allocated before the stack frame offset is allocated. */ 489*0b98e8aaSDavid van Moolenbroek 490*0b98e8aaSDavid van Moolenbroek pg = std::vector<unsigned>(allocaNoAddressTaken.size()); 491*0b98e8aaSDavid van Moolenbroek fillPermutationGenerator(pg); 492*0b98e8aaSDavid van Moolenbroek for(unsigned i=0; i<pg.size(); i++){ 493*0b98e8aaSDavid van Moolenbroek /* get the iterator for the first element of the helper vector */ 494*0b98e8aaSDavid van Moolenbroek std::vector<Instruction *>::iterator it = allocaNoAddressTaken.begin(); 495*0b98e8aaSDavid van Moolenbroek if(stackframe_do_permutate){ 496*0b98e8aaSDavid van Moolenbroek /* get the iterator for the next random element. When permutation is disabled, it keeps pointing to the first element */ 497*0b98e8aaSDavid van Moolenbroek ADVANCE_ITERATOR(it, pg[i]); 498*0b98e8aaSDavid van Moolenbroek } 499*0b98e8aaSDavid van Moolenbroek /* put the variable at the front of the basic block, and remove it from the helper vector. 500*0b98e8aaSDavid van Moolenbroek * This way, the variable that is added last will be at the front 501*0b98e8aaSDavid van Moolenbroek * */ 502*0b98e8aaSDavid van Moolenbroek NewFirstBB->getInstList().push_front(*it); 503*0b98e8aaSDavid van Moolenbroek allocaNoAddressTaken.erase(it); 504*0b98e8aaSDavid van Moolenbroek } 505*0b98e8aaSDavid van Moolenbroek 506*0b98e8aaSDavid van Moolenbroek if(do_offset){ 507*0b98e8aaSDavid van Moolenbroek if(stackframe_static_padding) { 508*0b98e8aaSDavid van Moolenbroek if(max_offset > 0) { 509*0b98e8aaSDavid van Moolenbroek new AllocaInst(IntegerType::get(M.getContext(), 8), ConstantInt::get(M.getContext(), APInt(64, (rand() % max_offset) + 1, 10)), "", NewFirstBB); 510*0b98e8aaSDavid van Moolenbroek } 511*0b98e8aaSDavid van Moolenbroek } 512*0b98e8aaSDavid van Moolenbroek else { 513*0b98e8aaSDavid van Moolenbroek /* Now insert a dynamically randomized stackframe offset */ 514*0b98e8aaSDavid van Moolenbroek Function *RandFunc = M.getFunction("rand"); 515*0b98e8aaSDavid van Moolenbroek assert(RandFunc != NULL); 516*0b98e8aaSDavid van Moolenbroek 517*0b98e8aaSDavid van Moolenbroek /* Call rand() */ 518*0b98e8aaSDavid van Moolenbroek std::vector<Value*> args; 519*0b98e8aaSDavid van Moolenbroek CallInst* RandFuncCall = PassUtil::createCallInstruction(RandFunc, args, "", NewFirstBB); 520*0b98e8aaSDavid van Moolenbroek Instruction *nextInst = RandFuncCall; 521*0b98e8aaSDavid van Moolenbroek 522*0b98e8aaSDavid van Moolenbroek if(max_offset > 0){ 523*0b98e8aaSDavid van Moolenbroek /* limit the rand value: rand() % max_offet */ 524*0b98e8aaSDavid van Moolenbroek ConstantInt* max_offset_const = ConstantInt::get(M.getContext(), APInt(32, max_offset, 10)); 525*0b98e8aaSDavid van Moolenbroek BinaryOperator *Remainder = BinaryOperator::Create(Instruction::SRem, RandFuncCall, max_offset_const, "", NewFirstBB); 526*0b98e8aaSDavid van Moolenbroek Remainder->removeFromParent(); 527*0b98e8aaSDavid van Moolenbroek Remainder->insertAfter(RandFuncCall); 528*0b98e8aaSDavid van Moolenbroek nextInst = Remainder; 529*0b98e8aaSDavid van Moolenbroek } 530*0b98e8aaSDavid van Moolenbroek 531*0b98e8aaSDavid van Moolenbroek /* Minimum rand value must be 1, so increment it. */ 532*0b98e8aaSDavid van Moolenbroek ConstantInt* One = ConstantInt::get(M.getContext(), APInt(32, StringRef("1"), 10)); 533*0b98e8aaSDavid van Moolenbroek BinaryOperator* AddOne = BinaryOperator::Create(Instruction::Add, nextInst, One, "", NewFirstBB); 534*0b98e8aaSDavid van Moolenbroek AddOne->removeFromParent(); 535*0b98e8aaSDavid van Moolenbroek AddOne->insertAfter(nextInst); 536*0b98e8aaSDavid van Moolenbroek 537*0b98e8aaSDavid van Moolenbroek /* Allocate the offset/padding */ 538*0b98e8aaSDavid van Moolenbroek AllocaInst* allocaInstruction = new AllocaInst(IntegerType::get(M.getContext(), 8), AddOne, "", NewFirstBB); 539*0b98e8aaSDavid van Moolenbroek allocaInstruction->removeFromParent(); 540*0b98e8aaSDavid van Moolenbroek allocaInstruction->insertAfter(AddOne); 541*0b98e8aaSDavid van Moolenbroek 542*0b98e8aaSDavid van Moolenbroek /* Inline the rand() call. */ 543*0b98e8aaSDavid van Moolenbroek InlineFunctionInfo IFI; 544*0b98e8aaSDavid van Moolenbroek InlineFunction(RandFuncCall, IFI); 545*0b98e8aaSDavid van Moolenbroek } 546*0b98e8aaSDavid van Moolenbroek } 547*0b98e8aaSDavid van Moolenbroek 548*0b98e8aaSDavid van Moolenbroek /* Go to the old first block */ 549*0b98e8aaSDavid van Moolenbroek BranchInst *br = BranchInst::Create (OldFirstBB, NewFirstBB); 550*0b98e8aaSDavid van Moolenbroek br->setSuccessor(0, OldFirstBB); 551*0b98e8aaSDavid van Moolenbroek 552*0b98e8aaSDavid van Moolenbroek /* Static stack frame padding does not really need 2 basic blocks, but it may need call site instrumentation. */ 553*0b98e8aaSDavid van Moolenbroek if(stackframe_static_padding) { 554*0b98e8aaSDavid van Moolenbroek bool ret = MergeBlockIntoPredecessor(OldFirstBB, this); 555*0b98e8aaSDavid van Moolenbroek assert(ret); 556*0b98e8aaSDavid van Moolenbroek 557*0b98e8aaSDavid van Moolenbroek if(stackframe_caller_padding && max_offset > 0) { 558*0b98e8aaSDavid van Moolenbroek std::vector<User*> Users(F->use_begin(), F->use_end()); 559*0b98e8aaSDavid van Moolenbroek while (!Users.empty()) { 560*0b98e8aaSDavid van Moolenbroek User *U = Users.back(); 561*0b98e8aaSDavid van Moolenbroek Users.pop_back(); 562*0b98e8aaSDavid van Moolenbroek if (Instruction *I = dyn_cast<Instruction>(U)) { 563*0b98e8aaSDavid van Moolenbroek Function *parent = I->getParent()->getParent(); 564*0b98e8aaSDavid van Moolenbroek /* XXX Skipping MAGIC_ENTRY_POINT shouldn't be necessary. Check why. */ 565*0b98e8aaSDavid van Moolenbroek if(MAGIC_IS_MAGIC_FUNC(M, parent) || parent->getName().equals(MAGIC_ENTRY_POINT)) { 566*0b98e8aaSDavid van Moolenbroek continue; 567*0b98e8aaSDavid van Moolenbroek } 568*0b98e8aaSDavid van Moolenbroek CallSite CS = PassUtil::getCallSiteFromInstruction(I); 569*0b98e8aaSDavid van Moolenbroek if(!CS.getInstruction()) { 570*0b98e8aaSDavid van Moolenbroek continue; 571*0b98e8aaSDavid van Moolenbroek } 572*0b98e8aaSDavid van Moolenbroek Function *calledFunction = getCalledFunctionFromCS(CS); 573*0b98e8aaSDavid van Moolenbroek if (CS.getInstruction() && !CS.arg_empty() && (calledFunction == F || calledFunction == NULL)) { 574*0b98e8aaSDavid van Moolenbroek new AllocaInst(IntegerType::get(M.getContext(), 8), ConstantInt::get(M.getContext(), APInt(64, (rand() % max_offset) + 1, 10)), "", I); 575*0b98e8aaSDavid van Moolenbroek } 576*0b98e8aaSDavid van Moolenbroek } 577*0b98e8aaSDavid van Moolenbroek } 578*0b98e8aaSDavid van Moolenbroek } 579*0b98e8aaSDavid van Moolenbroek } 580*0b98e8aaSDavid van Moolenbroek 581*0b98e8aaSDavid van Moolenbroek /* Basic block shifting. */ 582*0b98e8aaSDavid van Moolenbroek if(func_max_bb_shift > 0) { 583*0b98e8aaSDavid van Moolenbroek Instruction *I; 584*0b98e8aaSDavid van Moolenbroek PassUtil::getAllocaInfo(F, NULL, &I); 585*0b98e8aaSDavid van Moolenbroek BasicBlock *firstBB = F->getBasicBlockList().begin(); 586*0b98e8aaSDavid van Moolenbroek BasicBlock *splitBB = firstBB->splitBasicBlock(I, "split"); 587*0b98e8aaSDavid van Moolenbroek BasicBlock *dummyBB = BasicBlock::Create(M.getContext(), "dummy", F, splitBB); 588*0b98e8aaSDavid van Moolenbroek if(!stackframe_caller_padding) { 589*0b98e8aaSDavid van Moolenbroek firstBB = NewFirstBB; 590*0b98e8aaSDavid van Moolenbroek } 591*0b98e8aaSDavid van Moolenbroek 592*0b98e8aaSDavid van Moolenbroek /* Fill the dummy basic block with dummy instructions (using the prefetch intrinsic to emulate nop instructions), to shift the next basic block. */ 593*0b98e8aaSDavid van Moolenbroek Function *prefetchIntrinsic = PassUtil::getIntrinsicFunction(M, Intrinsic::prefetch); 594*0b98e8aaSDavid van Moolenbroek std::vector<Value*> args; 595*0b98e8aaSDavid van Moolenbroek args.push_back(ConstantPointerNull::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0))); 596*0b98e8aaSDavid van Moolenbroek args.push_back(ConstantInt::get(M.getContext(), APInt(32, 0))); 597*0b98e8aaSDavid van Moolenbroek args.push_back(ConstantInt::get(M.getContext(), APInt(32, 0))); 598*0b98e8aaSDavid van Moolenbroek #if LLVM_VERSION >= 30 599*0b98e8aaSDavid van Moolenbroek args.push_back(ConstantInt::get(M.getContext(), APInt(32, 0))); 600*0b98e8aaSDavid van Moolenbroek #endif 601*0b98e8aaSDavid van Moolenbroek unsigned shift = (rand() % func_max_bb_shift) + 1; 602*0b98e8aaSDavid van Moolenbroek do { 603*0b98e8aaSDavid van Moolenbroek PassUtil::createCallInstruction(prefetchIntrinsic, args, "", dummyBB); 604*0b98e8aaSDavid van Moolenbroek shift--; 605*0b98e8aaSDavid van Moolenbroek } while(shift > 0); 606*0b98e8aaSDavid van Moolenbroek BranchInst *br = BranchInst::Create (splitBB, dummyBB); 607*0b98e8aaSDavid van Moolenbroek br->setSuccessor(0, splitBB); 608*0b98e8aaSDavid van Moolenbroek 609*0b98e8aaSDavid van Moolenbroek /* Place an opaque conditional branch (always unconditionally skips the dummy basic block). */ 610*0b98e8aaSDavid van Moolenbroek Function *frameAddrIntrinsic = PassUtil::getIntrinsicFunction(M, Intrinsic::frameaddress); 611*0b98e8aaSDavid van Moolenbroek std::vector<Value*> frameAddrArgs; 612*0b98e8aaSDavid van Moolenbroek frameAddrArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, 0))); 613*0b98e8aaSDavid van Moolenbroek Value *frameAddr = PassUtil::createCallInstruction(frameAddrIntrinsic, frameAddrArgs, "", firstBB->getTerminator()); 614*0b98e8aaSDavid van Moolenbroek TerminatorInst *OldTI = firstBB->getTerminator(); 615*0b98e8aaSDavid van Moolenbroek IRBuilder<> Builder(firstBB); 616*0b98e8aaSDavid van Moolenbroek ICmpInst* ExtraCase = new ICmpInst(OldTI, ICmpInst::ICMP_EQ, frameAddr, ConstantPointerNull::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0)), ""); 617*0b98e8aaSDavid van Moolenbroek Builder.CreateCondBr(ExtraCase, dummyBB, splitBB); 618*0b98e8aaSDavid van Moolenbroek OldTI->eraseFromParent(); 619*0b98e8aaSDavid van Moolenbroek } 620*0b98e8aaSDavid van Moolenbroek } 621*0b98e8aaSDavid van Moolenbroek 622*0b98e8aaSDavid van Moolenbroek }{ 623*0b98e8aaSDavid van Moolenbroek 624*0b98e8aaSDavid van Moolenbroek 625*0b98e8aaSDavid van Moolenbroek #define __X(VAR) __XX(VAR) 626*0b98e8aaSDavid van Moolenbroek #define __XX(VAR) #VAR 627*0b98e8aaSDavid van Moolenbroek 628*0b98e8aaSDavid van Moolenbroek /* heap and map padding */ 629*0b98e8aaSDavid van Moolenbroek 630*0b98e8aaSDavid van Moolenbroek { 631*0b98e8aaSDavid van Moolenbroek 632*0b98e8aaSDavid van Moolenbroek /* Inject magic init call at the beginning of magic entry point function (before any allocaInsts). 633*0b98e8aaSDavid van Moolenbroek * Magic_init will return immediately if called for the second time, so both the magic pass and 634*0b98e8aaSDavid van Moolenbroek * this pass can insert call instructions into main 635*0b98e8aaSDavid van Moolenbroek * */ 636*0b98e8aaSDavid van Moolenbroek std::vector<Value*> args; 637*0b98e8aaSDavid van Moolenbroek PassUtil::createCallInstruction(magicInitFunc, args, "", magicEntryPointFunc->getBasicBlockList().begin()->begin()); 638*0b98e8aaSDavid van Moolenbroek 639*0b98e8aaSDavid van Moolenbroek }{ 640*0b98e8aaSDavid van Moolenbroek 641*0b98e8aaSDavid van Moolenbroek /* set the global variables */ 642*0b98e8aaSDavid van Moolenbroek 643*0b98e8aaSDavid van Moolenbroek Function *magicDataInitFunc = M.getFunction(MAGIC_DATA_INIT_FUNC_NAME); 644*0b98e8aaSDavid van Moolenbroek if(!magicDataInitFunc){ 645*0b98e8aaSDavid van Moolenbroek outs() <<"Error: no " << MAGIC_DATA_INIT_FUNC_NAME << "() found"; 646*0b98e8aaSDavid van Moolenbroek exit(1); 647*0b98e8aaSDavid van Moolenbroek } 648*0b98e8aaSDavid van Moolenbroek Instruction *magicArrayBuildFuncInst = magicDataInitFunc->back().getTerminator(); 649*0b98e8aaSDavid van Moolenbroek 650*0b98e8aaSDavid van Moolenbroek GlobalVariable* magicRootVar = M.getNamedGlobal(MAGIC_ROOT_VAR_NAME); 651*0b98e8aaSDavid van Moolenbroek if(!magicRootVar) { 652*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_ROOT_VAR_NAME << " variable found"; 653*0b98e8aaSDavid van Moolenbroek exit(1); 654*0b98e8aaSDavid van Moolenbroek } 655*0b98e8aaSDavid van Moolenbroek 656*0b98e8aaSDavid van Moolenbroek Value *seedValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_SEED); 657*0b98e8aaSDavid van Moolenbroek if(!seedValue) { 658*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_SEED << " field found"; 659*0b98e8aaSDavid van Moolenbroek exit(1); 660*0b98e8aaSDavid van Moolenbroek } 661*0b98e8aaSDavid van Moolenbroek new StoreInst(ConstantInt::get(M.getContext(), APInt(32, runtime_seed)), seedValue, false, magicArrayBuildFuncInst); 662*0b98e8aaSDavid van Moolenbroek 663*0b98e8aaSDavid van Moolenbroek Value *heapMapPermutateValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE); 664*0b98e8aaSDavid van Moolenbroek if(!heapMapPermutateValue) { 665*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE << " field found"; 666*0b98e8aaSDavid van Moolenbroek exit(1); 667*0b98e8aaSDavid van Moolenbroek } 668*0b98e8aaSDavid van Moolenbroek new StoreInst(ConstantInt::get(M.getContext(), APInt(32, heap_map_do_permutate)), heapMapPermutateValue, false, magicArrayBuildFuncInst); 669*0b98e8aaSDavid van Moolenbroek 670*0b98e8aaSDavid van Moolenbroek 671*0b98e8aaSDavid van Moolenbroek Value *heapOffsetValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET); 672*0b98e8aaSDavid van Moolenbroek if(!heapOffsetValue) { 673*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET << " field found"; 674*0b98e8aaSDavid van Moolenbroek exit(1); 675*0b98e8aaSDavid van Moolenbroek } 676*0b98e8aaSDavid van Moolenbroek new StoreInst(ConstantInt::get(M.getContext(), APInt(32, heap_max_offset)), heapOffsetValue, false, magicArrayBuildFuncInst); 677*0b98e8aaSDavid van Moolenbroek 678*0b98e8aaSDavid van Moolenbroek Value *heapPaddingValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING); 679*0b98e8aaSDavid van Moolenbroek if(!heapPaddingValue) { 680*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING << " field found"; 681*0b98e8aaSDavid van Moolenbroek exit(1); 682*0b98e8aaSDavid van Moolenbroek } 683*0b98e8aaSDavid van Moolenbroek new StoreInst(ConstantInt::get(M.getContext(), APInt(32, heap_max_padding)), heapPaddingValue, false, magicArrayBuildFuncInst); 684*0b98e8aaSDavid van Moolenbroek 685*0b98e8aaSDavid van Moolenbroek 686*0b98e8aaSDavid van Moolenbroek Value *mapOffsetValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES); 687*0b98e8aaSDavid van Moolenbroek if(!mapOffsetValue) { 688*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES << " field found"; 689*0b98e8aaSDavid van Moolenbroek exit(1); 690*0b98e8aaSDavid van Moolenbroek } 691*0b98e8aaSDavid van Moolenbroek new StoreInst(ConstantInt::get(M.getContext(), APInt(32, map_max_offset_pages)), mapOffsetValue, false, magicArrayBuildFuncInst); 692*0b98e8aaSDavid van Moolenbroek 693*0b98e8aaSDavid van Moolenbroek Value *mapPaddingValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES); 694*0b98e8aaSDavid van Moolenbroek if(!mapPaddingValue) { 695*0b98e8aaSDavid van Moolenbroek outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES << " field found"; 696*0b98e8aaSDavid van Moolenbroek exit(1); 697*0b98e8aaSDavid van Moolenbroek } 698*0b98e8aaSDavid van Moolenbroek new StoreInst(ConstantInt::get(M.getContext(), APInt(32, map_max_padding_pages)), mapPaddingValue, false, magicArrayBuildFuncInst); 699*0b98e8aaSDavid van Moolenbroek 700*0b98e8aaSDavid van Moolenbroek 701*0b98e8aaSDavid van Moolenbroek 702*0b98e8aaSDavid van Moolenbroek } 703*0b98e8aaSDavid van Moolenbroek 704*0b98e8aaSDavid van Moolenbroek } 705*0b98e8aaSDavid van Moolenbroek 706*0b98e8aaSDavid van Moolenbroek return true; 707*0b98e8aaSDavid van Moolenbroek } 708*0b98e8aaSDavid van Moolenbroek 709*0b98e8aaSDavid van Moolenbroek } // end namespace 710*0b98e8aaSDavid van Moolenbroek 711*0b98e8aaSDavid van Moolenbroek char ASRPass::ID = 1; 712*0b98e8aaSDavid van Moolenbroek static RegisterPass<ASRPass> AP("asr", "Address Space Randomization Pass"); 713