Fixes for AbsRegion and jump table index slicing involving global variable (#695)
[dyninst.git] / dataflowAPI / src / AbslocInterface.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31
32 #include "Absloc.h"
33 #include "AbslocInterface.h"
34
35 // Pile of InstructionAPI includes
36 #include "Expression.h"
37 #include "Register.h"
38 #include "Result.h"
39 #include "Dereference.h"
40 #include "BinaryFunction.h"
41 #include "Immediate.h"
42
43 #include "dataflowAPI/h/stackanalysis.h"
44 #include "common/src/singleton_object_pool.h"
45 #include "parseAPI/h/CFG.h"
46 #include "parseAPI/h/CodeObject.h"
47
48 using namespace Dyninst;
49 using namespace Dyninst::InstructionAPI;
50 extern int df_debug_stackanalysis;
51
52 template class std::vector<boost::shared_ptr<Dyninst::Assignment> >;
53
54 void AbsRegionConverter::convertAll(InstructionAPI::Expression::Ptr expr,
55                                     Address addr,
56                                     ParseAPI::Function *func,
57                                     ParseAPI::Block *block,
58                                     std::vector<AbsRegion> &regions) {
59   // If we're a memory dereference, then convert us and all
60   // used registers.
61   if (boost::dynamic_pointer_cast<Dereference>(expr)) {
62     std::vector<Expression::Ptr> tmp;
63     // Strip dereference...
64     expr->getChildren(tmp);
65     for (std::vector<Expression::Ptr>::const_iterator i = tmp.begin();
66          i != tmp.end(); ++i) {
67        regions.push_back(convert(*i, addr, func, block));
68     }
69   }
70   
71   // Otherwise just convert registers
72   
73   std::set<InstructionAST::Ptr> used;
74   expr->getUses(used);
75   for (std::set<InstructionAST::Ptr>::const_iterator j = used.begin();
76        j != used.end(); ++j) {
77     regions.push_back(convert(boost::dynamic_pointer_cast<RegisterAST>(*j)));
78   }
79 }
80
81 void AbsRegionConverter::convertAll(InstructionAPI::Instruction insn,
82                                     Address addr,
83                                     ParseAPI::Function *func,
84                                     ParseAPI::Block *block,
85                                     std::vector<AbsRegion> &used,
86                                     std::vector<AbsRegion> &defined) {
87                         
88                         if (!usedCache(addr, func, used)) {
89     std::set<RegisterAST::Ptr> regsRead;
90     insn.getReadSet(regsRead);
91
92
93     for (std::set<RegisterAST::Ptr>::const_iterator i = regsRead.begin();
94          i != regsRead.end(); ++i) {
95         if(insn.getArch() == Arch_aarch64) {
96             MachRegister machReg = (*i)->getID();
97             std::vector<MachRegister> flagRegs = {aarch64::n, aarch64::z, aarch64::c, aarch64::v};
98
99             if((machReg & 0xFF) == (aarch64::pstate & 0xFF) && (machReg & 0xFF0000) == (aarch64::SPR)) {
100                 for(std::vector<MachRegister>::iterator itr = flagRegs.begin(); itr != flagRegs.end(); itr++) {
101                     used.push_back(AbsRegionConverter::convert(RegisterAST::Ptr(new RegisterAST(*itr))));
102                 }
103             } else {
104                 used.push_back(AbsRegionConverter::convert(*i));
105             }
106         } else {
107             used.push_back(AbsRegionConverter::convert(*i));
108         }
109     }
110     
111     if (insn.readsMemory()) {
112       std::set<Expression::Ptr> memReads;
113       insn.getMemoryReadOperands(memReads);
114       for (std::set<Expression::Ptr>::const_iterator r = memReads.begin();
115            r != memReads.end();
116            ++r) {
117          used.push_back(AbsRegionConverter::convert(*r, addr, func, block));
118       }
119     }
120   }
121   if (!definedCache(addr, func, defined)) {
122     // Defined time
123     std::set<RegisterAST::Ptr> regsWritten;
124     insn.getWriteSet(regsWritten);
125     for (std::set<RegisterAST::Ptr>::const_iterator i = regsWritten.begin();
126          i != regsWritten.end(); ++i) {
127       if(insn.getArch() == Arch_aarch64) {
128             MachRegister machReg = (*i)->getID();
129             std::vector<MachRegister> flagRegs = {aarch64::n, aarch64::z, aarch64::c, aarch64::v};
130
131             if((machReg & 0xFF) == (aarch64::pstate & 0xFF) && (machReg & 0xFF0000) == (aarch64::SPR)) {
132                 for(std::vector<MachRegister>::iterator itr = flagRegs.begin(); itr != flagRegs.end(); itr++) {
133                     defined.push_back(AbsRegionConverter::convert(RegisterAST::Ptr(new RegisterAST(*itr))));
134                 }
135             } else {
136                 defined.push_back(AbsRegionConverter::convert(*i));
137             }
138         } else {
139             defined.push_back(AbsRegionConverter::convert(*i));
140         }
141     }
142
143     // special case for repeat-prefixed instructions on x86
144     // may disappear if Dyninst's representation of these instructions changes
145     if (insn.getArch() == Arch_x86) {
146       prefixEntryID insnPrefix = insn.getOperation().getPrefixID();
147       if ( (prefix_rep == insnPrefix) || (prefix_repnz == insnPrefix) ) {
148         defined.push_back(AbsRegionConverter::convert(RegisterAST::Ptr(
149           new RegisterAST(MachRegister::getPC(Arch_x86)))));
150       }
151     }
152     
153     if (insn.writesMemory()) {
154       std::set<Expression::Ptr> memWrites;
155       insn.getMemoryWriteOperands(memWrites);
156       for (std::set<Expression::Ptr>::const_iterator r = memWrites.begin();
157            r != memWrites.end();
158            ++r) {
159          defined.push_back(AbsRegionConverter::convert(*r, addr, func, block));
160       }
161     }
162   }
163
164   if (cacheEnabled_) {
165     used_cache_[func][addr] = used;
166     defined_cache_[func][addr] = defined;
167   }
168 }
169
170 AbsRegion AbsRegionConverter::convert(RegisterAST::Ptr reg) {
171   // We do not distinguish partial registers from full register.
172   // So, eax and rax are treated the same.
173   // But for flags, we want to separate CF, ZF, and so on
174   if (reg->getID().isFlag()) {
175     return AbsRegion(Absloc(reg->getID()));
176   } else {
177     return AbsRegion(Absloc(reg->getID().getBaseRegister()));
178   }                
179 }
180
181 class bindKnownRegs : public InstructionAPI::Visitor
182 {
183 public:
184     bindKnownRegs(Address sp, Address fp, Address ip, bool sdef, bool fdef) :
185             defined(true),
186             is_stack(false),
187             is_frame(false),
188             m_sp(sp),
189             m_fp(fp),
190             m_ip(ip),
191             stackDefined(sdef),
192             frameDefined(fdef) {}
193     virtual ~bindKnownRegs() {}
194     bool defined;
195     bool is_stack;
196     bool is_frame;
197     std::deque<long> results;
198     Address m_sp;
199     Address m_fp;
200     Address m_ip;
201     bool stackDefined;
202     bool frameDefined;
203     long getResult() {
204         if(results.empty()) return 0;
205         return results.front();
206     }
207     bool isDefined() {
208         return defined && (results.size() == 1);
209     }
210     virtual void visit(BinaryFunction* b)
211     {
212         if(!defined) return;
213         long arg1 = results.back();
214         results.pop_back();
215         long arg2 = results.back();
216         results.pop_back();
217         if(b->isAdd())
218         {
219             results.push_back(arg1+arg2);
220         }
221         else if(b->isMultiply())
222         {
223             results.push_back(arg1*arg2);
224         }
225         else
226         {
227             defined = false;
228         }
229     }
230     virtual void visit(Immediate* i)
231     {
232         if(!defined) return;
233         results.push_back(i->eval().convert<long>());
234     }
235     virtual void visit(RegisterAST* r)
236     {
237         if(!defined) return;
238         if(r->getID().isPC())
239         {
240             results.push_back(m_ip);
241             return;
242         }
243         if(r->getID().isFramePointer() && frameDefined)
244         {
245             results.push_back(m_fp);
246             is_frame = true;
247             return;
248         }
249         if(r->getID().isStackPointer() && stackDefined)
250         {
251             results.push_back(m_sp);
252             is_stack = true;
253             return;
254         }
255
256         defined = false;
257         results.push_back(0);
258     }
259     virtual void visit(Dereference* )
260     {
261         //defined = false;
262     }
263
264 };
265
266
267 AbsRegion AbsRegionConverter::convert(Expression::Ptr exp,
268                                       Address addr,
269                                       ParseAPI::Function *func,
270                                       ParseAPI::Block *block) {
271     // We want to simplify the expression as much as possible given 
272     // currently known state, and then quantify it as one of the following:
273     // 
274     // Stack: a memory access based off the current frame pointer (FP) or
275     //   stack pointer (SP). If we can determine an offset from the "top"
276     //   of the stack we create a stack slot location. Otherwise we create
277     //   a "stack" location that represents all stack locations.
278     //
279     // Heap: a memory access to a generic pointer.
280     //
281     // Memory: a memory access to a known address. 
282     //
283     // TODO: aliasing relations. Aliasing SUCKS. 
284
285     // Since we have an Expression as input, we don't have the dereference
286     // operator.
287
288     // Here's the logic:
289     // If no registers are used:
290     //   If only immediates are used:
291     //     Evaluate and create a MemLoc.
292     //   If a dereference exists:
293     //     WTF???
294     // If registers are used:
295     //   If the only register is the FP AND the function has a stack frame:
296     //     Set FP to 0, eval, and create a specific StackLoc.
297     //   If the only register is the SP:
298     //     If we know the contents of SP:
299     //       Eval and create a specific StackLoc
300     //     Else create a generic StackLoc.
301     //   If a non-stack register is used:
302     //     Create a generic MemLoc.
303
304     long spHeight = 0;
305     bool stackDefined = getCurrentStackHeight(func,
306                                               block,
307                                               addr, 
308                                               spHeight);
309     long fpHeight = 0;
310     bool frameDefined = getCurrentFrameHeight(func,
311                                               block,
312                                               addr,
313                                               fpHeight);
314
315     // Currently, we only bind sp, fp, and pc.
316     // If we decide to also bind aliases of these registers,
317     // we need to change bindKnownRegs accordingly.
318     Address pcVal = addr;
319     if (block->obj()->cs()->getArch() == Arch_x86 || block->obj()->cs()->getArch() == Arch_x86_64) {
320         // PC value on x86/64 is post-instruction
321         pcVal += block->getInsn(addr).size();
322     }
323
324     bindKnownRegs calc(spHeight, fpHeight, pcVal, stackDefined, frameDefined);
325     exp->apply(&calc);
326     bool isFrame = calc.is_frame;
327     bool isStack = calc.is_stack;
328     Address res = calc.getResult();
329
330     if (isFrame && stackAnalysisEnabled_) {
331       if (calc.isDefined() && frameDefined) {
332         return AbsRegion(Absloc(res, 0, func));
333       }
334       else {
335         return AbsRegion(Absloc::Stack);
336       }
337     }
338
339     if (isStack && stackAnalysisEnabled_) {
340       if (calc.isDefined() && stackDefined) {
341          return AbsRegion(Absloc(res,
342                                  0,
343                                  func));
344       }
345       else if (func->obj()->defensiveMode()) {
346           // SP could point to the heap, we make the worst-case 
347           // assumption and will emulate this stack access
348           return AbsRegion(Absloc::Heap); 
349       } else {
350          return AbsRegion(Absloc::Stack);
351       }
352     }
353
354     // Otherwise we're on the heap
355     if (calc.isDefined()) {
356       return AbsRegion(Absloc(res));
357     }
358     else {
359       return AbsRegion(Absloc::Heap);
360     }
361 }
362
363 AbsRegion AbsRegionConverter::stack(Address addr,
364                                     ParseAPI::Function *func,
365                                     ParseAPI::Block *block,
366                                     bool push) {
367     if(!stackAnalysisEnabled_) {
368 //        std::cerr << "Stack analysis disabled, returning Stack absregion" << std::endl;
369         return AbsRegion(Absloc::Stack);
370     }
371     long spHeight = 0;
372     bool stackExists = getCurrentStackHeight(func,
373                                              block,
374                                              addr, 
375                                              spHeight);
376     if (!stackExists) {
377       return AbsRegion(Absloc::Stack);
378     }
379
380     if (push) {
381       int word_size = func->isrc()->getAddressWidth();
382       spHeight -= word_size;
383     }
384
385     return AbsRegion(Absloc(spHeight,
386                             0,
387                             func));
388 }
389
390 AbsRegion AbsRegionConverter::frame(Address addr,
391                                     ParseAPI::Function *func,
392                                     ParseAPI::Block *block,
393                                     bool push) {
394     long fpHeight = 0;
395     bool frameExists = getCurrentFrameHeight(func,
396                                              block,
397                                              addr, 
398                                              fpHeight);
399
400     if (!frameExists) {
401       return AbsRegion(Absloc::Heap);
402     }
403
404     if (push) {
405       int word_size = func->isrc()->getAddressWidth();
406       fpHeight -= word_size;
407     }
408     
409     return AbsRegion(Absloc(fpHeight,
410                             0,
411                             func));
412 }
413
414 bool AbsRegionConverter::getCurrentStackHeight(ParseAPI::Function *func,
415                                                ParseAPI::Block *block,
416                                                Address addr,
417                                                long &height) {
418   if (!stackAnalysisEnabled_) return false;
419   StackAnalysis sA(func);
420  
421   StackAnalysis::Height heightSA = sA.findSP(block, addr);
422
423   // Ensure that analysis has been performed.
424   assert(!heightSA.isTop());
425   
426   if (heightSA.isBottom()) {
427     return false;
428   }
429   
430   height = heightSA.height();
431   
432   return true;
433 }
434
435 bool AbsRegionConverter::getCurrentFrameHeight(ParseAPI::Function *func,
436                                                ParseAPI::Block *block,
437                                                Address addr,
438                                                long &height) {
439   if (!stackAnalysisEnabled_) return false;                                            
440   StackAnalysis sA(func);
441
442   StackAnalysis::Height heightSA = sA.find(block, addr, MachRegister::getFramePointer(func->isrc()->getArch()));;
443
444   // Ensure that analysis has been performed.
445   assert(!heightSA.isTop());
446   
447   if (heightSA.isBottom()) {
448     return false;
449   }
450   
451   height = heightSA.height();
452   
453   return true;
454 }
455
456
457 bool AbsRegionConverter::usedCache(Address addr,
458                                    ParseAPI::Function *func,
459                                    std::vector<AbsRegion> &used) {
460   if (!cacheEnabled_) return false;
461   FuncCache::iterator iter = used_cache_.find(func);
462   if (iter == used_cache_.end()) return false;
463   AddrCache::iterator iter2 = iter->second.find(addr);
464   if (iter2 == iter->second.end()) return false;
465   used = iter2->second;
466   return true;
467 }
468
469 bool AbsRegionConverter::definedCache(Address addr,
470                                       ParseAPI::Function *func,
471                                       std::vector<AbsRegion> &defined) {
472   if (!cacheEnabled_) return false;
473   FuncCache::iterator iter = defined_cache_.find(func);
474   if (iter == defined_cache_.end()) return false;
475   AddrCache::iterator iter2 = iter->second.find(addr);
476   if (iter2 == iter->second.end()) return false;
477   defined = iter2->second;
478   return true;
479 }
480
481 ///////////////////////////////////////////////////////
482 // Create a set of Assignments from an InstructionAPI
483 // Instruction.
484 ///////////////////////////////////////////////////////
485
486 void AssignmentConverter::convert(const Instruction I, 
487                                   const Address &addr,
488                                   ParseAPI::Function *func,
489                                   ParseAPI::Block *block,
490                                   std::vector<Assignment::Ptr> &assignments) {
491   assignments.clear();
492   if (cache(func, addr, assignments)) return;
493
494   // Decompose the instruction into a set of abstract assignments.
495   // We don't have the Definition class concept yet, so we'll do the 
496   // hard work here. 
497   // Two phases:
498   // 1) Special-cased for IA32 multiple definition instructions,
499   //    based on the opcode of the instruction
500   // 2) Generic handling for things like flags and the PC. 
501
502   // Non-PC handling section
503   switch(I.getOperation().getID()) {
504   case e_push: {
505     // SP = SP - 4 
506     // *SP = <register>
507  
508     std::vector<Operand> operands;
509     I.getOperands(operands);
510
511     // According to the InstructionAPI, the first operand will be the argument, the second will be ESP.
512     assert(operands.size() == 2);
513
514     // The argument can be any of the following:
515     // 1) a register (push eax);
516     // 2) an immediate value (push $deadbeef)
517     // 3) a memory location. 
518
519     std::vector<AbsRegion> oper0;
520     aConverter.convertAll(operands[0].getValue(),
521                           addr,
522                           func,
523                           block,
524                           oper0);
525
526     handlePushEquivalent(I, addr, func, block, oper0, assignments);
527     break;
528   }
529   case e_call: {
530     // This can be seen as a push of the PC...
531
532     std::vector<AbsRegion> pcRegion;
533     pcRegion.push_back(Absloc::makePC(func->isrc()->getArch()));
534     Absloc sp = Absloc::makeSP(func->isrc()->getArch());
535     
536     handlePushEquivalent(I, addr, func, block, pcRegion, assignments);
537
538     // Now for the PC definition
539     // Assume full intra-dependence of non-flag and non-pc registers. 
540     std::vector<AbsRegion> used;
541     std::vector<AbsRegion> defined;
542
543     aConverter.convertAll(I,
544                           addr,
545                           func,
546                           block,
547                           used,
548                           defined);
549
550     Assignment::Ptr a = Assignment::makeAssignment(I, addr, func, block, pcRegion[0]);
551     if (!used.empty()) {
552         for(std::vector<AbsRegion>::const_iterator u = used.begin();
553             u != used.end();
554             ++u)
555         {
556             if(!(u->contains(pcRegion[0])) &&
557                  !(u->contains(sp)))
558             {
559                 a->addInput(*u);
560             }
561         }
562     }
563     else {
564       a->addInputs(pcRegion);
565     }
566     assignments.push_back(a);
567     break;
568   }
569   case e_pop: {
570     // <reg> = *SP
571     // SP = SP + 4/8
572     // Amusingly... this doesn't have an intra-instruction dependence. It should to enforce
573     // the order that <reg> = *SP happens before SP = SP - 4, but since the input to both 
574     // uses of SP in this case are the, well, input values... no "sideways" edges. 
575     // However, we still special-case it so that SP doesn't depend on the incoming stack value...
576     // Also, we use the same logic for return, defining it as
577     // PC = *SP
578     // SP = SP + 4/8
579
580     // As with push, eSP shows up as operand 1. 
581
582     std::vector<Operand> operands;
583     I.getOperands(operands);
584
585     // According to the InstructionAPI, the first operand will be the explicit register, the second will be ESP.
586     assert(operands.size() == 2);
587
588     std::vector<AbsRegion> oper0;
589     aConverter.convertAll(operands[0].getValue(),
590                           addr,
591                           func,
592                           block,
593                           oper0);
594
595     handlePopEquivalent(I, addr, func, block, oper0, assignments);
596     break;
597   }
598   case e_leave: {
599     // a leave is equivalent to:
600     // mov ebp, esp
601     // pop ebp
602     // From a definition POV, we have the following:
603     // SP = BP
604     // BP = *SP
605         
606     // BP    STACK[newSP]
607     //  |    |
608     //  v    v
609     // SP -> BP
610         
611     // This is going to give the stack analysis fits... for now, I think it just reverts the
612     // stack depth to 0. 
613
614     // TODO FIXME update stack analysis to make this really work. 
615         
616     AbsRegion sp(Absloc::makeSP(func->isrc()->getArch()));
617     AbsRegion fp(Absloc::makeFP(func->isrc()->getArch()));
618
619     // Should be "we assign SP using FP"
620     Assignment::Ptr spA = Assignment::makeAssignment(I,
621                                                          addr,
622                                                          func,
623                                                          block,
624                                                          sp);
625     spA->addInput(fp);
626
627     // And now we want "FP = (stack slot -2*wordsize)"
628     /*
629       AbsRegion stackTop(Absloc(0,
630       0,
631       func));
632     */
633     // Actually, I think this is ebp = pop esp === ebp = pop ebp
634     Assignment::Ptr fpA = Assignment::makeAssignment(I,
635                                                          addr,
636                                                          func,
637                                                          block,
638                                                          fp);
639     //fpA->addInput(aConverter.stack(addr + I->size(), func, false));
640     fpA->addInput(aConverter.frame(addr, func, block, false));
641
642     assignments.push_back(spA);
643     assignments.push_back(fpA);
644     break;
645   }
646   case e_ret_near:
647   case e_ret_far: {
648     // PC = *SP
649     // SP = SP + 4/8
650     // Like pop, except it's all implicit.
651
652     AbsRegion pc = AbsRegion(Absloc::makePC(func->isrc()->getArch()));
653     Assignment::Ptr pcA = Assignment::makeAssignment(I, 
654                                                          addr,
655                                                          func,
656                                                          block,
657                                                          pc);
658     pcA->addInput(aConverter.stack(addr, func, block, false));
659
660     AbsRegion sp = AbsRegion(Absloc::makeSP(func->isrc()->getArch()));
661     Assignment::Ptr spA = Assignment::makeAssignment(I,
662                                                          addr,
663                                                          func,
664                                                          block,
665                                                          sp);
666     spA->addInput(sp);
667
668     assignments.push_back(pcA);
669     assignments.push_back(spA);
670     break;
671   }
672
673   case e_xchg: {
674     // xchg defines two abslocs, and uses them as appropriate...
675
676     std::vector<Operand> operands;
677     I.getOperands(operands);
678
679     // According to the InstructionAPI, the first operand will be the argument, the second will be ESP.
680     assert(operands.size() == 2);
681
682     // We use the first to define the second, and vice versa
683     std::vector<AbsRegion> oper0;
684     aConverter.convertAll(operands[0].getValue(),
685                           addr,
686                           func,
687                           block,
688                           oper0);
689     
690     std::vector<AbsRegion> oper1;
691     aConverter.convertAll(operands[1].getValue(),
692                           addr,
693                           func,
694                           block,
695                           oper1);
696
697     // Okay. We may have a memory reference in here, which will
698     // cause either oper0 or oper1 to have multiple entries (the
699     // remainder will be registers). So. Use everything from oper1
700     // to define oper0[0], and vice versa.
701     
702     Assignment::Ptr a = Assignment::makeAssignment(I, addr, func, block, oper0[0]);
703     a->addInputs(oper1);
704
705     Assignment::Ptr b = Assignment::makeAssignment(I, addr, func, block, oper1[0]);
706     b->addInputs(oper0);
707
708     assignments.push_back(a);
709     assignments.push_back(b);
710     break;
711   }
712
713
714   case power_op_stwu: {
715     std::vector<Operand> operands;
716     I.getOperands(operands);
717
718     // stwu <a>, <b>, <c>
719     // <a> = R1
720     // <b> = -16(R1)
721     // <c> = R1
722
723     // From this, R1 <= R1 - 16; -16(R1) <= R1
724     // So a <= b (without a deref)
725     // deref(b) <= c
726
727     std::set<Expression::Ptr> writes;
728     I.getMemoryWriteOperands(writes);
729     assert(writes.size() == 1);
730
731     Expression::Ptr tmp = *(writes.begin());
732     AbsRegion effAddr = aConverter.convert(tmp,
733                                            addr, 
734                                            func,
735                                            block);
736     std::vector<AbsRegion> regions;
737     aConverter.convertAll(operands[0].getValue(), addr, func, block, regions);
738     AbsRegion RS = regions[0];
739     regions.clear();
740     aConverter.convertAll(operands[2].getValue(), addr, func, block, regions);
741     AbsRegion RA = regions[0];
742
743     Assignment::Ptr mem = Assignment::makeAssignment(I, 
744                                                          addr,
745                                                          func,
746                                                          block,
747                                                          effAddr);
748     mem->addInput(RS);
749     
750     Assignment::Ptr ra = Assignment::makeAssignment(I,
751                                                         addr,
752                                                         func,
753                                                         block,
754                                                         RA);
755     ra->addInput(RS);
756     assignments.push_back(mem);
757     assignments.push_back(ra);
758     break;
759   }      
760         
761   default:
762     // Assume full intra-dependence of non-flag and non-pc registers. 
763     std::vector<AbsRegion> used;
764     std::vector<AbsRegion> defined;
765
766     aConverter.convertAll(I,
767                           addr,
768                           func,
769                           block,
770                           used,
771                           defined);
772     // PC should be regarded as a constant              
773     AbsRegion pc(Absloc::makePC(func->isrc()->getArch()));
774     for (auto uit = used.begin(); uit != used.end(); ++uit)
775         if (*uit == pc) {
776             used.erase(uit);                     
777             break;
778         }
779     for (std::vector<AbsRegion>::const_iterator i = defined.begin();
780          i != defined.end(); ++i) {
781        Assignment::Ptr a = Assignment::makeAssignment(I, addr, func, block, *i);
782        a->addInputs(used);
783        assignments.push_back(a);
784     }
785     break;
786   }
787     
788
789   // Now for flags...
790   // According to Matt, the easiest way to represent dependencies for flags on 
791   // IA-32/AMD-64 is to have them depend on the inputs to the instruction and 
792   // not the outputs of the instruction; therefore, there's no intra-instruction
793   // dependence. 
794
795   // PC-handling section
796   // Most instructions use the PC to set the PC. This includes calls, relative branches,
797   // and the like. So we're basically looking for indirect branches or absolute branches.
798   // (are there absolutes on IA-32?).
799   // Also, conditional branches and the flag registers they use. 
800
801   if (cacheEnabled_) {
802     cache_[func][addr] = assignments;
803   }
804
805 }
806
807 void AssignmentConverter::handlePushEquivalent(const Instruction I,
808                                                Address addr,
809                                                ParseAPI::Function *func,
810                                                ParseAPI::Block *block,
811                                                std::vector<AbsRegion> &operands,
812                                                std::vector<Assignment::Ptr> &assignments) {
813   // The handled-in operands are used to define *SP
814   // And then we update SP
815   
816    AbsRegion stackTop = aConverter.stack(addr, func, block, true);
817   AbsRegion sp(Absloc::makeSP(func->isrc()->getArch()));
818
819   Assignment::Ptr spA = Assignment::makeAssignment(I,
820                                                        addr,
821                                                        func,
822                                                        block,
823                                                        stackTop);
824   spA->addInputs(operands);
825   spA->addInput(sp);
826
827   Assignment::Ptr spB = Assignment::makeAssignment(I, addr, func, block, sp);
828   spB->addInput(sp);
829
830   assignments.push_back(spA);
831   assignments.push_back(spB);
832 }
833
834 void AssignmentConverter::handlePopEquivalent(const Instruction I,
835                                               Address addr,
836                                               ParseAPI::Function *func,
837                                               ParseAPI::Block *block,
838                                               std::vector<AbsRegion> &operands,
839                                               std::vector<Assignment::Ptr> &assignments) {
840   // We use the top of the stack and any operands beyond the first.
841   // (Can you pop into memory?)
842
843    AbsRegion stackTop = aConverter.stack(addr, func, block, false);
844   AbsRegion sp(Absloc::makeSP(func->isrc()->getArch()));
845   
846   Assignment::Ptr spA = Assignment::makeAssignment(I,
847                                                        addr,
848                                                        func,
849                                                        block,
850                                                        operands[0]);
851   spA->addInput(stackTop);
852   spA->addInput(sp);
853
854   for (unsigned i = 1; i < operands.size(); i++) {
855     spA->addInput(operands[i]);
856   }
857
858   // Now stack assignment
859   Assignment::Ptr spB = Assignment::makeAssignment(I, addr, func, block, sp);
860   spB->addInput(sp);
861
862   assignments.push_back(spA);
863   assignments.push_back(spB);
864 }
865
866 bool AssignmentConverter::cache(ParseAPI::Function *func, 
867                                 Address addr, 
868                                 std::vector<Assignment::Ptr> &assignments) {
869   if (!cacheEnabled_) {
870     return false;
871   }
872   FuncCache::iterator iter = cache_.find(func);
873   if (iter == cache_.end()) {
874     return false;
875   }
876   AddrCache::iterator iter2 = iter->second.find(addr);
877   if (iter2 == iter->second.end()) {
878     return false;
879   }
880   assignments = iter2->second;
881   return true;
882 }
883
884
885