Fix vpadd decoding. Clean up control flow target logic and shared pointer constructio...
[dyninst.git] / parseAPI / src / BoundFactCalculator.C
1 #include "dyntypes.h"
2 #include "CodeObject.h"
3 #include "CodeSource.h"
4
5 #include "BoundFactCalculator.h"
6 #include "IndirectASTVisitor.h"
7 #include "debug_parse.h"
8 #include "JumpTablePred.h"
9 #include "Instruction.h"
10
11 using namespace Dyninst::InstructionAPI;
12
13 void BoundFactsCalculator::NaturalDFS(Node::Ptr cur) {
14     nodeColor[cur] = 1;
15     NodeIterator nbegin, nend;
16     cur->outs(nbegin, nend);
17
18     for (; nbegin != nend; ++nbegin) 
19         if (nodeColor.find(*nbegin) == nodeColor.end())
20             NaturalDFS(*nbegin);
21
22     reverseOrder.push_back(cur);
23    
24 }
25
26 void BoundFactsCalculator::ReverseDFS(Node::Ptr cur) {
27     nodeColor[cur] = 1;
28     analysisOrder[cur] = orderStamp;
29     NodeIterator nbegin, nend;
30     cur->ins(nbegin, nend);
31
32     for (; nbegin != nend; ++nbegin) 
33         if (nodeColor.find(*nbegin) == nodeColor.end())
34             ReverseDFS(*nbegin);
35 }
36
37 static void BuildEdgeFromVirtualEntry(SliceNode::Ptr virtualEntry,
38                                       ParseAPI::Block *curBlock,
39                                       map<ParseAPI::Block*, vector<SliceNode::Ptr> >&targetMap,
40                                       set<ParseAPI::Block*> &visit,
41                                       GraphPtr slice) {
42     if (targetMap.find(curBlock) != targetMap.end()) {
43         const vector<SliceNode::Ptr> &targets = targetMap[curBlock];
44         for (auto nit = targets.begin(); nit != targets.end(); ++nit) {
45             SliceNode::Ptr trgNode = *nit; 
46             slice->insertPair(virtualEntry, trgNode, TypedSliceEdge::create(virtualEntry, trgNode, FALLTHROUGH));
47         }
48         return;
49     }
50     if (visit.find(curBlock) != visit.end()) return;
51     visit.insert(curBlock);
52     for (auto eit = curBlock->targets().begin(); eit != curBlock->targets().end(); ++eit)
53         if ((*eit)->type() != CALL && (*eit)->type() != RET) {
54             BuildEdgeFromVirtualEntry(virtualEntry, (*eit)->trg(), targetMap, visit, slice);       
55         }
56 }                                     
57
58 void BoundFactsCalculator::DetermineAnalysisOrder() {
59     NodeIterator nbegin, nend;
60     slice->allNodes(nbegin, nend);
61
62     nodeColor.clear();
63     reverseOrder.clear();
64     analysisOrder.clear();
65     for (; nbegin != nend; ++nbegin) 
66         if (nodeColor.find(*nbegin) == nodeColor.end()) {
67             NaturalDFS(*nbegin);
68         }
69     nodeColor.clear();
70     orderStamp = 0;
71     for (auto nit = reverseOrder.rbegin(); nit != reverseOrder.rend(); ++nit)
72         if (nodeColor.find(*nit) == nodeColor.end()) {
73             ++orderStamp;
74             ReverseDFS(*nit);
75         }
76
77     // Create a virtual entry node that has
78     // edges into all entry SCCs
79     SliceNode::Ptr virtualEntry = SliceNode::create(Assignment::Ptr(), func->entry(), func);
80     analysisOrder[virtualEntry] = 0;
81     for (int curOrder = 1; curOrder <= orderStamp; ++curOrder) {
82         // First determine all nodes in this SCC
83         vector<Node::Ptr> curNodes;
84         NodeIterator nbegin, nend;
85         slice->allNodes(nbegin, nend);
86         for (; nbegin != nend; ++nbegin) {
87             if (analysisOrder[*nbegin] == curOrder) {
88                 curNodes.push_back(*nbegin);
89             } 
90         }
91
92         // If this SCC does not have any outside edge,
93         // it is an entry SCC and we need to connect
94         // the virtual entry to it
95         if (!HasIncomingEdgesFromLowerLevel(curOrder, curNodes)) {
96             if (curNodes.size() == 1) {
97                 // If the SCC has only one node,
98                 // we connect the virtual entry to this single node
99                 SliceNode::Ptr node = boost::static_pointer_cast<SliceNode>(*(curNodes.begin()));
100                 slice->insertPair(virtualEntry, node, TypedSliceEdge::create(virtualEntry, node, FALLTHROUGH));
101             } else {
102                 // If there are more than one node in this SCC,
103                 // we do a DFS to see which nodes in the SCC can be
104                 // reached from the entry of the function without passing
105                 // through other nodes in the SCC.
106                 // Basically, we only connect edges from the virtual entry
107                 // to the entries of the SCC
108                 set<ParseAPI::Block*> visit;
109                 map<ParseAPI::Block*, vector<SliceNode::Ptr> >targetMap;
110                 for (auto nit = curNodes.begin(); nit != curNodes.end(); ++nit) {
111                     SliceNode::Ptr node = boost::static_pointer_cast<SliceNode>(*nit);
112                     ParseAPI::Block * b = node->block();
113                     Address addr = node->addr();
114                     if (targetMap.find(b) == targetMap.end()) {
115                         targetMap[b].push_back(node);
116                     } else if (targetMap[b][0]->addr() > addr) {
117                         targetMap[b].clear();
118                         targetMap[b].push_back(node);
119                     } else if (targetMap[b][0]->addr() == addr) {
120                         targetMap[b].push_back(node);
121                     }
122                 }
123                 BuildEdgeFromVirtualEntry(virtualEntry, virtualEntry->block(), targetMap, visit, slice); 
124             }
125         }
126     }
127
128     slice->clearEntryNodes();
129     slice->markAsEntryNode(virtualEntry);
130 }
131
132 bool BoundFactsCalculator::HasIncomingEdgesFromLowerLevel(int curOrder, vector<Node::Ptr>& curNodes) {
133     for (auto nit = curNodes.begin(); nit != curNodes.end(); ++nit) {
134         Node::Ptr cur = *nit;
135         NodeIterator nbegin, nend;
136         cur->ins(nbegin, nend);
137         for (; nbegin != nend; ++nbegin) 
138             if (analysisOrder[*nbegin] < curOrder) return true;
139     }
140     return false;
141
142 }
143
144 bool BoundFactsCalculator::CalculateBoundedFacts() {    
145     /* We use a dataflow analysis to calculate the value bound
146      * of each register and potentially some memory locations.
147      * The key steps of the dataflow analysis are 
148      * 1. Determine the analysis order:
149      *    First calculate all strongly connected components (SCC)
150      *    of the graph. The flow analysis inside a SCC is 
151      *    iterative. The flow analysis between several SCCs
152      *    is done topologically. 
153      * 2. For each node, need to calculate the meet and 
154      *    calculate the transfer function.
155      * 1. The meet should be simply an intersection of all the bounded facts 
156      * along all paths. 
157      * 2. To calculate the transfer function, we first get the symbolic expression
158      * of the instrution for the node. Then depending on the instruction operation
159      * and the meet result, we know what are still bounded. For example, loading 
160      * memory is always unbounded; doing and operation on a register with a constant
161      * makes the register bounded. 
162      */
163     
164     DetermineAnalysisOrder();
165     queue<Node::Ptr> workingList;
166     unordered_set<Node::Ptr, Node::NodePtrHasher> inQueue;
167     unordered_map<Node::Ptr, int, Node::NodePtrHasher> inQueueLimit;
168
169     for (int curOrder = 0; curOrder <= orderStamp; ++curOrder) {
170         // We first determine which nodes are
171         // in this SCC
172         vector<Node::Ptr> curNodes;
173         NodeIterator nbegin, nend;
174         slice->allNodes(nbegin, nend);
175         for (; nbegin != nend; ++nbegin) {
176             if (analysisOrder[*nbegin] == curOrder) {
177                 curNodes.push_back(*nbegin);
178                 workingList.push(*nbegin);
179                 inQueue.insert(*nbegin);
180             } 
181         }
182
183         if (!HasIncomingEdgesFromLowerLevel(curOrder, curNodes)) {
184             // If this SCC is an entry SCC,
185             // we choose a node inside the SCC
186             // and let it be top.
187             // This should only contain the virtual entry node
188             parsing_printf("This SCC does not incoming edges from outside\n");
189             boundFactsIn[curNodes[0]] = new BoundFact();
190             boundFactsOut[curNodes[0]] = new BoundFact();
191         }
192         parsing_printf("Starting analysis inside SCC %d\n", curOrder);
193         // We now start iterative analysis inside the SCC
194         while (!workingList.empty()) {
195             // We get the current node
196             Node::Ptr curNode = workingList.front();
197             workingList.pop();
198             inQueue.erase(curNode);
199             
200             SliceNode::Ptr node = boost::static_pointer_cast<SliceNode>(curNode);
201             ++inQueueLimit[curNode];
202             if (inQueueLimit[curNode] > IN_QUEUE_LIMIT) continue;
203             
204             BoundFact* oldFactIn = GetBoundFactIn(curNode);
205             parsing_printf("Calculate Meet for %lx", node->addr());
206             if (node->assign()) {
207                 parsing_printf(", insn: %s\n", node->assign()->insn()->format().c_str());
208             }
209             else {
210                 if (node->block() == NULL) 
211                     parsing_printf(", the VirtualExit node\n");
212                 else
213                     parsing_printf(", the VirtualEntry node\n");
214
215             }
216             parsing_printf("\tOld fact for %lx:\n", node->addr());
217             if (oldFactIn == NULL) parsing_printf("\t\t do not exist\n"); else oldFactIn->Print();
218
219             // We find all predecessors of the current node
220             // and calculates the union of the analysis results
221             // from the predecessors
222             BoundFact* newFactIn = Meet(curNode);
223             parsing_printf("\tNew fact at %lx\n", node->addr());
224             if (newFactIn != NULL) newFactIn->Print(); else parsing_printf("\t\tNot calculated\n");
225
226             // If the current node has not been calcualted yet,
227             // or the new meet results are different from the 
228             // old ones, we keep the new results
229             if (newFactIn != NULL && (oldFactIn == NULL || *oldFactIn != *newFactIn)) {
230                 parsing_printf("\tFacts change!\n");
231                 if (oldFactIn != NULL) delete oldFactIn;
232                 boundFactsIn[curNode] = newFactIn;
233                 BoundFact* newFactOut = new BoundFact(*newFactIn);
234
235                 // The current node has a transfer function
236                 // that changes the analysis results
237                 CalcTransferFunction(curNode, newFactOut);
238         
239                 if (boundFactsOut.find(curNode) != boundFactsOut.end() && boundFactsOut[curNode] != NULL)
240                     delete boundFactsOut[curNode];                  
241                 boundFactsOut[curNode] = newFactOut;
242                 curNode->outs(nbegin, nend);
243                 for (; nbegin != nend; ++nbegin)
244                     // We only add node inside current SCC into the working list
245                     if (inQueue.find(*nbegin) == inQueue.end() && analysisOrder[*nbegin] == curOrder) {
246                         workingList.push(*nbegin);
247                         inQueue.insert(*nbegin);
248                     }
249             } else {
250                 if (newFactIn != NULL) delete newFactIn;
251                 parsing_printf("\tFacts do not change!\n");
252             }
253
254         }
255     }
256
257     return true;
258 }
259
260
261
262
263 void BoundFactsCalculator::ThunkBound( BoundFact*& curFact, Node::Ptr src, Node::Ptr trg, bool &newCopy) {
264
265     // This function checks whether any found thunk is between 
266     // the src node and the trg node. If there is any, then we have 
267     // extra bound information to be added.
268     ParseAPI::Block *srcBlock;
269     Address srcAddr = 0;
270     if (src == Node::Ptr()) 
271         srcBlock = func->entry();
272     else {
273         SliceNode::Ptr srcNode = boost::static_pointer_cast<SliceNode>(src);
274         srcBlock = srcNode->block();
275         srcAddr = srcNode->addr();
276
277     }
278     SliceNode::Ptr trgNode = boost::static_pointer_cast<SliceNode>(trg);                               
279     ParseAPI::Block *trgBlock = trgNode->block();
280     Address trgAddr = trgNode->addr();
281
282     bool first = true;
283     for (auto tit = thunks.begin(); tit != thunks.end(); ++tit) {
284         ParseAPI::Block* thunkBlock = tit->second.block;
285         parsing_printf("\t\tCheck srcAddr at %lx, trgAddr at %lx, thunk at %lx\n", srcAddr, trgAddr, tit->first);
286         if (src != Node::Ptr()) {
287             if (srcBlock == thunkBlock) {
288                 if (srcAddr > tit->first) continue;
289             } else {
290                 if (rf.thunk_ins[thunkBlock].find(srcBlock) == rf.thunk_ins[thunkBlock].end()) continue;
291             }
292         }
293         if (trgBlock == thunkBlock) {
294             if (trgAddr < tit->first) continue;
295         } else {
296             if (rf.thunk_outs[thunkBlock].find(trgBlock) == rf.thunk_outs[thunkBlock].end()) continue;
297         }
298
299         parsing_printf("\t\t\tfind thunk at %lx between the source and the target. Add fact", tit->first);
300         BoundValue *bv = new BoundValue(tit->second.value);
301         bv->Print();
302         if (first && !newCopy) {
303             newCopy = true;
304             curFact = new BoundFact(*curFact);
305         }
306         curFact->GenFact(VariableAST::create(Variable(AbsRegion(Absloc(tit->second.reg)))), bv, false);
307         first = false;
308     }
309
310
311 }
312
313
314 static bool IsConditionalJump(Instruction::Ptr insn) {
315     entryID id = insn->getOperation().getID();
316
317     if (id == e_jz || id == e_jnz ||
318         id == e_jb || id == e_jnb ||
319         id == e_jbe || id == e_jnbe ||
320         id == e_jb_jnaej_j || id == e_jnb_jae_j ||
321         id == e_jle || id == e_jl ||
322         id == e_jnl || id == e_jnle) return true;
323     return false;
324 }
325
326 BoundFact* BoundFactsCalculator::Meet(Node::Ptr curNode) {
327
328     SliceNode::Ptr node = boost::static_pointer_cast<SliceNode>(curNode);     
329
330     EdgeIterator gbegin, gend;
331     curNode->ins(gbegin, gend);    
332     BoundFact* newFact = NULL;
333     
334     bool first = true;  
335     for (; gbegin != gend; ++gbegin) {
336         TypedSliceEdge::Ptr edge = boost::static_pointer_cast<TypedSliceEdge>(*gbegin); 
337         SliceNode::Ptr srcNode = boost::static_pointer_cast<SliceNode>(edge->source()); 
338         BoundFact *prevFact = GetBoundFactOut(srcNode);     
339         bool newCopy = false;
340         if (prevFact == NULL) {
341             parsing_printf("\t\tIncoming node %lx has not been calculated yet, ignore it\n", srcNode->addr());
342             continue;
343         } else {            
344             // Otherwise, create a new copy.
345             // We do not want to overwrite the bound fact
346             // of the predecessor
347             prevFact = new BoundFact(*prevFact);
348                 newCopy = true;
349         }
350         parsing_printf("\t\tMeet incoming edge from %lx\n", srcNode->addr());
351         parsing_printf("\t\tThe fact from %lx before applying transfer function\n", srcNode->addr());
352         prevFact->Print();
353         if (!srcNode->assign()) {
354             prevFact = new BoundFact(*prevFact);
355             newCopy = true;
356             parsing_printf("\t\tThe predecessor node is the virtual entry ndoe\n");
357             if (firstBlock) {
358                 // If the indirect jump is in the entry block
359                 // of the function, we assume that rax is in
360                 // range [0,8] for analyzing the movaps table.
361                 // NEED TO HAVE A SAFE WAY TO DO THIS!!
362                 parsing_printf("\t\tApplying entry block rax assumption!\n");
363                 AST::Ptr axAST;
364                 if (func->entry()->obj()->cs()->getAddressWidth() == 8)
365                     axAST = VariableAST::create(Variable(AbsRegion(Absloc(x86_64::rax))));
366                 else
367                     // DOES THIS REALLY SHOW UP IN 32-BIT CODE???
368                     axAST = VariableAST::create(Variable(AbsRegion(Absloc(x86::eax))));
369                 prevFact->GenFact(axAST, new BoundValue(StridedInterval(1,0,8)), false);
370             }
371         } else if (srcNode->assign() && IsConditionalJump(srcNode->assign()->insn())) {
372             prevFact = new BoundFact(*prevFact);
373             newCopy = true;
374             // If the predecessor is a conditional jump,
375             // we can determine bound fact based on the predicate and the edge type
376             parsing_printf("\t\tThe predecessor node is a conditional jump!\n");
377             if (!prevFact->ConditionalJumpBound(srcNode->assign()->insn(), edge->type())) {
378                 fprintf(stderr, "From %lx to %lx\n", srcNode->addr(), node->addr());
379                 assert(0);
380             }
381         } 
382         ThunkBound(prevFact, srcNode, node, newCopy);
383         parsing_printf("\t\tFact from %lx after applying transfer function\n", srcNode->addr());
384         prevFact->Print();
385         if (first) {
386             // For the first incoming dataflow fact,
387             // we just copy it.
388             // We can do this because if an a-loc
389             // is missing in the fact map, we assume
390             // the a-loc is top. 
391             first = false;
392             if (newCopy) newFact = prevFact; else newFact = new BoundFact(*prevFact);
393         } else {
394             newFact->Meet(*prevFact);
395             if (newCopy) delete prevFact;
396         }
397     }
398     return newFact;
399 }
400
401 void BoundFactsCalculator::CalcTransferFunction(Node::Ptr curNode, BoundFact *newFact){
402     SliceNode::Ptr node = boost::static_pointer_cast<SliceNode>(curNode);    
403     if (!node->assign()) return;
404     if (node->assign() && node->assign()->out().absloc().type() == Absloc::Register &&
405             (node->assign()->out().absloc().reg() == x86::zf || node->assign()->out().absloc().reg() == x86_64::zf)) {
406             // zf should be only predecessor of this node
407         parsing_printf("\t\tThe predecessor node is zf assignment!\n");
408         newFact->SetPredicate(node->assign(), ExpandAssignment(node->assign()) );           
409         return;
410     }
411     entryID id = node->assign()->insn()->getOperation().getID();
412     // The predecessor is not a conditional jump,
413     // then we can determine buond fact based on the src assignment
414     parsing_printf("\t\tThe predecessor node is normal node\n");
415     parsing_printf("\t\t\tentry id %d\n", id);
416
417     AbsRegion &ar = node->assign()->out();
418     Instruction::Ptr insn = node->assign()->insn();
419     pair<AST::Ptr, bool> expandRet = ExpandAssignment(node->assign());
420         
421     if (expandRet.first == NULL) {
422         parsing_printf("\t\t\t No semantic support for this instruction. Assume it does not affect jump target calculation. Ignore it (Treat as identity function) except for ptest. ptest should kill the current predicate\n");       
423         if (id == e_ptest) {
424             parsing_printf("\t\t\t\tptest instruction, kill predciate.\n");
425             newFact->pred.valid = false;
426         }
427         return;
428     } else {
429         parsing_printf("\tAST: %s\n", expandRet.first->format().c_str());
430     }
431     
432     AST::Ptr calculation = expandRet.first;     
433     BoundCalcVisitor bcv(*newFact, node->block(), handleOneByteRead);
434     calculation->accept(&bcv);
435     AST::Ptr outAST;
436     // If the instruction writes memory,
437     // we need the AST that represents the memory access and the address.
438     // When the AbsRegion represents memory,
439     // the generator of the AbsRegion is set to be the AST that represents
440     // the memory address during symbolic expansion.
441     // In other cases, if the AbsRegion represents a register,
442     // the generator is not set.
443     if (ar.generator() != NULL) 
444         outAST = SimplifyAnAST(RoseAST::create(ROSEOperation(ROSEOperation::derefOp, ar.size()), ar.generator()), node->assign()->insn()->size());
445     else
446         outAST = VariableAST::create(Variable(ar));
447 /*
448  * Naively, bsf and bsr produces a bound from 0 to the number of bits of the source operands.
449  * In pratice, especially in libc, the real bound is usually smaller than the size of the source operand.
450  * Ex 1: shl    %cl,%edx
451  *       bsf    %rdx,%rcx
452  * Here rcx is in range [0,31] rather than [0,63] even though rdx has 64 bits.
453  *
454  * Ex 2: pmovmskb %xmm0,%edx
455  *       bsf    %rdx, %rdx
456  * Here rdx is in range[0,15] because pmovmskb only sets the least significat 16 bits
457  * In addition, overapproximation of the bound can lead to bogus control flow
458  * that causes overlapping blocks or function.
459  * It is important to further anaylze the operand in bsf rather than directly conclude the bound
460     if (id == e_bsf || id == e_bsr) {
461         int size = node->assign()->insn()->getOperand(0).getValue()->size();
462         newFact->GenFact(outAST, new BoundValue(StridedInterval(1,0, size * 8 - 1)), false);
463         parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
464         newFact->Print();
465         return;
466
467     }
468 */
469     if (id == e_xchg) {
470         newFact->SwapFact(calculation, outAST);
471         parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
472         newFact->Print();
473         return;
474     }
475
476     if (id == e_push) {
477          if (calculation->getID() == AST::V_ConstantAST) {
478              ConstantAST::Ptr c = boost::static_pointer_cast<ConstantAST>(calculation);
479              newFact->PushAConst(c->val().val);
480              parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
481              newFact->Print();
482              return;
483          }
484     }
485
486     if (id == e_pop) {
487         if (newFact->PopAConst(outAST)) {
488              parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
489              newFact->Print();
490              return;
491         }            
492     }
493
494     // Assume all SETxx entry ids are contiguous    
495     if (id >= e_setb && id <= e_setz) {
496         newFact->GenFact(outAST, new BoundValue(StridedInterval(1,0,1)), false);
497         parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
498         newFact->Print();
499         return;
500     }
501
502
503     if (bcv.IsResultBounded(calculation)) { 
504         parsing_printf("\t\t\tGenerate bound fact for %s\n", outAST->format().c_str());
505         newFact->GenFact(outAST, new BoundValue(*bcv.GetResultBound(calculation)), false);
506     }
507     else {
508         parsing_printf("\t\t\tKill bound fact for %s\n", outAST->format().c_str());
509         newFact->KillFact(outAST, false);
510     }
511     if (calculation->getID() == AST::V_VariableAST) {
512         // We only track alising between registers
513         parsing_printf("\t\t\t%s and %s are equal\n", calculation->format().c_str(), outAST->format().c_str());
514         newFact->InsertRelation(calculation, outAST, BoundFact::Equal);
515     }
516     newFact->AdjustPredicate(outAST, calculation);
517
518     // Now try to track all aliasing.
519     // Currently, all variables in the slice are presented as an AST 
520     // consists of input variables to the slice (the variables that 
521     // we do not the sources of their values).
522     newFact->TrackAlias(DeepCopyAnAST(calculation), outAST);
523
524     // Apply tracking relations to the calculation to generate a
525     // potentially stricter bound
526     BoundValue *strictValue = newFact->ApplyRelations(outAST);
527     if (strictValue != NULL) {
528         parsing_printf("\t\t\tGenerate stricter bound fact for %s\n", outAST->format().c_str());
529         newFact->GenFact(outAST, strictValue, false);
530     }
531     parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
532     newFact->Print();
533
534 }                                               
535
536 BoundFact* BoundFactsCalculator::GetBoundFactIn(Node::Ptr node) {
537     auto fit = boundFactsIn.find(node);
538     if (fit == boundFactsIn.end())
539         return NULL;
540     else
541         return fit->second;
542 }
543 BoundFact* BoundFactsCalculator::GetBoundFactOut(Node::Ptr node) {
544     auto fit = boundFactsOut.find(node);
545     if (fit == boundFactsOut.end())
546         return NULL;
547     else
548         return fit->second;
549 }
550 BoundFactsCalculator::~BoundFactsCalculator() {
551     for (auto fit = boundFactsIn.begin(); fit != boundFactsIn.end(); ++fit)
552         if (fit->second != NULL)
553             delete fit->second;
554     boundFactsIn.clear();
555     for (auto fit = boundFactsOut.begin(); fit != boundFactsOut.end(); ++fit)
556         if (fit->second != NULL)
557             delete fit->second;
558     boundFactsOut.clear();
559
560 }
561
562 pair<AST::Ptr, bool> BoundFactsCalculator::ExpandAssignment(Assignment::Ptr assign) {
563     parsing_printf("Expand assignment : %s Instruction: %s\n", assign->format().c_str(), assign->insn()->format().c_str());
564     if (expandCache.find(assign) != expandCache.end()) {
565         AST::Ptr ast = expandCache[assign];
566         if (ast) return make_pair(ast, true); else return make_pair(ast, false);
567
568     } else {
569         pair<AST::Ptr, bool> expandRet = SymEval::expand(assign, false);
570         if (expandRet.second && expandRet.first) {
571             parsing_printf("Original expand: %s\n", expandRet.first->format().c_str());
572             AST::Ptr calculation = SimplifyAnAST(expandRet.first, assign->insn()->size());
573             expandCache[assign] = calculation;
574         } else {
575             expandCache[assign] = AST::Ptr();
576         }
577         return make_pair( expandCache[assign], expandRet.second );
578     }
579 }
580