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