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