xref: /minix3/minix/llvm/passes/asr/ASRPass.cpp (revision bdb565187c0f1a04513dd488df843317b27f86c8)
10b98e8aaSDavid van Moolenbroek #include <asr/ASRPass.h>
20b98e8aaSDavid van Moolenbroek #include <magic_common.h>
30b98e8aaSDavid van Moolenbroek #include <magic/support/MagicUtil.h>
40b98e8aaSDavid van Moolenbroek #include <llvm/Transforms/Utils/BasicBlockUtils.h>
50b98e8aaSDavid van Moolenbroek 
6*bdb56518SDavid van Moolenbroek #define MAGIC_IS_MAGIC_FUNC(M, F) (!StringRef((F)->getSection()).compare(MAGIC_STATIC_FUNCTIONS_SECTION))
70b98e8aaSDavid van Moolenbroek 
80b98e8aaSDavid van Moolenbroek using namespace llvm;
90b98e8aaSDavid van Moolenbroek 
100b98e8aaSDavid van Moolenbroek 
110b98e8aaSDavid van Moolenbroek // command-line arguments
120b98e8aaSDavid van Moolenbroek 
130b98e8aaSDavid van Moolenbroek static cl::opt<int>
140b98e8aaSDavid van Moolenbroek seed("asr-seed",
150b98e8aaSDavid van Moolenbroek     cl::desc("Random seed integer value for ASRPass. '0' will use current time as seed"),
160b98e8aaSDavid van Moolenbroek     cl::init(DEFAULT_SEED), cl::NotHidden, cl::ValueRequired);
170b98e8aaSDavid van Moolenbroek 
180b98e8aaSDavid van Moolenbroek 
190b98e8aaSDavid van Moolenbroek static cl::opt<int>
200b98e8aaSDavid van Moolenbroek gv_max_offset("asr-gv-max-offset",
210b98e8aaSDavid van Moolenbroek     cl::desc(""),
220b98e8aaSDavid van Moolenbroek     cl::init(GV_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired);
230b98e8aaSDavid van Moolenbroek 
240b98e8aaSDavid van Moolenbroek static cl::opt<int>
250b98e8aaSDavid van Moolenbroek gv_max_padding("asr-gv-max-padding",
260b98e8aaSDavid van Moolenbroek     cl::desc(""),
270b98e8aaSDavid van Moolenbroek     cl::init(GV_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired);
280b98e8aaSDavid van Moolenbroek 
290b98e8aaSDavid van Moolenbroek static cl::opt<int>
300b98e8aaSDavid van Moolenbroek gv_do_permutate("asr-gv-do-permutate",
310b98e8aaSDavid van Moolenbroek     cl::desc(""),
320b98e8aaSDavid van Moolenbroek     cl::init(GV_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired);
330b98e8aaSDavid van Moolenbroek 
340b98e8aaSDavid van Moolenbroek 
350b98e8aaSDavid van Moolenbroek static cl::opt<int>
360b98e8aaSDavid van Moolenbroek func_max_offset("asr-func-max-offset",
370b98e8aaSDavid van Moolenbroek     cl::desc(""),
380b98e8aaSDavid van Moolenbroek     cl::init(FUNC_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired);
390b98e8aaSDavid van Moolenbroek 
400b98e8aaSDavid van Moolenbroek static cl::opt<int>
410b98e8aaSDavid van Moolenbroek func_max_padding("asr-func-max-padding",
420b98e8aaSDavid van Moolenbroek     cl::desc(""),
430b98e8aaSDavid van Moolenbroek     cl::init(FUNC_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired);
440b98e8aaSDavid van Moolenbroek 
450b98e8aaSDavid van Moolenbroek static cl::opt<int>
460b98e8aaSDavid van Moolenbroek func_max_bb_shift("asr-func-max-bb-shift",
470b98e8aaSDavid van Moolenbroek     cl::desc(""),
480b98e8aaSDavid van Moolenbroek     cl::init(FUNC_DEFAULT_MAX_BB_SHIFT), cl::NotHidden, cl::ValueRequired);
490b98e8aaSDavid van Moolenbroek 
500b98e8aaSDavid van Moolenbroek static cl::opt<int>
510b98e8aaSDavid van Moolenbroek func_do_permutate("asr-func-do-permutate",
520b98e8aaSDavid van Moolenbroek     cl::desc(""),
530b98e8aaSDavid van Moolenbroek     cl::init(FUNC_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired);
540b98e8aaSDavid van Moolenbroek 
550b98e8aaSDavid van Moolenbroek 
560b98e8aaSDavid van Moolenbroek static cl::opt<int>
570b98e8aaSDavid van Moolenbroek stack_do_offset("asr-stack-do-offset",
580b98e8aaSDavid van Moolenbroek     cl::desc(""),
590b98e8aaSDavid van Moolenbroek     cl::init(STACK_DEFAULT_DO_OFFSET), cl::NotHidden, cl::ValueRequired);
600b98e8aaSDavid van Moolenbroek 
610b98e8aaSDavid van Moolenbroek static cl::opt<int>
620b98e8aaSDavid van Moolenbroek stack_max_offset("asr-stack-max-offset",
630b98e8aaSDavid van Moolenbroek     cl::desc(""),
640b98e8aaSDavid van Moolenbroek     cl::init(STACK_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired);
650b98e8aaSDavid van Moolenbroek 
660b98e8aaSDavid van Moolenbroek 
670b98e8aaSDavid van Moolenbroek static cl::opt<int>
680b98e8aaSDavid van Moolenbroek stackframe_do_offset("asr-stackframe-do-offset",
690b98e8aaSDavid van Moolenbroek     cl::desc(""),
700b98e8aaSDavid van Moolenbroek     cl::init(STACKFRAME_DEFAULT_DO_OFFSET), cl::NotHidden, cl::ValueRequired);
710b98e8aaSDavid van Moolenbroek 
720b98e8aaSDavid van Moolenbroek static cl::opt<int>
730b98e8aaSDavid van Moolenbroek stackframe_max_offset("asr-stackframe-max-offset",
740b98e8aaSDavid van Moolenbroek     cl::desc(""),
750b98e8aaSDavid van Moolenbroek     cl::init(STACKFRAME_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired);
760b98e8aaSDavid van Moolenbroek 
770b98e8aaSDavid van Moolenbroek static cl::opt<int>
780b98e8aaSDavid van Moolenbroek stackframe_max_padding("asr-stackframe-max-padding",
790b98e8aaSDavid van Moolenbroek     cl::desc(""),
800b98e8aaSDavid van Moolenbroek     cl::init(STACKFRAME_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired);
810b98e8aaSDavid van Moolenbroek 
820b98e8aaSDavid van Moolenbroek static cl::opt<int>
830b98e8aaSDavid van Moolenbroek stackframe_do_permutate("asr-stackframe-do-permutate",
840b98e8aaSDavid van Moolenbroek     cl::desc(""),
850b98e8aaSDavid van Moolenbroek     cl::init(STACKFRAME_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired);
860b98e8aaSDavid van Moolenbroek 
870b98e8aaSDavid van Moolenbroek static cl::opt<int>
880b98e8aaSDavid van Moolenbroek stackframe_static_padding("asr-stackframe-static-padding",
890b98e8aaSDavid van Moolenbroek     cl::desc(""),
900b98e8aaSDavid van Moolenbroek     cl::init(STACKFRAME_DEFAULT_STATIC_PADDING), cl::NotHidden, cl::ValueRequired);
910b98e8aaSDavid van Moolenbroek 
920b98e8aaSDavid van Moolenbroek static cl::opt<int>
930b98e8aaSDavid van Moolenbroek stackframe_caller_padding("asr-stackframe-caller-padding",
940b98e8aaSDavid van Moolenbroek     cl::desc(""),
950b98e8aaSDavid van Moolenbroek     cl::init(STACKFRAME_DEFAULT_CALLER_PADDING), cl::NotHidden, cl::ValueRequired);
960b98e8aaSDavid van Moolenbroek 
970b98e8aaSDavid van Moolenbroek static cl::opt<int>
980b98e8aaSDavid van Moolenbroek heap_map_do_permutate("asr-heap-map-do-permutate",
990b98e8aaSDavid van Moolenbroek     cl::desc(""),
1000b98e8aaSDavid van Moolenbroek     cl::init(HEAP_MAP_DEFAULT_DO_PERMUTATE), cl::NotHidden, cl::ValueRequired);
1010b98e8aaSDavid van Moolenbroek 
1020b98e8aaSDavid van Moolenbroek 
1030b98e8aaSDavid van Moolenbroek static cl::opt<int>
1040b98e8aaSDavid van Moolenbroek heap_max_offset("asr-heap-max-offset",
1050b98e8aaSDavid van Moolenbroek     cl::desc(""),
1060b98e8aaSDavid van Moolenbroek     cl::init(HEAP_DEFAULT_MAX_OFFSET), cl::NotHidden, cl::ValueRequired);
1070b98e8aaSDavid van Moolenbroek 
1080b98e8aaSDavid van Moolenbroek static cl::opt<int>
1090b98e8aaSDavid van Moolenbroek heap_max_padding("asr-heap-max-padding",
1100b98e8aaSDavid van Moolenbroek     cl::desc(""),
1110b98e8aaSDavid van Moolenbroek     cl::init(HEAP_DEFAULT_MAX_PADDING), cl::NotHidden, cl::ValueRequired);
1120b98e8aaSDavid van Moolenbroek 
1130b98e8aaSDavid van Moolenbroek 
1140b98e8aaSDavid van Moolenbroek static cl::opt<int>
1150b98e8aaSDavid van Moolenbroek map_max_offset_pages("asr-map-max-offset-pages",
1160b98e8aaSDavid van Moolenbroek     cl::desc(""),
1170b98e8aaSDavid van Moolenbroek     cl::init(MAP_DEFAULT_MAX_OFFSET_PAGES), cl::NotHidden, cl::ValueRequired);
1180b98e8aaSDavid van Moolenbroek 
1190b98e8aaSDavid van Moolenbroek static cl::opt<int>
1200b98e8aaSDavid van Moolenbroek map_max_padding_pages("asr-map-max-padding-pages",
1210b98e8aaSDavid van Moolenbroek     cl::desc(""),
1220b98e8aaSDavid van Moolenbroek     cl::init(MAP_DEFAULT_MAX_PADDING_PAGES), cl::NotHidden, cl::ValueRequired);
1230b98e8aaSDavid van Moolenbroek 
1240b98e8aaSDavid van Moolenbroek 
1250b98e8aaSDavid van Moolenbroek #define __X(P) #P
1260b98e8aaSDavid van Moolenbroek         std::string magicMemFuncNames[] = { MAGIC_MEM_FUNC_NAMES };
1270b98e8aaSDavid van Moolenbroek #undef __X
1280b98e8aaSDavid van Moolenbroek 
1290b98e8aaSDavid van Moolenbroek namespace llvm {
1300b98e8aaSDavid van Moolenbroek 
1310b98e8aaSDavid van Moolenbroek PASS_COMMON_INIT_ONCE();
1320b98e8aaSDavid van Moolenbroek 
1330b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
1340b98e8aaSDavid van Moolenbroek // Constructors, destructor, and operators
1350b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
1360b98e8aaSDavid van Moolenbroek 
ASRPass()1370b98e8aaSDavid van Moolenbroek ASRPass::ASRPass() : ModulePass(ID) {}
1380b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
1390b98e8aaSDavid van Moolenbroek // Public methods
1400b98e8aaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
1410b98e8aaSDavid van Moolenbroek 
fillPermutationGenerator(std::vector<unsigned> & permutationGenerator)1420b98e8aaSDavid van Moolenbroek void fillPermutationGenerator(std::vector<unsigned> &permutationGenerator){
1430b98e8aaSDavid 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.
1440b98e8aaSDavid van Moolenbroek     unsigned size = permutationGenerator.size();
1450b98e8aaSDavid van Moolenbroek     for (unsigned i = 0; i < size; ++i) {
1460b98e8aaSDavid van Moolenbroek         unsigned j = rand() % (size - i);
1470b98e8aaSDavid van Moolenbroek         permutationGenerator[i] = j;
1480b98e8aaSDavid van Moolenbroek     }
1490b98e8aaSDavid van Moolenbroek }
1500b98e8aaSDavid van Moolenbroek 
getCalledFunctionFromCS(const CallSite & CS)1510b98e8aaSDavid van Moolenbroek Function* getCalledFunctionFromCS(const CallSite &CS) {
1520b98e8aaSDavid van Moolenbroek     assert(CS.getInstruction());
1530b98e8aaSDavid van Moolenbroek     Function *function = CS.getCalledFunction();
1540b98e8aaSDavid van Moolenbroek     if(function) {
1550b98e8aaSDavid van Moolenbroek         return function;
1560b98e8aaSDavid van Moolenbroek     }
1570b98e8aaSDavid van Moolenbroek 
1580b98e8aaSDavid van Moolenbroek     //handle the weird case of bitcasted function call
1590b98e8aaSDavid van Moolenbroek     ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue());
1600b98e8aaSDavid van Moolenbroek     if(!CE) {
1610b98e8aaSDavid van Moolenbroek         return NULL;
1620b98e8aaSDavid van Moolenbroek     }
1630b98e8aaSDavid van Moolenbroek     assert(CE && CE->getOpcode() == Instruction::BitCast && "Bitcast expected, something else found!");
1640b98e8aaSDavid van Moolenbroek     function = dyn_cast<Function>(CE->getOperand(0));
1650b98e8aaSDavid van Moolenbroek     assert(function);
1660b98e8aaSDavid van Moolenbroek 
1670b98e8aaSDavid van Moolenbroek     return function;
1680b98e8aaSDavid van Moolenbroek }
1690b98e8aaSDavid van Moolenbroek 
1700b98e8aaSDavid van Moolenbroek #define ADVANCE_ITERATOR(IT, N_POS) for(unsigned __adv_it_count=0; __adv_it_count< N_POS; __adv_it_count++){ IT++;}
1710b98e8aaSDavid van Moolenbroek 
create_padding_gv(Module & M,GlobalVariable * InsertBefore,int n_bytes)1720b98e8aaSDavid van Moolenbroek GlobalVariable *create_padding_gv(Module &M, GlobalVariable *InsertBefore, int n_bytes){
1730b98e8aaSDavid van Moolenbroek 
1740b98e8aaSDavid van Moolenbroek     ArrayType* ArrayTy = ArrayType::get(IntegerType::get(M.getContext(), 8), n_bytes);
1750b98e8aaSDavid van Moolenbroek 
1760b98e8aaSDavid van Moolenbroek     GlobalVariable* padding_char_arr = new GlobalVariable(/*Module=*/M,
1770b98e8aaSDavid van Moolenbroek             /*Type=*/ArrayTy,
1780b98e8aaSDavid van Moolenbroek             /*isConstant=*/false,
1790b98e8aaSDavid van Moolenbroek             /*Linkage=*/GlobalValue::InternalLinkage,
1800b98e8aaSDavid van Moolenbroek             /*Initializer=*/ConstantAggregateZero::get(ArrayTy),
1810b98e8aaSDavid van Moolenbroek             /*Name=*/"magic_asr_padding_gv",
1820b98e8aaSDavid van Moolenbroek             /*InsertBefore=*/InsertBefore);
1830b98e8aaSDavid van Moolenbroek     padding_char_arr->setAlignment(1);
1840b98e8aaSDavid van Moolenbroek     padding_char_arr->setSection(InsertBefore->getSection());
1850b98e8aaSDavid van Moolenbroek     return padding_char_arr;
1860b98e8aaSDavid van Moolenbroek 
1870b98e8aaSDavid van Moolenbroek }
1880b98e8aaSDavid van Moolenbroek 
create_padding_lv(Module & M,Instruction * InsertBefore,int n_bytes)1890b98e8aaSDavid van Moolenbroek AllocaInst *create_padding_lv(Module &M, Instruction *InsertBefore, int n_bytes){
1900b98e8aaSDavid van Moolenbroek 
1910b98e8aaSDavid van Moolenbroek     ArrayType* ArrayTy = ArrayType::get(IntegerType::get(M.getContext(), 8), n_bytes);
1920b98e8aaSDavid van Moolenbroek     AllocaInst* ptr_x = new AllocaInst(ArrayTy, "magic_asr_padding_lv", InsertBefore);
1930b98e8aaSDavid van Moolenbroek     ptr_x->setAlignment(16);
1940b98e8aaSDavid van Moolenbroek 
1950b98e8aaSDavid van Moolenbroek     /* Seems not to be necessary
1960b98e8aaSDavid van Moolenbroek 
1970b98e8aaSDavid van Moolenbroek     ConstantInt* const_int64_0 = ConstantInt::get(M.getContext(), APInt(64, StringRef("0"), 10));
1980b98e8aaSDavid van Moolenbroek     ConstantInt* const_int8_0 = ConstantInt::get(M.getContext(), APInt(8, StringRef("97"), 10));
1990b98e8aaSDavid van Moolenbroek 
2000b98e8aaSDavid van Moolenbroek     std::vector<Value*> ptr_indices;
2010b98e8aaSDavid van Moolenbroek     ptr_indices.push_back(const_int64_0);
2020b98e8aaSDavid van Moolenbroek     ptr_indices.push_back(const_int64_0);
2030b98e8aaSDavid van Moolenbroek 
2040b98e8aaSDavid van Moolenbroek     Instruction* ptr_8 = GetElementPtrInst::Create(ptr_x, ptr_indices.begin(), ptr_indices.end(), "", ptr_x->getParent());
2050b98e8aaSDavid van Moolenbroek     ptr_8->removeFromParent();
2060b98e8aaSDavid van Moolenbroek     ptr_8->insertAfter(ptr_x);
2070b98e8aaSDavid van Moolenbroek 
2080b98e8aaSDavid van Moolenbroek     StoreInst* void_9 = new StoreInst(const_int8_0, ptr_8, true, ptr_x->getParent());
2090b98e8aaSDavid van Moolenbroek     void_9->setAlignment(16);
2100b98e8aaSDavid van Moolenbroek     void_9->removeFromParent();
2110b98e8aaSDavid van Moolenbroek     void_9->insertAfter(ptr_8);
2120b98e8aaSDavid van Moolenbroek 
2130b98e8aaSDavid van Moolenbroek     */
2140b98e8aaSDavid van Moolenbroek 
2150b98e8aaSDavid van Moolenbroek     return ptr_x;
2160b98e8aaSDavid van Moolenbroek 
2170b98e8aaSDavid van Moolenbroek }
2180b98e8aaSDavid van Moolenbroek 
create_padding_func(Module & M,int n_ops)2190b98e8aaSDavid van Moolenbroek Function *create_padding_func(Module &M, int n_ops){
2200b98e8aaSDavid van Moolenbroek     /* Places a padding function at the end of the function list */
2210b98e8aaSDavid van Moolenbroek 
2220b98e8aaSDavid van Moolenbroek     std::vector<TYPECONST Type*>FuncTy_0_args;
2230b98e8aaSDavid van Moolenbroek     TYPECONST FunctionType* FuncTy_0 = FunctionType::get(Type::getVoidTy(M.getContext()), FuncTy_0_args, false);
2240b98e8aaSDavid van Moolenbroek 
2250b98e8aaSDavid van Moolenbroek     Function* func_padding_func = Function::Create(FuncTy_0, GlobalValue::ExternalLinkage, "magic_asr_padding_func", &M);
2260b98e8aaSDavid van Moolenbroek     func_padding_func->setCallingConv(CallingConv::C);
2270b98e8aaSDavid van Moolenbroek     BasicBlock* bb = BasicBlock::Create(M.getContext(), "",func_padding_func,0);
2280b98e8aaSDavid van Moolenbroek 
2290b98e8aaSDavid van Moolenbroek     ConstantInt* const_int32_0 = ConstantInt::get(M.getContext(), APInt(32, StringRef("0"), 10));
2300b98e8aaSDavid van Moolenbroek     ConstantInt* const_int32_1 = ConstantInt::get(M.getContext(), APInt(32, StringRef("1"), 10));
2310b98e8aaSDavid van Moolenbroek 
2320b98e8aaSDavid van Moolenbroek     AllocaInst* ptr_x = new AllocaInst(IntegerType::get(M.getContext(), 32), "x", bb);
2330b98e8aaSDavid van Moolenbroek     ptr_x->setAlignment(4);
2340b98e8aaSDavid van Moolenbroek 
2350b98e8aaSDavid van Moolenbroek     StoreInst* void_1 = new StoreInst(const_int32_0, ptr_x, true, bb);
2360b98e8aaSDavid van Moolenbroek     void_1->setAlignment(4);
2370b98e8aaSDavid van Moolenbroek 
2380b98e8aaSDavid van Moolenbroek     for(int i=0; i< n_ops; i++){
2390b98e8aaSDavid van Moolenbroek         LoadInst* load_x = new LoadInst(ptr_x, "", true, bb);
2400b98e8aaSDavid van Moolenbroek         load_x->setAlignment(4);
2410b98e8aaSDavid van Moolenbroek 
2420b98e8aaSDavid van Moolenbroek         BinaryOperator* add_x = BinaryOperator::Create(Instruction::Add, load_x, const_int32_1, "", bb);
2430b98e8aaSDavid van Moolenbroek 
2440b98e8aaSDavid van Moolenbroek         StoreInst* void_2 = new StoreInst(add_x, ptr_x, true, bb);
2450b98e8aaSDavid van Moolenbroek         void_2->setAlignment(4);
2460b98e8aaSDavid van Moolenbroek     }
2470b98e8aaSDavid van Moolenbroek 
2480b98e8aaSDavid van Moolenbroek     ReturnInst::Create(M.getContext(), bb);
2490b98e8aaSDavid van Moolenbroek 
2500b98e8aaSDavid van Moolenbroek     return func_padding_func;
2510b98e8aaSDavid van Moolenbroek }
2520b98e8aaSDavid van Moolenbroek 
getStringRefFromInt(int i)2530b98e8aaSDavid van Moolenbroek StringRef getStringRefFromInt(int i){
2540b98e8aaSDavid van Moolenbroek     std::stringstream stm;
2550b98e8aaSDavid van Moolenbroek     stm << i;
2560b98e8aaSDavid van Moolenbroek     return StringRef(*new std::string(stm.str()));
2570b98e8aaSDavid van Moolenbroek }
2580b98e8aaSDavid van Moolenbroek 
runOnModule(Module & M)2590b98e8aaSDavid van Moolenbroek bool ASRPass::runOnModule(Module &M) {
2600b98e8aaSDavid van Moolenbroek 
2610b98e8aaSDavid van Moolenbroek     Module::GlobalListType &globalList = M.getGlobalList();
2620b98e8aaSDavid van Moolenbroek     Module::FunctionListType &functionList = M.getFunctionList();
2630b98e8aaSDavid van Moolenbroek     int runtime_seed = seed;
2640b98e8aaSDavid van Moolenbroek 
2650b98e8aaSDavid van Moolenbroek     Function *magicEntryPointFunc = M.getFunction(MAGIC_ENTRY_POINT);
2660b98e8aaSDavid van Moolenbroek     if( !magicEntryPointFunc ){
2670b98e8aaSDavid van Moolenbroek         //if no valid entry point, we are not compiling a valid program, skip pass
2680b98e8aaSDavid van Moolenbroek         return false;
2690b98e8aaSDavid van Moolenbroek     }
2700b98e8aaSDavid van Moolenbroek 
2710b98e8aaSDavid van Moolenbroek     Function *magicInitFunc = M.getFunction(MAGIC_INIT_FUNC_NAME);
2720b98e8aaSDavid van Moolenbroek     if( !magicInitFunc ){
2730b98e8aaSDavid van Moolenbroek         outs() << "Error: no " << MAGIC_INIT_FUNC_NAME << "() found";
2740b98e8aaSDavid van Moolenbroek         exit(1);
2750b98e8aaSDavid van Moolenbroek     }
2760b98e8aaSDavid van Moolenbroek 
2770b98e8aaSDavid van Moolenbroek     {
2780b98e8aaSDavid van Moolenbroek         // get random seed number, or use the current time if the seed number is set to 0.
2790b98e8aaSDavid van Moolenbroek         if(!seed){
2800b98e8aaSDavid van Moolenbroek             seed = time(NULL);
2810b98e8aaSDavid van Moolenbroek         }
2820b98e8aaSDavid van Moolenbroek         srand(seed);
2830b98e8aaSDavid van Moolenbroek 
2840b98e8aaSDavid van Moolenbroek     }{
2850b98e8aaSDavid van Moolenbroek 
2860b98e8aaSDavid van Moolenbroek         /* Randomly offset and permutate list of global variables, and insert random padding between neighbouring global variables */
2870b98e8aaSDavid van Moolenbroek 
2880b98e8aaSDavid van Moolenbroek         std::vector<unsigned> pg(globalList.size());
2890b98e8aaSDavid van Moolenbroek         fillPermutationGenerator(pg);
2900b98e8aaSDavid van Moolenbroek 
2910b98e8aaSDavid van Moolenbroek         for(unsigned i=0; i < pg.size(); i++){
2920b98e8aaSDavid van Moolenbroek             Module::global_iterator it = globalList.begin();
2930b98e8aaSDavid van Moolenbroek             // get the next random global variable
2940b98e8aaSDavid van Moolenbroek             ADVANCE_ITERATOR(it, pg[i]);
2950b98e8aaSDavid van Moolenbroek             // skip certain variables
2960b98e8aaSDavid van Moolenbroek             if(it->getName().startswith("llvm.")
2970b98e8aaSDavid van Moolenbroek                 || it->getLinkage() == GlobalValue::ExternalWeakLinkage){
2980b98e8aaSDavid van Moolenbroek                 continue;
2990b98e8aaSDavid van Moolenbroek             }
3000b98e8aaSDavid van Moolenbroek             if(it->getLinkage() != GlobalValue::ExternalLinkage && it->getName().compare("environ")){
3010b98e8aaSDavid van Moolenbroek                 // This prevents most public global variables (common linkage, but not external linkage) to be kept in the same order
3020b98e8aaSDavid van Moolenbroek                 it->setLinkage(GlobalValue::InternalLinkage);
3030b98e8aaSDavid van Moolenbroek             }
3040b98e8aaSDavid van Moolenbroek             if(gv_do_permutate){
3050b98e8aaSDavid van Moolenbroek                 // randomize the order of variables, by removing the global variable, and putting it at the end of globalList
3060b98e8aaSDavid van Moolenbroek                 GlobalVariable *gv = globalList.remove(it);
3070b98e8aaSDavid van Moolenbroek                 globalList.push_back(gv);
3080b98e8aaSDavid van Moolenbroek                 it = --globalList.end();
3090b98e8aaSDavid van Moolenbroek             }
3100b98e8aaSDavid van Moolenbroek             // put a padding variable between each two adjacent global variables, and place a big offset before the first global variable
3110b98e8aaSDavid van Moolenbroek             int max_padding = i == 0 ? gv_max_offset : gv_max_padding;
3120b98e8aaSDavid van Moolenbroek             if(max_padding > 0){
3130b98e8aaSDavid van Moolenbroek                 create_padding_gv(M, it, (rand () % max_padding) + 1);
3140b98e8aaSDavid van Moolenbroek             }
3150b98e8aaSDavid van Moolenbroek         }
3160b98e8aaSDavid van Moolenbroek 
3170b98e8aaSDavid van Moolenbroek     }{
3180b98e8aaSDavid van Moolenbroek 
3190b98e8aaSDavid van Moolenbroek         /* Randomly offset and permutate function list, and insert random padding between neighbouring functions. */
3200b98e8aaSDavid van Moolenbroek 
3210b98e8aaSDavid van Moolenbroek         std::vector<unsigned> pg(functionList.size());
3220b98e8aaSDavid van Moolenbroek         fillPermutationGenerator(pg);
3230b98e8aaSDavid van Moolenbroek 
3240b98e8aaSDavid van Moolenbroek         for(unsigned i=0; i < pg.size(); i++){
3250b98e8aaSDavid van Moolenbroek             Module::iterator it = functionList.begin();
3260b98e8aaSDavid van Moolenbroek             if(func_do_permutate){
3270b98e8aaSDavid 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 */
3280b98e8aaSDavid van Moolenbroek                 ADVANCE_ITERATOR(it, pg[i]);
3290b98e8aaSDavid van Moolenbroek             }
3300b98e8aaSDavid van Moolenbroek             Function *F = functionList.remove(it);
3310b98e8aaSDavid van Moolenbroek             functionList.push_back(F);
3320b98e8aaSDavid van Moolenbroek             /* place a padding function at the end of the function list, behind the current function */
3330b98e8aaSDavid van Moolenbroek             int max_padding = i == 0 ? func_max_offset : func_max_padding;
3340b98e8aaSDavid van Moolenbroek             if(max_padding > 0){
3350b98e8aaSDavid van Moolenbroek                 create_padding_func(M, (rand () % (max_padding/2)) + (max_padding/2));
3360b98e8aaSDavid van Moolenbroek             }
3370b98e8aaSDavid van Moolenbroek         }
3380b98e8aaSDavid van Moolenbroek 
3390b98e8aaSDavid van Moolenbroek     }{
3400b98e8aaSDavid van Moolenbroek 
3410b98e8aaSDavid van Moolenbroek 
3420b98e8aaSDavid van Moolenbroek         /* permutate and pad local function variables, and create dynamically randomized stack and stack frame offsets */
3430b98e8aaSDavid van Moolenbroek 
3440b98e8aaSDavid van Moolenbroek         for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
3450b98e8aaSDavid van Moolenbroek             Function *F = it;
3460b98e8aaSDavid van Moolenbroek 
3470b98e8aaSDavid van Moolenbroek             /* skip certain functions */
3480b98e8aaSDavid van Moolenbroek             if(F->getBasicBlockList().size() == 0){
3490b98e8aaSDavid van Moolenbroek                 continue;
3500b98e8aaSDavid van Moolenbroek             }
3510b98e8aaSDavid van Moolenbroek             if(MAGIC_IS_MAGIC_FUNC(M, F)){
3520b98e8aaSDavid van Moolenbroek                 continue;
3530b98e8aaSDavid van Moolenbroek             }
3540b98e8aaSDavid van Moolenbroek             if(!F->getName().compare("rand")){
3550b98e8aaSDavid van Moolenbroek                 continue;
3560b98e8aaSDavid van Moolenbroek             }
3570b98e8aaSDavid van Moolenbroek 
3580b98e8aaSDavid van Moolenbroek 
3590b98e8aaSDavid van Moolenbroek             /* find all allocation instructions in order to pad them. */
3600b98e8aaSDavid van Moolenbroek 
3610b98e8aaSDavid van Moolenbroek             /* Helper vectors to store all alloca instructions temporarily.
3620b98e8aaSDavid van Moolenbroek              * Make two collections, depending on whether the address of the variable is taken and used as a pointer.
3630b98e8aaSDavid van Moolenbroek              * (Because pointer dereferencing, buffer overflow, etc. add extra risks to those variables that have their addresses taken)
3640b98e8aaSDavid van Moolenbroek              * We order the allocation instructions as follows:
3650b98e8aaSDavid van Moolenbroek              * - First, we allocate the ones that don't have their address taken, only permutated.
3660b98e8aaSDavid van Moolenbroek              * - Then, we allocate an stack frame offset (dynamically randomly sized).
3670b98e8aaSDavid van Moolenbroek              * - After the stack frame offset, we allocate those that have their address taken, with permutation and padding.
3680b98e8aaSDavid 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.
3690b98e8aaSDavid van Moolenbroek              * This gives the extra advantages that those allocations are folded into the prolog/epilog code by the code generator, for extra performance.
3700b98e8aaSDavid van Moolenbroek              * (See AllocaInst::isStaticAlloca() in llvm/Instructions.h)
3710b98e8aaSDavid van Moolenbroek              * */
3720b98e8aaSDavid van Moolenbroek             std::vector<Instruction *> allocaAddressTaken, allocaNoAddressTaken;
3730b98e8aaSDavid van Moolenbroek 
3740b98e8aaSDavid van Moolenbroek             /* Only the first basic block contains alloca instructions */
3750b98e8aaSDavid van Moolenbroek             BasicBlock *BB =  F->getBasicBlockList().begin();
3760b98e8aaSDavid van Moolenbroek 
3770b98e8aaSDavid van Moolenbroek             /* with each iteration, one of these integers will be incremented/decremented */
3780b98e8aaSDavid van Moolenbroek             unsigned bb_size = BB->getInstList().size();
3790b98e8aaSDavid van Moolenbroek             unsigned pos = 0;
3800b98e8aaSDavid van Moolenbroek             while(pos < bb_size){
3810b98e8aaSDavid van Moolenbroek 
3820b98e8aaSDavid van Moolenbroek                 /* check if instruction at position <pos> is an allocation instruction.
3830b98e8aaSDavid van Moolenbroek                  * If, so remove and put in one of the helper vectors
3840b98e8aaSDavid van Moolenbroek                  * */
3850b98e8aaSDavid van Moolenbroek 
3860b98e8aaSDavid van Moolenbroek                 BasicBlock::iterator it = BB->getInstList().begin();
3870b98e8aaSDavid van Moolenbroek                 /* move to current position in instruction list */
3880b98e8aaSDavid van Moolenbroek                 ADVANCE_ITERATOR(it, pos);
3890b98e8aaSDavid van Moolenbroek                 Instruction *inst = &(*it);
3900b98e8aaSDavid van Moolenbroek                 if (AllocaInst *allocaInst = dyn_cast<AllocaInst>(inst)){
3910b98e8aaSDavid van Moolenbroek                     /* this is an allocation instruction. insert it at the front of of the right helper vector
3920b98e8aaSDavid van Moolenbroek                      * (last found allocation instruction will be at the front), and remove it from the basic block.
3930b98e8aaSDavid van Moolenbroek                      * */
3940b98e8aaSDavid van Moolenbroek                     int hasAddressTaken = 0;
395*bdb56518SDavid van Moolenbroek                     for (Value::user_iterator UI = allocaInst->user_begin(), E = allocaInst->user_end(); UI != E; ++UI) {
3960b98e8aaSDavid van Moolenbroek 
3970b98e8aaSDavid van Moolenbroek                         /* Loop through all the Uses of this allocation function. */
3980b98e8aaSDavid van Moolenbroek 
3990b98e8aaSDavid van Moolenbroek                         User *U = *UI;
4000b98e8aaSDavid van Moolenbroek                         if(dyn_cast<LoadInst>(U) || dyn_cast<StoreInst>(U)){
4010b98e8aaSDavid van Moolenbroek                             /* This is a load or store instruction, which does not
4020b98e8aaSDavid van Moolenbroek                              * indicate that a pointer of this variable is generated
4030b98e8aaSDavid van Moolenbroek                              * */
4040b98e8aaSDavid van Moolenbroek                             continue;
4050b98e8aaSDavid van Moolenbroek                         }else if(CallInst *cInst = dyn_cast<CallInst>(U)){
4060b98e8aaSDavid van Moolenbroek                             if(cInst->getCalledFunction() && MAGIC_IS_MAGIC_FUNC(M, cInst->getCalledFunction())){
4070b98e8aaSDavid van Moolenbroek                                 /* This is a function call instruction, but this
4080b98e8aaSDavid van Moolenbroek                                  * concerns a magic library function, so it does not count as a generated pointer.
4090b98e8aaSDavid van Moolenbroek                                  * Any other functions calls would have set hasAddressTaken to 1 */
4100b98e8aaSDavid van Moolenbroek                                 continue;
4110b98e8aaSDavid van Moolenbroek                             }
4120b98e8aaSDavid van Moolenbroek                         }
4130b98e8aaSDavid van Moolenbroek                         /* This instruction will (likely) create a pointer, because it is not a load, store or magic-function-call instruction */
4140b98e8aaSDavid van Moolenbroek                         hasAddressTaken = 1;
4150b98e8aaSDavid van Moolenbroek                         break;
4160b98e8aaSDavid van Moolenbroek                     }
4170b98e8aaSDavid van Moolenbroek 
4180b98e8aaSDavid van Moolenbroek                     /* Put the alloca instruction in the right helper vector, and remove from the basic block. */
4190b98e8aaSDavid van Moolenbroek                     if(hasAddressTaken){
4200b98e8aaSDavid van Moolenbroek                         allocaAddressTaken.insert(allocaAddressTaken.begin(), it);
4210b98e8aaSDavid van Moolenbroek                     }else{
4220b98e8aaSDavid van Moolenbroek                         allocaNoAddressTaken.insert(allocaNoAddressTaken.begin(), it);
4230b98e8aaSDavid van Moolenbroek                     }
4240b98e8aaSDavid van Moolenbroek                     it->removeFromParent();
4250b98e8aaSDavid van Moolenbroek                     bb_size--;
4260b98e8aaSDavid van Moolenbroek                 }else{
4270b98e8aaSDavid van Moolenbroek                     pos++;
4280b98e8aaSDavid van Moolenbroek                 }
4290b98e8aaSDavid van Moolenbroek             }
4300b98e8aaSDavid van Moolenbroek 
4310b98e8aaSDavid van Moolenbroek             /* Permutate and pad the alloca instructions whose addresses are taken. */
4320b98e8aaSDavid van Moolenbroek 
4330b98e8aaSDavid van Moolenbroek             std::vector<unsigned> pg(allocaAddressTaken.size());
4340b98e8aaSDavid van Moolenbroek             fillPermutationGenerator(pg);
4350b98e8aaSDavid van Moolenbroek             for(unsigned i=0; i<pg.size(); i++){
4360b98e8aaSDavid van Moolenbroek                 /* get the iterator for the first element of the helper vector */
4370b98e8aaSDavid van Moolenbroek                 std::vector<Instruction *>::iterator it = allocaAddressTaken.begin();
4380b98e8aaSDavid van Moolenbroek                 if(stackframe_do_permutate){
4390b98e8aaSDavid van Moolenbroek                     /* get the iterator for the next random element. When permutation is disabled, it keeps pointing to the first element */
4400b98e8aaSDavid van Moolenbroek                     ADVANCE_ITERATOR(it, pg[i]);
4410b98e8aaSDavid van Moolenbroek                 }
4420b98e8aaSDavid van Moolenbroek                 /* put the variable at the front of the basic block, and remove it from the helper vector.
4430b98e8aaSDavid van Moolenbroek                  * This way, the variable that is added last will be at the front
4440b98e8aaSDavid van Moolenbroek                  * */
4450b98e8aaSDavid van Moolenbroek                 BB->getInstList().push_front(*it);
4460b98e8aaSDavid van Moolenbroek                 allocaAddressTaken.erase(it);
4470b98e8aaSDavid van Moolenbroek 
4480b98e8aaSDavid van Moolenbroek                 /* put a padding variable between each two adjacent local variables
4490b98e8aaSDavid van Moolenbroek                  * this is done by inserting a padding var at the front each time a
4500b98e8aaSDavid van Moolenbroek                  * var has been put at the front with push_front().
4510b98e8aaSDavid van Moolenbroek                  * */
4520b98e8aaSDavid van Moolenbroek                 int max_padding = (i==pg.size()-1 ? 0 : stackframe_max_padding);
4530b98e8aaSDavid van Moolenbroek                 if(max_padding > 0){
4540b98e8aaSDavid van Moolenbroek                     create_padding_lv(M, BB->getInstList().begin(), (rand () % max_padding) + 1);
4550b98e8aaSDavid van Moolenbroek                 }
4560b98e8aaSDavid van Moolenbroek             }
4570b98e8aaSDavid van Moolenbroek 
4580b98e8aaSDavid van Moolenbroek 
4590b98e8aaSDavid van Moolenbroek             /* Create a global stack offset, and an offset for each stack frame. Both have a dynamic random size */
4600b98e8aaSDavid van Moolenbroek 
4610b98e8aaSDavid van Moolenbroek             /* Determine if we must pad or offset, and how much */
4620b98e8aaSDavid van Moolenbroek             int max_offset, do_offset=1;
4630b98e8aaSDavid van Moolenbroek             if(F->getName().equals(MAGIC_ENTRY_POINT)){
4640b98e8aaSDavid van Moolenbroek                 if(!stack_do_offset){
4650b98e8aaSDavid van Moolenbroek                     do_offset=0;
4660b98e8aaSDavid van Moolenbroek                 }
4670b98e8aaSDavid van Moolenbroek                 /* give the entry function (first function) a large offset instead of an padding */
4680b98e8aaSDavid van Moolenbroek                 max_offset = stack_max_offset;
4690b98e8aaSDavid van Moolenbroek             }else{
4700b98e8aaSDavid van Moolenbroek                 if(!stackframe_do_offset){
4710b98e8aaSDavid van Moolenbroek                     do_offset=0;
4720b98e8aaSDavid van Moolenbroek                 }
4730b98e8aaSDavid van Moolenbroek                 max_offset = stackframe_max_offset;
4740b98e8aaSDavid van Moolenbroek             }
4750b98e8aaSDavid van Moolenbroek 
4760b98e8aaSDavid van Moolenbroek             /* Create a new block before the first block. Now, all the variable allocations whose addresses are taken are no longer
4770b98e8aaSDavid van Moolenbroek              * in the first block, so CallInst::isStaticAlloca() does no longer apply to them.
4780b98e8aaSDavid van Moolenbroek              * When isStaticAlloca() == true, the code generator will fold it into the prolog/epilog code, so it is basically free.
4790b98e8aaSDavid van Moolenbroek              * This means that we now get less efficient code.
4800b98e8aaSDavid van Moolenbroek              * This is necessary to prevent the variables whose address is taken from being allocated before the stack frame offset is allocated.
4810b98e8aaSDavid van Moolenbroek              * Alternatively, we could allocate before the function call, instead of after. */
4820b98e8aaSDavid van Moolenbroek 
4830b98e8aaSDavid van Moolenbroek             BasicBlock *OldFirstBB = F->getBasicBlockList().begin();
4840b98e8aaSDavid van Moolenbroek             BasicBlock *NewFirstBB = BasicBlock::Create(M.getContext(), "newBB", F, OldFirstBB);
4850b98e8aaSDavid van Moolenbroek 
4860b98e8aaSDavid van Moolenbroek 
4870b98e8aaSDavid van Moolenbroek             /* Permutate and insert the allocation instructions whose addresses are NOT taken into the new first block (dont apply padding).
4880b98e8aaSDavid van Moolenbroek              * These must be allocated before the stack frame offset is allocated. */
4890b98e8aaSDavid van Moolenbroek 
4900b98e8aaSDavid van Moolenbroek             pg = std::vector<unsigned>(allocaNoAddressTaken.size());
4910b98e8aaSDavid van Moolenbroek             fillPermutationGenerator(pg);
4920b98e8aaSDavid van Moolenbroek             for(unsigned i=0; i<pg.size(); i++){
4930b98e8aaSDavid van Moolenbroek                 /* get the iterator for the first element of the helper vector */
4940b98e8aaSDavid van Moolenbroek                 std::vector<Instruction *>::iterator it = allocaNoAddressTaken.begin();
4950b98e8aaSDavid van Moolenbroek                 if(stackframe_do_permutate){
4960b98e8aaSDavid van Moolenbroek                     /* get the iterator for the next random element. When permutation is disabled, it keeps pointing to the first element */
4970b98e8aaSDavid van Moolenbroek                     ADVANCE_ITERATOR(it, pg[i]);
4980b98e8aaSDavid van Moolenbroek                 }
4990b98e8aaSDavid van Moolenbroek                 /* put the variable at the front of the basic block, and remove it from the helper vector.
5000b98e8aaSDavid van Moolenbroek                  * This way, the variable that is added last will be at the front
5010b98e8aaSDavid van Moolenbroek                  * */
5020b98e8aaSDavid van Moolenbroek                 NewFirstBB->getInstList().push_front(*it);
5030b98e8aaSDavid van Moolenbroek                 allocaNoAddressTaken.erase(it);
5040b98e8aaSDavid van Moolenbroek             }
5050b98e8aaSDavid van Moolenbroek 
5060b98e8aaSDavid van Moolenbroek             if(do_offset){
5070b98e8aaSDavid van Moolenbroek                 if(stackframe_static_padding) {
5080b98e8aaSDavid van Moolenbroek                     if(max_offset > 0) {
5090b98e8aaSDavid van Moolenbroek                         new AllocaInst(IntegerType::get(M.getContext(), 8), ConstantInt::get(M.getContext(), APInt(64, (rand() % max_offset) + 1, 10)), "", NewFirstBB);
5100b98e8aaSDavid van Moolenbroek                     }
5110b98e8aaSDavid van Moolenbroek                 }
5120b98e8aaSDavid van Moolenbroek                 else {
5130b98e8aaSDavid van Moolenbroek                     /* Now insert a dynamically randomized stackframe offset */
5140b98e8aaSDavid van Moolenbroek                     Function *RandFunc = M.getFunction("rand");
5150b98e8aaSDavid van Moolenbroek                     assert(RandFunc != NULL);
5160b98e8aaSDavid van Moolenbroek 
5170b98e8aaSDavid van Moolenbroek                     /* Call rand() */
5180b98e8aaSDavid van Moolenbroek                     std::vector<Value*> args;
5190b98e8aaSDavid van Moolenbroek                     CallInst* RandFuncCall = PassUtil::createCallInstruction(RandFunc, args, "", NewFirstBB);
5200b98e8aaSDavid van Moolenbroek                     Instruction *nextInst = RandFuncCall;
5210b98e8aaSDavid van Moolenbroek 
5220b98e8aaSDavid van Moolenbroek                     if(max_offset > 0){
5230b98e8aaSDavid van Moolenbroek                         /* limit the rand value: rand() % max_offet */
5240b98e8aaSDavid van Moolenbroek                         ConstantInt* max_offset_const = ConstantInt::get(M.getContext(), APInt(32, max_offset, 10));
5250b98e8aaSDavid van Moolenbroek                         BinaryOperator *Remainder = BinaryOperator::Create(Instruction::SRem, RandFuncCall, max_offset_const, "", NewFirstBB);
5260b98e8aaSDavid van Moolenbroek                         Remainder->removeFromParent();
5270b98e8aaSDavid van Moolenbroek                         Remainder->insertAfter(RandFuncCall);
5280b98e8aaSDavid van Moolenbroek                         nextInst = Remainder;
5290b98e8aaSDavid van Moolenbroek                     }
5300b98e8aaSDavid van Moolenbroek 
5310b98e8aaSDavid van Moolenbroek                     /* Minimum rand value must be 1, so increment it. */
5320b98e8aaSDavid van Moolenbroek                     ConstantInt* One = ConstantInt::get(M.getContext(), APInt(32, StringRef("1"), 10));
5330b98e8aaSDavid van Moolenbroek                     BinaryOperator* AddOne = BinaryOperator::Create(Instruction::Add, nextInst, One, "", NewFirstBB);
5340b98e8aaSDavid van Moolenbroek                     AddOne->removeFromParent();
5350b98e8aaSDavid van Moolenbroek                     AddOne->insertAfter(nextInst);
5360b98e8aaSDavid van Moolenbroek 
5370b98e8aaSDavid van Moolenbroek                     /* Allocate the offset/padding */
5380b98e8aaSDavid van Moolenbroek                     AllocaInst* allocaInstruction = new AllocaInst(IntegerType::get(M.getContext(), 8), AddOne, "", NewFirstBB);
5390b98e8aaSDavid van Moolenbroek                     allocaInstruction->removeFromParent();
5400b98e8aaSDavid van Moolenbroek                     allocaInstruction->insertAfter(AddOne);
5410b98e8aaSDavid van Moolenbroek 
5420b98e8aaSDavid van Moolenbroek                     /* Inline the rand() call. */
5430b98e8aaSDavid van Moolenbroek                     InlineFunctionInfo IFI;
5440b98e8aaSDavid van Moolenbroek                     InlineFunction(RandFuncCall, IFI);
5450b98e8aaSDavid van Moolenbroek                 }
5460b98e8aaSDavid van Moolenbroek             }
5470b98e8aaSDavid van Moolenbroek 
5480b98e8aaSDavid van Moolenbroek             /* Go to the old first block */
5490b98e8aaSDavid van Moolenbroek             BranchInst *br =  BranchInst::Create (OldFirstBB, NewFirstBB);
5500b98e8aaSDavid van Moolenbroek             br->setSuccessor(0, OldFirstBB);
5510b98e8aaSDavid van Moolenbroek 
5520b98e8aaSDavid van Moolenbroek             /* Static stack frame padding does not really need 2 basic blocks, but it may need call site instrumentation. */
5530b98e8aaSDavid van Moolenbroek             if(stackframe_static_padding) {
5540b98e8aaSDavid van Moolenbroek                 bool ret = MergeBlockIntoPredecessor(OldFirstBB, this);
5550b98e8aaSDavid van Moolenbroek                 assert(ret);
5560b98e8aaSDavid van Moolenbroek 
5570b98e8aaSDavid van Moolenbroek                 if(stackframe_caller_padding && max_offset > 0) {
558*bdb56518SDavid van Moolenbroek                     std::vector<User*> Users(F->user_begin(), F->user_end());
5590b98e8aaSDavid van Moolenbroek                     while (!Users.empty()) {
5600b98e8aaSDavid van Moolenbroek                         User *U = Users.back();
5610b98e8aaSDavid van Moolenbroek                         Users.pop_back();
5620b98e8aaSDavid van Moolenbroek                         if (Instruction *I = dyn_cast<Instruction>(U)) {
5630b98e8aaSDavid van Moolenbroek                             Function *parent = I->getParent()->getParent();
5640b98e8aaSDavid van Moolenbroek                             /* XXX Skipping MAGIC_ENTRY_POINT shouldn't be necessary. Check why. */
565139ae0daSDavid van Moolenbroek                             /* ..the reason is that main() typically contains the message loop, which loops
566139ae0daSDavid van Moolenbroek                              * forever making calls. These calls are getting padded, and AllocaInst causes a
567139ae0daSDavid van Moolenbroek                              * stack pointer adjustment every time a call is made. This stack memory is never
568139ae0daSDavid van Moolenbroek                              * released, since the function never returns. The result is that we eventually
569139ae0daSDavid van Moolenbroek                              * run out of stack. Since MINIX3 also uses user-level threads these days, the
570139ae0daSDavid van Moolenbroek                              * problem is not limited to main(), and for this reason I have disabled caller
571139ae0daSDavid van Moolenbroek                              * padding by default. -dcvmoole
572139ae0daSDavid van Moolenbroek                              */
5730b98e8aaSDavid van Moolenbroek                             if(MAGIC_IS_MAGIC_FUNC(M, parent) || parent->getName().equals(MAGIC_ENTRY_POINT)) {
5740b98e8aaSDavid van Moolenbroek                                 continue;
5750b98e8aaSDavid van Moolenbroek                             }
5760b98e8aaSDavid van Moolenbroek                             CallSite CS = PassUtil::getCallSiteFromInstruction(I);
5770b98e8aaSDavid van Moolenbroek                             if(!CS.getInstruction()) {
5780b98e8aaSDavid van Moolenbroek                                 continue;
5790b98e8aaSDavid van Moolenbroek                             }
5800b98e8aaSDavid van Moolenbroek                             Function *calledFunction = getCalledFunctionFromCS(CS);
5810b98e8aaSDavid van Moolenbroek                             if (CS.getInstruction() && !CS.arg_empty() && (calledFunction == F || calledFunction == NULL)) {
5820b98e8aaSDavid van Moolenbroek                                 new AllocaInst(IntegerType::get(M.getContext(), 8), ConstantInt::get(M.getContext(), APInt(64, (rand() % max_offset) + 1, 10)), "", I);
5830b98e8aaSDavid van Moolenbroek                             }
5840b98e8aaSDavid van Moolenbroek                         }
5850b98e8aaSDavid van Moolenbroek                     }
5860b98e8aaSDavid van Moolenbroek                 }
5870b98e8aaSDavid van Moolenbroek             }
5880b98e8aaSDavid van Moolenbroek 
5890b98e8aaSDavid van Moolenbroek             /* Basic block shifting. */
5900b98e8aaSDavid van Moolenbroek             if(func_max_bb_shift > 0) {
5910b98e8aaSDavid van Moolenbroek                 Instruction *I;
5920b98e8aaSDavid van Moolenbroek                 PassUtil::getAllocaInfo(F, NULL, &I);
5930b98e8aaSDavid van Moolenbroek                 BasicBlock *firstBB = F->getBasicBlockList().begin();
5940b98e8aaSDavid van Moolenbroek                 BasicBlock *splitBB = firstBB->splitBasicBlock(I, "split");
5950b98e8aaSDavid van Moolenbroek                 BasicBlock *dummyBB = BasicBlock::Create(M.getContext(), "dummy", F, splitBB);
5960b98e8aaSDavid van Moolenbroek                 if(!stackframe_caller_padding) {
5970b98e8aaSDavid van Moolenbroek                     firstBB = NewFirstBB;
5980b98e8aaSDavid van Moolenbroek                 }
5990b98e8aaSDavid van Moolenbroek 
6000b98e8aaSDavid van Moolenbroek                 /* Fill the dummy basic block with dummy instructions (using the prefetch intrinsic to emulate nop instructions), to shift the next basic block. */
6010b98e8aaSDavid van Moolenbroek                 Function *prefetchIntrinsic = PassUtil::getIntrinsicFunction(M, Intrinsic::prefetch);
6020b98e8aaSDavid van Moolenbroek                 std::vector<Value*> args;
6030b98e8aaSDavid van Moolenbroek                 args.push_back(ConstantPointerNull::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0)));
6040b98e8aaSDavid van Moolenbroek                 args.push_back(ConstantInt::get(M.getContext(), APInt(32, 0)));
6050b98e8aaSDavid van Moolenbroek                 args.push_back(ConstantInt::get(M.getContext(), APInt(32, 0)));
6060b98e8aaSDavid van Moolenbroek #if LLVM_VERSION >= 30
6070b98e8aaSDavid van Moolenbroek                 args.push_back(ConstantInt::get(M.getContext(), APInt(32, 0)));
6080b98e8aaSDavid van Moolenbroek #endif
6090b98e8aaSDavid van Moolenbroek                 unsigned shift = (rand() % func_max_bb_shift) + 1;
6100b98e8aaSDavid van Moolenbroek                 do {
6110b98e8aaSDavid van Moolenbroek                     PassUtil::createCallInstruction(prefetchIntrinsic, args, "", dummyBB);
6120b98e8aaSDavid van Moolenbroek                     shift--;
6130b98e8aaSDavid van Moolenbroek                 } while(shift > 0);
6140b98e8aaSDavid van Moolenbroek                 BranchInst *br =  BranchInst::Create (splitBB, dummyBB);
6150b98e8aaSDavid van Moolenbroek                 br->setSuccessor(0, splitBB);
6160b98e8aaSDavid van Moolenbroek 
6170b98e8aaSDavid van Moolenbroek                 /* Place an opaque conditional branch (always unconditionally skips the dummy basic block). */
6180b98e8aaSDavid van Moolenbroek                 Function *frameAddrIntrinsic = PassUtil::getIntrinsicFunction(M, Intrinsic::frameaddress);
6190b98e8aaSDavid van Moolenbroek                 std::vector<Value*> frameAddrArgs;
6200b98e8aaSDavid van Moolenbroek                 frameAddrArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, 0)));
6210b98e8aaSDavid van Moolenbroek                 Value *frameAddr = PassUtil::createCallInstruction(frameAddrIntrinsic, frameAddrArgs, "", firstBB->getTerminator());
6220b98e8aaSDavid van Moolenbroek                 TerminatorInst *OldTI = firstBB->getTerminator();
6230b98e8aaSDavid van Moolenbroek                 IRBuilder<> Builder(firstBB);
6240b98e8aaSDavid van Moolenbroek                 ICmpInst* ExtraCase = new ICmpInst(OldTI, ICmpInst::ICMP_EQ, frameAddr, ConstantPointerNull::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0)), "");
6250b98e8aaSDavid van Moolenbroek                 Builder.CreateCondBr(ExtraCase, dummyBB, splitBB);
6260b98e8aaSDavid van Moolenbroek                 OldTI->eraseFromParent();
6270b98e8aaSDavid van Moolenbroek             }
6280b98e8aaSDavid van Moolenbroek         }
6290b98e8aaSDavid van Moolenbroek 
6300b98e8aaSDavid van Moolenbroek     }{
6310b98e8aaSDavid van Moolenbroek 
6320b98e8aaSDavid van Moolenbroek 
6330b98e8aaSDavid van Moolenbroek #define __X(VAR) __XX(VAR)
6340b98e8aaSDavid van Moolenbroek #define __XX(VAR) #VAR
6350b98e8aaSDavid van Moolenbroek 
6360b98e8aaSDavid van Moolenbroek         /* heap and map padding */
6370b98e8aaSDavid van Moolenbroek 
6380b98e8aaSDavid van Moolenbroek         {
6390b98e8aaSDavid van Moolenbroek 
6400b98e8aaSDavid van Moolenbroek             /* Inject magic init call at the beginning of magic entry point function (before any allocaInsts).
6410b98e8aaSDavid van Moolenbroek              * Magic_init will return immediately if called for the second time, so both the magic pass and
6420b98e8aaSDavid van Moolenbroek              * this pass can insert call instructions into main
6430b98e8aaSDavid van Moolenbroek              * */
6440b98e8aaSDavid van Moolenbroek             std::vector<Value*> args;
6450b98e8aaSDavid van Moolenbroek             PassUtil::createCallInstruction(magicInitFunc, args, "", magicEntryPointFunc->getBasicBlockList().begin()->begin());
6460b98e8aaSDavid van Moolenbroek 
6470b98e8aaSDavid van Moolenbroek         }{
6480b98e8aaSDavid van Moolenbroek 
6490b98e8aaSDavid van Moolenbroek             /* set the global variables */
6500b98e8aaSDavid van Moolenbroek 
6510b98e8aaSDavid van Moolenbroek             Function *magicDataInitFunc = M.getFunction(MAGIC_DATA_INIT_FUNC_NAME);
6520b98e8aaSDavid van Moolenbroek             if(!magicDataInitFunc){
6530b98e8aaSDavid van Moolenbroek                 outs() <<"Error: no " << MAGIC_DATA_INIT_FUNC_NAME << "() found";
6540b98e8aaSDavid van Moolenbroek                 exit(1);
6550b98e8aaSDavid van Moolenbroek             }
6560b98e8aaSDavid van Moolenbroek             Instruction *magicArrayBuildFuncInst = magicDataInitFunc->back().getTerminator();
6570b98e8aaSDavid van Moolenbroek 
6580b98e8aaSDavid van Moolenbroek             GlobalVariable* magicRootVar = M.getNamedGlobal(MAGIC_ROOT_VAR_NAME);
6590b98e8aaSDavid van Moolenbroek             if(!magicRootVar) {
6600b98e8aaSDavid van Moolenbroek                 outs() << "Error: no " << MAGIC_ROOT_VAR_NAME << " variable found";
6610b98e8aaSDavid van Moolenbroek                 exit(1);
6620b98e8aaSDavid van Moolenbroek             }
6630b98e8aaSDavid van Moolenbroek 
6640b98e8aaSDavid van Moolenbroek             Value *seedValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_SEED);
6650b98e8aaSDavid van Moolenbroek             if(!seedValue) {
6660b98e8aaSDavid van Moolenbroek                 outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_SEED << " field found";
6670b98e8aaSDavid van Moolenbroek                 exit(1);
6680b98e8aaSDavid van Moolenbroek             }
6690b98e8aaSDavid van Moolenbroek             new StoreInst(ConstantInt::get(M.getContext(), APInt(32, runtime_seed)), seedValue, false, magicArrayBuildFuncInst);
6700b98e8aaSDavid van Moolenbroek 
6710b98e8aaSDavid van Moolenbroek             Value *heapMapPermutateValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE);
6720b98e8aaSDavid van Moolenbroek             if(!heapMapPermutateValue) {
6730b98e8aaSDavid van Moolenbroek                 outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE << " field found";
6740b98e8aaSDavid van Moolenbroek                 exit(1);
6750b98e8aaSDavid van Moolenbroek             }
6760b98e8aaSDavid van Moolenbroek             new StoreInst(ConstantInt::get(M.getContext(), APInt(32, heap_map_do_permutate)), heapMapPermutateValue, false, magicArrayBuildFuncInst);
6770b98e8aaSDavid van Moolenbroek 
6780b98e8aaSDavid van Moolenbroek 
6790b98e8aaSDavid van Moolenbroek             Value *heapOffsetValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET);
6800b98e8aaSDavid van Moolenbroek             if(!heapOffsetValue) {
6810b98e8aaSDavid van Moolenbroek                 outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET << " field found";
6820b98e8aaSDavid van Moolenbroek                 exit(1);
6830b98e8aaSDavid van Moolenbroek             }
6840b98e8aaSDavid van Moolenbroek             new StoreInst(ConstantInt::get(M.getContext(), APInt(32, heap_max_offset)), heapOffsetValue, false, magicArrayBuildFuncInst);
6850b98e8aaSDavid van Moolenbroek 
6860b98e8aaSDavid van Moolenbroek             Value *heapPaddingValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING);
6870b98e8aaSDavid van Moolenbroek             if(!heapPaddingValue) {
6880b98e8aaSDavid van Moolenbroek                 outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING << " field found";
6890b98e8aaSDavid van Moolenbroek                 exit(1);
6900b98e8aaSDavid van Moolenbroek             }
6910b98e8aaSDavid van Moolenbroek             new StoreInst(ConstantInt::get(M.getContext(), APInt(32, heap_max_padding)), heapPaddingValue, false, magicArrayBuildFuncInst);
6920b98e8aaSDavid van Moolenbroek 
6930b98e8aaSDavid van Moolenbroek 
6940b98e8aaSDavid van Moolenbroek             Value *mapOffsetValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES);
6950b98e8aaSDavid van Moolenbroek             if(!mapOffsetValue) {
6960b98e8aaSDavid van Moolenbroek                 outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES << " field found";
6970b98e8aaSDavid van Moolenbroek                 exit(1);
6980b98e8aaSDavid van Moolenbroek             }
6990b98e8aaSDavid van Moolenbroek             new StoreInst(ConstantInt::get(M.getContext(), APInt(32, map_max_offset_pages)), mapOffsetValue, false, magicArrayBuildFuncInst);
7000b98e8aaSDavid van Moolenbroek 
7010b98e8aaSDavid van Moolenbroek             Value *mapPaddingValue = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES);
7020b98e8aaSDavid van Moolenbroek             if(!mapPaddingValue) {
7030b98e8aaSDavid van Moolenbroek                 outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES << " field found";
7040b98e8aaSDavid van Moolenbroek                 exit(1);
7050b98e8aaSDavid van Moolenbroek             }
7060b98e8aaSDavid van Moolenbroek             new StoreInst(ConstantInt::get(M.getContext(), APInt(32, map_max_padding_pages)), mapPaddingValue, false, magicArrayBuildFuncInst);
7070b98e8aaSDavid van Moolenbroek 
7080b98e8aaSDavid van Moolenbroek 
7090b98e8aaSDavid van Moolenbroek 
7100b98e8aaSDavid van Moolenbroek         }
7110b98e8aaSDavid van Moolenbroek 
7120b98e8aaSDavid van Moolenbroek     }
7130b98e8aaSDavid van Moolenbroek 
7140b98e8aaSDavid van Moolenbroek     return true;
7150b98e8aaSDavid van Moolenbroek }
7160b98e8aaSDavid van Moolenbroek 
7170b98e8aaSDavid van Moolenbroek } // end namespace
7180b98e8aaSDavid van Moolenbroek 
7190b98e8aaSDavid van Moolenbroek char ASRPass::ID = 1;
7200b98e8aaSDavid van Moolenbroek static RegisterPass<ASRPass> AP("asr", "Address Space Randomization Pass");
721