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))
11 // command-line arguments
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
);
20 gv_max_offset("asr-gv-max-offset",
22 cl::init(GV_DEFAULT_MAX_OFFSET
), cl::NotHidden
, cl::ValueRequired
);
25 gv_max_padding("asr-gv-max-padding",
27 cl::init(GV_DEFAULT_MAX_PADDING
), cl::NotHidden
, cl::ValueRequired
);
30 gv_do_permutate("asr-gv-do-permutate",
32 cl::init(GV_DEFAULT_DO_PERMUTATE
), cl::NotHidden
, cl::ValueRequired
);
36 func_max_offset("asr-func-max-offset",
38 cl::init(FUNC_DEFAULT_MAX_OFFSET
), cl::NotHidden
, cl::ValueRequired
);
41 func_max_padding("asr-func-max-padding",
43 cl::init(FUNC_DEFAULT_MAX_PADDING
), cl::NotHidden
, cl::ValueRequired
);
46 func_max_bb_shift("asr-func-max-bb-shift",
48 cl::init(FUNC_DEFAULT_MAX_BB_SHIFT
), cl::NotHidden
, cl::ValueRequired
);
51 func_do_permutate("asr-func-do-permutate",
53 cl::init(FUNC_DEFAULT_DO_PERMUTATE
), cl::NotHidden
, cl::ValueRequired
);
57 stack_do_offset("asr-stack-do-offset",
59 cl::init(STACK_DEFAULT_DO_OFFSET
), cl::NotHidden
, cl::ValueRequired
);
62 stack_max_offset("asr-stack-max-offset",
64 cl::init(STACK_DEFAULT_MAX_OFFSET
), cl::NotHidden
, cl::ValueRequired
);
68 stackframe_do_offset("asr-stackframe-do-offset",
70 cl::init(STACKFRAME_DEFAULT_DO_OFFSET
), cl::NotHidden
, cl::ValueRequired
);
73 stackframe_max_offset("asr-stackframe-max-offset",
75 cl::init(STACKFRAME_DEFAULT_MAX_OFFSET
), cl::NotHidden
, cl::ValueRequired
);
78 stackframe_max_padding("asr-stackframe-max-padding",
80 cl::init(STACKFRAME_DEFAULT_MAX_PADDING
), cl::NotHidden
, cl::ValueRequired
);
83 stackframe_do_permutate("asr-stackframe-do-permutate",
85 cl::init(STACKFRAME_DEFAULT_DO_PERMUTATE
), cl::NotHidden
, cl::ValueRequired
);
88 stackframe_static_padding("asr-stackframe-static-padding",
90 cl::init(STACKFRAME_DEFAULT_STATIC_PADDING
), cl::NotHidden
, cl::ValueRequired
);
93 stackframe_caller_padding("asr-stackframe-caller-padding",
95 cl::init(STACKFRAME_DEFAULT_CALLER_PADDING
), cl::NotHidden
, cl::ValueRequired
);
98 heap_map_do_permutate("asr-heap-map-do-permutate",
100 cl::init(HEAP_MAP_DEFAULT_DO_PERMUTATE
), cl::NotHidden
, cl::ValueRequired
);
104 heap_max_offset("asr-heap-max-offset",
106 cl::init(HEAP_DEFAULT_MAX_OFFSET
), cl::NotHidden
, cl::ValueRequired
);
109 heap_max_padding("asr-heap-max-padding",
111 cl::init(HEAP_DEFAULT_MAX_PADDING
), cl::NotHidden
, cl::ValueRequired
);
115 map_max_offset_pages("asr-map-max-offset-pages",
117 cl::init(MAP_DEFAULT_MAX_OFFSET_PAGES
), cl::NotHidden
, cl::ValueRequired
);
120 map_max_padding_pages("asr-map-max-padding-pages",
122 cl::init(MAP_DEFAULT_MAX_PADDING_PAGES
), cl::NotHidden
, cl::ValueRequired
);
126 std::string magicMemFuncNames
[] = { MAGIC_MEM_FUNC_NAMES
};
131 PASS_COMMON_INIT_ONCE();
133 //===----------------------------------------------------------------------===//
134 // Constructors, destructor, and operators
135 //===----------------------------------------------------------------------===//
137 ASRPass::ASRPass() : ModulePass(ID
) {}
138 //===----------------------------------------------------------------------===//
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();
158 //handle the weird case of bitcasted function call
159 ConstantExpr
*CE
= dyn_cast
<ConstantExpr
>(CS
.getCalledValue());
163 assert(CE
&& CE
->getOpcode() == Instruction::BitCast
&& "Bitcast expected, something else found!");
164 function
= dyn_cast
<Function
>(CE
->getOperand(0));
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
,
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);
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
;
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
271 Function
*magicInitFunc
= M
.getFunction(MAGIC_INIT_FUNC_NAME
);
272 if( !magicInitFunc
){
273 outs() << "Error: no " << MAGIC_INIT_FUNC_NAME
<< "() found";
278 // get random seed number, or use the current time if the seed number is set to 0.
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
){
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
);
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
;
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
;
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
) {
347 /* skip certain functions */
348 if(F
->getBasicBlockList().size() == 0){
351 if(MAGIC_IS_MAGIC_FUNC(M
, F
)){
354 if(!F
->getName().compare("rand")){
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)
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();
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
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.
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. */
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
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 */
413 /* This instruction will (likely) create a pointer, because it is not a load, store or magic-function-call instruction */
418 /* Put the alloca instruction in the right helper vector, and remove from the basic block. */
420 allocaAddressTaken
.insert(allocaAddressTaken
.begin(), it
);
422 allocaNoAddressTaken
.insert(allocaNoAddressTaken
.begin(), it
);
424 it
->removeFromParent();
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
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().
452 int max_padding
= (i
==pg
.size()-1 ? 0 : stackframe_max_padding
);
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
){
467 /* give the entry function (first function) a large offset instead of an padding */
468 max_offset
= stack_max_offset
;
470 if(!stackframe_do_offset
){
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
502 NewFirstBB
->getInstList().push_front(*it
);
503 allocaNoAddressTaken
.erase(it
);
507 if(stackframe_static_padding
) {
509 new AllocaInst(IntegerType::get(M
.getContext(), 8), ConstantInt::get(M
.getContext(), APInt(64, (rand() % max_offset
) + 1, 10)), "", NewFirstBB
);
513 /* Now insert a dynamically randomized stackframe offset */
514 Function
*RandFunc
= M
.getFunction("rand");
515 assert(RandFunc
!= NULL
);
518 std::vector
<Value
*> args
;
519 CallInst
* RandFuncCall
= PassUtil::createCallInstruction(RandFunc
, args
, "", NewFirstBB
);
520 Instruction
*nextInst
= RandFuncCall
;
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);
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();
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
)) {
576 CallSite CS
= PassUtil::getCallSiteFromInstruction(I
);
577 if(!CS
.getInstruction()) {
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) {
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)));
609 unsigned shift
= (rand() % func_max_bb_shift
) + 1;
611 PassUtil::createCallInstruction(prefetchIntrinsic
, args
, "", dummyBB
);
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
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";
656 Instruction
*magicArrayBuildFuncInst
= magicDataInitFunc
->back().getTerminator();
658 GlobalVariable
* magicRootVar
= M
.getNamedGlobal(MAGIC_ROOT_VAR_NAME
);
660 outs() << "Error: no " << MAGIC_ROOT_VAR_NAME
<< " variable found";
664 Value
*seedValue
= MagicUtil::getMagicRStructFieldPtr(M
, magicArrayBuildFuncInst
, magicRootVar
, MAGIC_RSTRUCT_FIELD_ASR_SEED
);
666 outs() << "Error: no " << MAGIC_RSTRUCT_FIELD_ASR_SEED
<< " field found";
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";
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";
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";
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";
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";
706 new StoreInst(ConstantInt::get(M
.getContext(), APInt(32, map_max_padding_pages
)), mapPaddingValue
, false, magicArrayBuildFuncInst
);
719 char ASRPass::ID
= 1;
720 static RegisterPass
<ASRPass
> AP("asr", "Address Space Randomization Pass");