GCC 4.8 build fixes: ensure all extern template declarations are in fact extern'ed...
[dyninst.git] / parseAPI / src / IA_IAPI.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 #include "dyntypes.h"
32 #include "dyn_regs.h"
33 #include "IA_IAPI.h"
34 #include "util.h"
35 #include "Register.h"
36 #include "Dereference.h"
37 #include "Immediate.h"
38 #include "BinaryFunction.h"
39 #include "debug_parse.h"
40 #include "IA_platformDetails.h"
41 #include "util.h"
42 #include "common/src/Types.h"
43 #include "dyntypes.h"
44 #include "IndirectAnalyzer.h"
45
46 #include <deque>
47 #include <map>
48
49 #if defined(os_vxworks)
50 #include "common/src/wtxKludges.h"
51 #endif
52
53 using namespace Dyninst;
54 using namespace InstructionAPI;
55 using namespace Dyninst::InsnAdapter;
56 using namespace Dyninst::ParseAPI;
57
58 std::map<Architecture, RegisterAST::Ptr> IA_IAPI::framePtr;
59 std::map<Architecture, RegisterAST::Ptr> IA_IAPI::stackPtr;
60 std::map<Architecture, RegisterAST::Ptr> IA_IAPI::thePC;
61
62 extern template class boost::shared_ptr<Dyninst::InstructionAPI::BinaryFunction::funcT>;
63 extern template class boost::shared_ptr<Dyninst::InstructionAPI::InstructionAST>;
64
65 IA_IAPI::IA_IAPI(const IA_IAPI &rhs) 
66    : InstructionAdapter(rhs),
67      dec(rhs.dec),
68      allInsns(rhs.allInsns),
69      validCFT(rhs.validCFT),
70      cachedCFT(rhs.cachedCFT),
71      validLinkerStubState(rhs.validLinkerStubState),
72      cachedLinkerStubState(rhs.cachedLinkerStubState),
73      hascftstatus(rhs.hascftstatus),
74      tailCalls(rhs.tailCalls) {
75    //curInsnIter = allInsns.find(rhs.curInsnIter->first);
76     curInsnIter = allInsns.end()-1;
77 }
78
79 IA_IAPI &IA_IAPI::operator=(const IA_IAPI &rhs) {
80    dec = rhs.dec;
81    allInsns = rhs.allInsns;
82    //curInsnIter = allInsns.find(rhs.curInsnIter->first);
83    curInsnIter = allInsns.end()-1;
84    validCFT = rhs.validCFT;
85    cachedCFT = rhs.cachedCFT;
86    validLinkerStubState = rhs.validLinkerStubState;
87    cachedLinkerStubState = rhs.cachedLinkerStubState;
88    hascftstatus = rhs.hascftstatus;
89    tailCalls = rhs.tailCalls;
90
91    // InstructionAdapter members
92    current = rhs.current;
93    previous = rhs.previous;
94    parsedJumpTable = rhs.parsedJumpTable;
95    successfullyParsedJumpTable = rhs.successfullyParsedJumpTable;
96    isDynamicCall_ = rhs.isDynamicCall_;
97    checkedDynamicCall_ = rhs.checkedDynamicCall_;
98    isInvalidCallTarget_ = rhs.isInvalidCallTarget_;
99    checkedInvalidCallTarget_ = rhs.checkedInvalidCallTarget_;
100    _obj = rhs._obj;
101    _cr = rhs._cr;
102    _isrc = rhs._isrc;
103    _curBlk = rhs._curBlk;
104
105    return *this;
106 }
107
108 void IA_IAPI::initASTs()
109 {
110     if(framePtr.empty())
111     {
112         framePtr[Arch_x86] = RegisterAST::Ptr(new RegisterAST(MachRegister::getFramePointer(Arch_x86)));
113         framePtr[Arch_x86_64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getFramePointer(Arch_x86_64)));
114         framePtr[Arch_ppc32] = RegisterAST::Ptr(new RegisterAST(MachRegister::getFramePointer(Arch_ppc32)));
115         framePtr[Arch_ppc64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getFramePointer(Arch_ppc64)));
116         framePtr[Arch_aarch64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getFramePointer(Arch_aarch64)));
117     }
118     if(stackPtr.empty())
119     {
120         stackPtr[Arch_x86] = RegisterAST::Ptr(new RegisterAST(MachRegister::getStackPointer(Arch_x86)));
121         stackPtr[Arch_x86_64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getStackPointer(Arch_x86_64)));
122         stackPtr[Arch_ppc32] = RegisterAST::Ptr(new RegisterAST(MachRegister::getStackPointer(Arch_ppc32)));
123         stackPtr[Arch_ppc64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getStackPointer(Arch_ppc64)));
124         stackPtr[Arch_aarch64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getStackPointer(Arch_aarch64)));
125     }
126     if(thePC.empty())
127     {
128         thePC[Arch_x86] = RegisterAST::Ptr(new RegisterAST(MachRegister::getPC(Arch_x86)));
129         thePC[Arch_x86_64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getPC(Arch_x86_64)));
130         thePC[Arch_ppc32] = RegisterAST::Ptr(new RegisterAST(MachRegister::getPC(Arch_ppc32)));
131         thePC[Arch_ppc64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getPC(Arch_ppc64)));
132         thePC[Arch_aarch64] = RegisterAST::Ptr(new RegisterAST(MachRegister::getPC(Arch_aarch64)));
133     }
134 }
135
136 IA_IAPI::IA_IAPI(InstructionDecoder dec_, 
137         Address where_,
138         CodeObject * o,
139         CodeRegion * r,
140         InstructionSource *isrc,
141         Block * curBlk_) :
142     InstructionAdapter(where_, o, r, isrc, curBlk_), 
143     dec(dec_),
144     validCFT(false), 
145     cachedCFT(std::make_pair(false, 0)),
146     validLinkerStubState(false),
147     cachedLinkerStubState(false)
148 {
149     hascftstatus.first = false;
150     tailCalls.clear();
151
152     //boost::tuples::tie(curInsnIter, boost::tuples::ignore) = allInsns.insert(std::make_pair(current, dec.decode()));
153     curInsnIter =
154         allInsns.insert(
155             allInsns.end(),
156             std::make_pair(current, dec.decode()));
157
158     initASTs();
159 }
160
161 void
162 IA_IAPI::reset(
163     InstructionDecoder dec_,
164     Address start,
165     CodeObject *o,
166     CodeRegion *r,
167     InstructionSource *isrc,
168     Block * curBlk_)
169 {
170     // reset the base
171     InstructionAdapter::reset(start,o,r,isrc,curBlk_);
172
173     dec = dec_;
174     validCFT = false;
175     cachedCFT = make_pair(false, 0);
176     validLinkerStubState = false; 
177     hascftstatus.first = false;
178     tailCalls.clear();
179
180     allInsns.clear();
181
182     curInsnIter =
183         allInsns.insert(
184             allInsns.end(),
185             std::make_pair(current, dec.decode()));
186
187     initASTs();
188 }
189
190
191 void IA_IAPI::advance()
192 {
193     if(!curInsn()) {
194         parsing_printf("..... WARNING: failed to advance InstructionAdapter at 0x%lx, allInsns.size() = %d\n", current,
195                        allInsns.size());
196         return;
197     }
198     InstructionAdapter::advance();
199     current += curInsn()->size();
200
201     curInsnIter =
202         allInsns.insert(
203             allInsns.end(),
204             std::make_pair(current, dec.decode()));
205
206     if(!curInsn())
207     {
208         parsing_printf("......WARNING: after advance at 0x%lx, curInsn() NULL\n", current);
209     }
210     validCFT = false;
211     validLinkerStubState = false;
212     hascftstatus.first = false;
213     tailCalls.clear();
214 }
215
216 bool IA_IAPI::retreat()
217 {
218     if(!curInsn()) {
219         parsing_printf("..... WARNING: failed to retreat InstructionAdapter at 0x%lx, allInsns.size() = %d\n", current,
220                        allInsns.size());
221         return false;
222     }
223     InstructionAdapter::retreat();
224     allInsns_t::iterator remove = curInsnIter;
225     if(curInsnIter != allInsns.begin()) {
226         --curInsnIter;
227         allInsns.erase(remove);
228         current = curInsnIter->first;
229         if(curInsnIter != allInsns.begin()) {
230             allInsns_t::iterator pit = curInsnIter;
231             --pit;
232             previous = curInsnIter->first;
233         } else {
234             previous = -1;
235         }
236     } else {
237         parsing_printf("..... WARNING: cowardly refusal to retreat past first instruction at 0x%lx\n", current);
238         return false;
239     }
240
241     /* blind duplication -- nate */
242     validCFT = false;
243     validLinkerStubState = false;
244     hascftstatus.first = false;
245     tailCalls.clear();
246     return true;
247
248     
249     
250
251 size_t IA_IAPI::getSize() const
252 {
253     Instruction::Ptr ci = curInsn();
254     assert(ci);
255     return ci->size();
256 }
257
258 bool IA_IAPI::hasCFT() const
259 {
260     parsing_cerr << "hasCFT called" << endl;
261   if(hascftstatus.first) {
262     parsing_cerr << "\t Returning cached entry: " << hascftstatus.second << endl;
263     return hascftstatus.second;
264   }
265   InsnCategory c = curInsn()->getCategory();
266   hascftstatus.second = false;
267   if(c == c_BranchInsn ||
268      c == c_ReturnInsn) {
269      if ( likely ( ! (_obj->defensiveMode() && isNopJump()) ) ) {
270         parsing_cerr << "\t branch or return, ret true" << endl;
271         hascftstatus.second = true;
272      }
273   }
274   else if(c == c_CallInsn) {
275      if(isRealCall()) {
276         hascftstatus.second = true;
277      }
278      else if(isDynamicCall()) {
279         hascftstatus.second = true;
280      }
281      else if(simulateJump()) {
282         hascftstatus.second = true;
283      }
284   }
285   else if(c == c_SysEnterInsn) 
286   {
287     hascftstatus.second = true;
288   }
289   else if (c == c_SyscallInsn)
290   {
291     hascftstatus.second = true;
292   }
293   
294   hascftstatus.first = true;
295   return hascftstatus.second;
296 }
297
298 bool IA_IAPI::isAbort() const
299 {
300     entryID e = curInsn()->getOperation().getID();
301     return e == e_int3 ||
302        e == e_hlt;
303 }
304
305 bool IA_IAPI::isInvalidInsn() const
306 {
307     entryID e = curInsn()->getOperation().getID();
308     if(e == e_No_Entry)
309     {
310        parsing_printf("...WARNING: un-decoded instruction at 0x%x\n", current);
311        return true;
312     }
313     return false;
314 }
315
316 /* This function determines if a given instruction is weird enough that we've
317  * probably veered into non-code bytes and are parsing garbage.  
318  * note: yes, some of the code in here is does low-level things like 
319  *       grab instruction bytes directly instead of relying on the parseAPI,
320  *       but since this code executes for every parsed instruction, it needs
321  *       to be efficient.  
322  */
323 bool IA_IAPI::isGarbageInsn() const
324 {
325     bool ret = false;
326     // GARBAGE PARSING HEURISTIC
327     if (unlikely(_obj->defensiveMode())) {
328         entryID e = curInsn()->getOperation().getID();
329         switch (e) {
330         case e_arpl:
331             cerr << "REACHED AN ARPL AT "<< std::hex << current 
332                  << std::dec <<" COUNTING AS INVALID" << endl;
333             ret = true;
334             break;
335         case e_fisub:
336             cerr << "REACHED A FISUB AT "<< std::hex << current 
337                  << std::dec <<" COUNTING AS INVALID" << endl;
338             ret = true;
339             break;
340         case e_into:
341             cerr << "REACHED AN INTO AT "<< std::hex << current 
342                  << std::dec <<" COUNTING AS INVALID" << endl;
343             ret = true;
344             break;
345         case e_mov: {
346             set<RegisterAST::Ptr> regs;
347             curInsn()->getWriteSet(regs);
348             for (set<RegisterAST::Ptr>::iterator rit = regs.begin();
349                  rit != regs.end(); rit++) 
350             {
351                 if (Dyninst::isSegmentRegister((*rit)->getID().regClass())) {
352                     cerr << "REACHED A MOV SEGMENT INSN AT "<< std::hex 
353                         << current << std::dec <<" COUNTING AS INVALID" << endl;
354                     ret = true;
355                     break;
356                 }
357             }
358             break;
359         }
360         case e_add:
361             if (2 == curInsn()->size() && 
362                 0 == curInsn()->rawByte(0) && 
363                 0 == curInsn()->rawByte(1)) 
364             {
365                 cerr << "REACHED A 0x0000 INSTRUCTION "<< std::hex << current 
366                      << std::dec <<" COUNTING AS INVALID" << endl;
367                 ret = true;
368             }
369             break;
370         case e_push: // pushes of segment registers do not occur frequently in real code (and crash Rose)
371 #if 0 // instructionAPI implementation
372             set<RegisterAST::Ptr> regs;
373             curInsn()->getWriteSet(regs);
374             for (set<RegisterAST::Ptr>::iterator rit = regs.begin();
375                  rit != regs.end(); rit++) 
376             {
377                 if (Dyninst::isSegmentRegister((*rit)->getID().regClass())) {
378                     cerr << "REACHED A PUSH OF A SEGMENT REGISTER AT "<< std::hex 
379                         << current << std::dec <<" COUNTING AS INVALID" << endl;
380                     ret = true;
381                     break;
382                 }
383             }
384 #else // faster raw-byte implementation 
385             switch (curInsn()->rawByte(0)) {
386                 case 0x06:
387                 case 0x0e:
388                 case 0x16:
389                 case 0x1e:
390                     ret = true;
391                     cerr << "REACHED A PUSH OF A SEGMENT REGISTER "<< std::hex << current 
392                          << std::dec <<" COUNTING AS INVALID" << endl;
393                     break;
394                 case 0x0f:
395                     if (2 == curInsn()->size() && 
396                         ((0xa0 == curInsn()->rawByte(1)) || (0xa8 == curInsn()->rawByte(1))))
397                     {
398                         ret = true;
399                         cerr << "REACHED A 2-BYTE PUSH OF A SEGMENT REGISTER "<< std::hex << current 
400                              << std::dec <<" COUNTING AS INVALID" << endl;
401                     }
402                     break;
403                 default:
404                     break;
405             }
406 #endif
407         default:
408             break;
409         }
410     }
411     return ret;
412 }       
413 bool IA_IAPI::isFrameSetupInsn() const
414 {
415     return isFrameSetupInsn(curInsn());
416 }
417
418 bool IA_IAPI::isDynamicCall() const
419 {
420     Instruction::Ptr ci = curInsn();
421     if(ci && (ci->getCategory() == c_CallInsn))
422     {
423        Address addr;
424        bool success;
425        boost::tie(success, addr) = getCFT();
426        if (!success) {
427           parsing_printf("... Call 0x%lx is indirect\n", current);
428           return true;
429        }
430     }
431     return false;
432 }
433
434 bool IA_IAPI::isAbsoluteCall() const
435 {
436     Instruction::Ptr ci = curInsn();
437     if(ci->getCategory() == c_CallInsn)
438     {
439         Expression::Ptr cft = ci->getControlFlowTarget();
440         if(cft && boost::dynamic_pointer_cast<Immediate>(cft))
441         {
442             return true;
443         }
444         if (isDynamicCall()) {
445             return true; // indirect call targets are absolute 
446                          // (though unknown for now)
447         }
448     }
449     return false;
450 }
451
452 bool IA_IAPI::isBranch() const
453 {
454     return curInsn()->getCategory() == c_BranchInsn;
455 }
456 bool IA_IAPI::isCall() const
457 {
458     return curInsn()->getCategory() == c_CallInsn;
459 }
460
461 bool IA_IAPI::isInterruptOrSyscall() const
462 {
463     return (isInterrupt() && isSyscall());
464 }
465
466 bool IA_IAPI::isSyscall() const
467 {
468     static RegisterAST::Ptr gs(new RegisterAST(x86::gs));
469     
470     Instruction::Ptr ci = curInsn();
471
472     return (((ci->getOperation().getID() == e_call) &&
473                 (curInsn()->getOperation().isRead(gs)) &&
474                 (ci->getOperand(0).format(ci->getArch()) == "16")) ||
475             (ci->getOperation().getID() == e_syscall) || 
476             (ci->getOperation().getID() == e_int) || 
477             (ci->getOperation().getID() == power_op_sc));
478 }
479
480
481 bool IA_IAPI::isInterrupt() const
482 {
483     Instruction::Ptr ci = curInsn();
484     return ((ci->getOperation().getID() == e_int) ||
485             (ci->getOperation().getID() == e_int3));
486 }
487
488 bool IA_IAPI::isSysEnter() const
489 {
490   Instruction::Ptr ci = curInsn();
491   return (ci->getOperation().getID() == e_sysenter);
492 }
493
494 bool IA_IAPI::isIndirectJump() const {
495     Instruction::Ptr ci = curInsn();
496     if(ci->getCategory() != c_BranchInsn) return false;
497     if(ci->allowsFallThrough()) return false;
498     bool valid;
499     Address target;
500     boost::tie(valid, target) = getCFT(); 
501     if (valid) return false;
502     parsing_printf("... indirect jump at 0x%x, delay parsing it\n", current);
503     return true;
504 }
505
506 void IA_IAPI::parseSyscall(std::vector<std::pair<Address, EdgeTypeEnum> >& outEdges) const
507 {
508     parsing_printf("[%s:%d] Treating syscall as call to sink w/ possible FT edge to next insn at 0x%lx\n",
509                    FILE__, __LINE__, getAddr());
510     outEdges.push_back(std::make_pair((Address)-1,CALL));
511     outEdges.push_back(std::make_pair(getNextAddr(), CALL_FT));
512 }
513
514 void IA_IAPI::parseSysEnter(std::vector<std::pair<Address, EdgeTypeEnum> >& outEdges) const
515 {
516   IA_IAPI scratch(*this);
517   
518   do {
519     scratch.advance();
520   } while(scratch.isNop());
521   if(scratch.curInsn()->getCategory() == c_BranchInsn)
522   {
523     parsing_printf("[%s:%d] Detected Linux-ish sysenter idiom at 0x%lx\n",
524                    FILE__, __LINE__, getAddr());
525     outEdges.push_back(std::make_pair(scratch.getAddr(), COND_NOT_TAKEN));
526     scratch.advance();
527     outEdges.push_back(std::make_pair(scratch.getAddr(), CALL_FT));
528   }
529   else
530   {
531     parsing_printf("[%s:%d] Treating sysenter as call to kernel w/normal return to next insn at 0x%lx\n",
532                   FILE__, __LINE__, getAddr());
533     outEdges.push_back(std::make_pair(getNextAddr(), CALL_FT));
534   }
535 }
536
537
538
539 void IA_IAPI::getNewEdges(std::vector<std::pair< Address, EdgeTypeEnum> >& outEdges,
540                           Function* context,
541                           Block* currBlk,
542                           unsigned int num_insns,
543                           dyn_hash_map<Address, std::string> *plt_entries,
544                           const set<Address>& knownTargets) const
545 {
546     Instruction::Ptr ci = curInsn();
547
548     // Only call this on control flow instructions!
549     if(ci->getCategory() == c_CallInsn)
550     {
551        bool success; 
552        Address target;
553        boost::tie(success, target) = getCFT();
554         bool callEdge = true;
555         bool ftEdge = true;
556         if( success && !isDynamicCall() )
557         {
558             if ( ! isRealCall() )
559                 callEdge = false;
560
561             if ( simulateJump() ) 
562             {
563                 outEdges.push_back(std::make_pair(target, DIRECT));
564                 callEdge = false;
565                 ftEdge = false;
566             }
567         }
568
569         if ( unlikely(_obj->defensiveMode()) )
570         {
571             if (!success || isDynamicCall()) 
572             {
573                 std::string empty;
574                if ( ! isIATcall(empty) )
575                     ftEdge = false;
576             }
577             else if ( ! _isrc->isValidAddress(target) )
578             {
579                 ftEdge = false;
580             }
581         }
582  
583         if (callEdge)
584             outEdges.push_back(std::make_pair(target, CALL));
585         if (ftEdge)
586             outEdges.push_back(std::make_pair(getAddr() + getSize(), CALL_FT));
587         return;
588     }
589     else if(ci->getCategory() == c_BranchInsn)
590     {
591         if(ci->allowsFallThrough())
592         {
593             outEdges.push_back(std::make_pair(getCFT().second,
594                                               COND_TAKEN));
595             outEdges.push_back(std::make_pair(getNextAddr(), COND_NOT_TAKEN));
596             return;
597         }
598
599         // Catch blocks can appear after either direct jumps or indirect jumps
600         // There may be nops between this jump and the catch block and
601         // there is possibility that the exception table entry points a nop.
602         // Therefore, we need to check for every nop and first non-nop instruction after the jump for catch blocks
603         IA_IAPI tmp_ah(*this);
604         tmp_ah.advance();
605         Address catchStart;
606         bool found = false;
607         while (tmp_ah.curInsn() && tmp_ah.isNop()) {
608             if(_cr->findCatchBlock(tmp_ah.getAddr(),catchStart))  {
609                 found = true;
610                 break;
611             }
612             tmp_ah.advance();
613         }
614         if(found || (tmp_ah.curInsn() &&_cr->findCatchBlock(tmp_ah.getAddr(),catchStart)))
615         {
616             outEdges.push_back(std::make_pair(catchStart, CATCH));
617         }
618
619         bool valid;
620         Address target;
621         boost::tie(valid, target) = getCFT(); 
622         // Direct jump
623         if (valid) 
624         {
625
626             if(!isTailCall(context, DIRECT, num_insns, knownTargets))
627             {
628                 if(plt_entries->find(target) == plt_entries->end())
629                 {
630                     outEdges.push_back(std::make_pair(target,DIRECT));
631                 }
632                 else
633                 {
634                     parsing_printf("%s[%d]: PLT tail call to %x (%s)\n", 
635                         FILE__, __LINE__, target,
636                         (*plt_entries)[target].c_str());
637                     outEdges.push_back(std::make_pair(target, DIRECT));
638                     tailCalls[DIRECT] = true;
639                 }
640             }
641             else
642             {
643                 parsing_printf("%s[%d]: tail call to %x\n", 
644                     FILE__, __LINE__, target);
645                 outEdges.push_back(std::make_pair(target, DIRECT));
646             }
647             return;
648         }
649         else
650         {
651             parsing_printf("... indirect jump at 0x%x\n", current);
652             if( num_insns == 2 ) {
653               // Handle a pernicious indirect tail call idiom here
654               // What we've seen is mov (%rdi), %rax; jmp *%rax
655               // Anything that tries to go enum->jump table *should* need more than two
656               // instructions and has not been seen in the wild....
657               if(currBlk == context->entry()) 
658               {
659                 parsing_printf("\tIndirect branch as 2nd insn of entry block, treating as tail call\n");
660                 parsing_printf("%s[%d]: indirect tail call %s at 0x%lx\n", FILE__, __LINE__,
661                                ci->format().c_str(), current);
662                 outEdges.push_back(std::make_pair((Address)-1,INDIRECT));
663                 tailCalls[INDIRECT]=true;
664                 // Fix the cache, because we're dumb.
665                 tailCalls[DIRECT]=true;
666                 return;
667               }
668               else
669               {
670                 parsing_printf("... uninstrumentable due to 0 size\n");
671                 return;
672               }
673             }
674             if(isTailCall(context, INDIRECT, num_insns, knownTargets)) {
675                 parsing_printf("%s[%d]: indirect tail call %s at 0x%lx\n", FILE__, __LINE__,
676                                ci->format().c_str(), current);
677                 outEdges.push_back(std::make_pair((Address)-1,INDIRECT));
678                 tailCalls[INDIRECT] = true;
679                 return;
680             }
681             parsing_printf("%s[%d]: jump table candidate %s at 0x%lx\n", FILE__, __LINE__,
682                            ci->format().c_str(), current);
683             parsedJumpTable = true;
684             successfullyParsedJumpTable = parseJumpTable(context, currBlk, outEdges);
685             parsing_printf("Parsed jump table\n");
686             if(!successfullyParsedJumpTable || outEdges.empty()) {
687                 outEdges.push_back(std::make_pair((Address)-1,INDIRECT));
688                 parsing_printf("%s[%d]: unparsed jump table %s at 0x%lx in function %s UNINSTRUMENTABLE\n", FILE__, __LINE__,
689                            ci->format().c_str(), current, context->name().c_str());
690             }
691             return;
692         }
693     }
694     else if(ci->getCategory() == c_ReturnInsn)
695     {
696         parsing_printf("%s[%d]: return candidate %s at 0x%lx\n", FILE__, __LINE__,
697                            ci->format().c_str(), current);
698         if(ci->allowsFallThrough())
699         {
700             outEdges.push_back(std::make_pair(getNextAddr(), FALLTHROUGH));
701         }
702         else if (!isReturn(context, currBlk)) {
703             // If BLR is not a return, then it is a jump table
704             parsedJumpTable = true;
705             parsing_printf("%s[%d]: BLR jump table candidate %s at 0x%lx\n", FILE__, __LINE__,
706                            ci->format().c_str(), current);
707             successfullyParsedJumpTable = parseJumpTable(context, currBlk, outEdges);
708             parsing_printf("Parsed BLR jump table\n");
709             if(!successfullyParsedJumpTable || outEdges.empty()) {
710                 parsing_printf("%s[%d]: BLR unparsed jump table %s at 0x%lx in function %s UNINSTRUMENTABLE\n", 
711                                FILE__, __LINE__, ci->format().c_str(), current, context->name().c_str());
712                 outEdges.push_back(std::make_pair((Address)-1,INDIRECT));
713             }
714         }
715         
716         // Check potential catch blocks after return instructions
717         // There may be nops between this return instruction and the catch block and
718         // there is possibility that the exception table entry points a nop.
719         // Therefore, we need to check for every nop and first non-nop instruction after the return for catch blocks
720
721         IA_IAPI tmp_ah(*this);
722         tmp_ah.advance();
723         Address catchStart;
724         bool found = false;
725         while (tmp_ah.curInsn() && tmp_ah.isNop()) {
726             if(_cr->findCatchBlock(tmp_ah.getAddr(),catchStart))  {
727                 found = true;
728                 break;
729             }
730             tmp_ah.advance();
731         }
732         if(found || (tmp_ah.curInsn() &&_cr->findCatchBlock(tmp_ah.getAddr(),catchStart)))
733         {
734             outEdges.push_back(std::make_pair(catchStart, CATCH));
735         }
736
737         parsing_printf("Returning from parse out edges\n");
738         return;
739     }
740     else if(isSysEnter())
741     {
742       parseSysEnter(outEdges);
743       return;
744     } else if (isSyscall()) {
745         parseSyscall(outEdges);
746         return;
747     }
748     
749     fprintf(stderr, "Unhandled instruction %s\n", ci->format().c_str());
750     assert(0);
751 }
752
753 bool IA_IAPI::isIPRelativeBranch() const
754 {
755             // These don't exist on IA32...
756 #if !defined(arch_x86_64)
757     return false;
758 #endif
759     Instruction::Ptr ci = curInsn();
760
761     bool valid;
762     Address target;
763     boost::tie(valid, target) = getCFT();
764     
765     if(ci->getCategory() == c_BranchInsn &&
766        !valid) {
767        Expression::Ptr cft = ci->getControlFlowTarget();
768        if(cft->isUsed(thePC[_isrc->getArch()]))
769        {
770           parsing_printf("\tIP-relative indirect jump to %s at 0x%lx\n",
771                          cft->format().c_str(), current);
772           return true;
773        }
774     }
775     return false;
776     
777 }
778
779 Instruction::Ptr IA_IAPI::curInsn() const
780 {
781     return curInsnIter->second;
782 }
783
784 bool IA_IAPI::isLeave() const
785 {
786     Instruction::Ptr ci = curInsn();
787     return ci && (ci->getOperation().getID() == e_leave);
788 }
789
790 bool IA_IAPI::isDelaySlot() const
791 {
792     return false;
793 }
794
795 Instruction::Ptr IA_IAPI::getInstruction() const
796 {
797     return curInsn();
798 }
799
800 bool IA_IAPI::isRealCall() const
801 {
802   // Obviated by simulateJump
803    bool success;
804    Address addr;
805    boost::tie(success, addr) = getCFT();
806    if (success &&
807        (addr == getNextAddr())) {
808       parsing_printf("... getting PC\n");
809       return false;
810    }
811    if(isThunk()) {
812       return false;
813    }
814    return true;
815 }
816
817 std::map<Address, bool> IA_IAPI::thunkAtTarget;
818
819
820 bool IA_IAPI::isConditional() const
821 {
822     return curInsn()->allowsFallThrough();
823 }
824
825 bool IA_IAPI::simulateJump() const
826 {
827     // obfuscated programs simulate jumps by calling into a block that 
828     // discards the return address from the stack, we check for these
829     // fake calls in malware mode
830     if (_obj->defensiveMode() && !isDynamicCall()) {
831         return isFakeCall();
832     }
833     // TODO: we don't simulate jumps on x86 architectures; add logic as we need it.                
834     return false;
835 }
836
837 std::pair<bool, Address> IA_IAPI::getFallthrough() const 
838 {
839    return make_pair(true, curInsnIter->first + curInsnIter->second->size());
840 }
841
842 std::pair<bool, Address> IA_IAPI::getCFT() const
843 {
844    if(validCFT) return cachedCFT;
845     Expression::Ptr callTarget = curInsn()->getControlFlowTarget();
846         if (!callTarget) return make_pair(false, 0);
847        // FIXME: templated bind(),dammit!
848     callTarget->bind(thePC[_isrc->getArch()].get(), Result(s64, current));
849     parsing_printf("%s[%d]: binding PC %s in %s to 0x%x...", FILE__, __LINE__,
850                    thePC[_isrc->getArch()]->format().c_str(), curInsn()->format().c_str(), current);
851
852     Result actualTarget = callTarget->eval();
853 #if defined(os_vxworks)
854
855     int reloc_target = current;
856 #if defined(arch_x86)
857     ++reloc_target;
858 #endif
859
860     if (actualTarget.convert<Address>() == reloc_target) {
861         // We have a zero offset branch.  Consider relocation information.
862         SymtabCodeRegion *scr = dynamic_cast<SymtabCodeRegion *>(_cr);
863         SymtabCodeSource *scs = dynamic_cast<SymtabCodeSource *>(_obj->cs());
864
865         if (!scr && scs) {
866             set<CodeRegion *> regions;
867             assert( scs->findRegions(reloc_target, regions) == 1 );
868             scr = dynamic_cast<SymtabCodeRegion *>(*regions.begin());
869         }
870
871         SymtabAPI::Symbol *sym = NULL;
872         if (scr) {
873             std::vector<SymtabAPI::relocationEntry> relocs =
874                 scr->symRegion()->getRelocations();
875
876             for (unsigned i = 0; i < relocs.size(); ++i) {
877                 if (relocs[i].rel_addr() == reloc_target) {
878                     sym = relocs[i].getDynSym();
879                     if (sym && sym->getOffset()) {
880                         parsing_printf(" <reloc hit> ");
881                         actualTarget = Result(s64, sym->getOffset());
882                     }
883                     break;
884                 }
885             }
886         }
887
888         if (sym && sym->getOffset() == 0) {
889             // VxWorks external call.
890             // Need some external means to find the target.
891             Address found;
892             const std::string &sym_name = sym->getMangledName();
893             if (wtxFindFunction(sym_name.c_str(), 0x0, found)) {
894                 parsing_printf(" <wtx search hit> ");
895                 actualTarget = Result(s64, found);
896
897                 // We've effectively found a plt call.  Update linkage table.
898                 _obj->cs()->linkage()[found] = sym_name;
899
900             } else {
901                 parsing_printf(" <wtx fail %s> ", sym_name.c_str());
902                 actualTarget.defined = false;
903             }
904         }
905     }
906 #endif
907
908     if(actualTarget.defined)
909     {
910        cachedCFT = std::make_pair(true, actualTarget.convert<Address>());
911        parsing_printf("SUCCESS (CFT=0x%x)\n", cachedCFT.second);
912     }
913     else
914     {
915        cachedCFT = std::make_pair(false, 0); 
916         parsing_printf("FAIL (CFT=0x%x), callTarget exp: %s\n",
917                        cachedCFT.second,callTarget->format().c_str());
918     }
919     validCFT = true;
920
921     if(isLinkerStub()) {
922         parsing_printf("Linker stub detected: Correcting CFT.  (CFT=0x%x)\n",
923                        cachedCFT.second);
924     }
925
926     return cachedCFT;
927 }
928
929 bool IA_IAPI::isRelocatable(InstrumentableLevel lvl) const
930 {
931     Instruction::Ptr ci = curInsn();
932     if(ci && (ci->getCategory() == c_CallInsn))
933     {
934         if(!isDynamicCall())
935         {
936            bool valid; Address addr;
937            boost::tie(valid, addr) = getCFT();
938            assert(valid);
939            if(!_isrc->isValidAddress(addr))
940            {
941               parsing_printf("... Call to 0x%lx is invalid (outside code or data)\n",
942                              addr);
943                 return false;
944             }
945         }
946     }
947     if(lvl == HAS_BR_INDIR)
948     {
949         return false;
950     }
951     return true;
952 }
953
954 bool IA_IAPI::parseJumpTable(Dyninst::ParseAPI::Function * currFunc,
955                              Dyninst::ParseAPI::Block* currBlk,
956                              std::vector<std::pair< Address, Dyninst::ParseAPI::EdgeTypeEnum > >& outEdges) const
957 {
958 /*
959     IA_platformDetails* jumpTableParser = makePlatformDetails(_isrc->getArch(), this);
960     bool ret = jumpTableParser->parseJumpTable(currBlk, outEdges);
961     delete jumpTableParser;
962 */
963
964
965     IndirectControlFlowAnalyzer icfa(currFunc, currBlk);
966     bool ret = icfa.NewJumpTableAnalysis(outEdges);
967
968     parsing_printf("Jump table parser returned %d, %d edges\n", ret, outEdges.size());
969     for (auto oit = outEdges.begin(); oit != outEdges.end(); ++oit) parsing_printf("edge target at %lx\n", oit->first);
970     // Update statistics 
971     currBlk->obj()->cs()->incrementCounter(PARSE_JUMPTABLE_COUNT);
972     if (!ret) currBlk->obj()->cs()->incrementCounter(PARSE_JUMPTABLE_FAIL);
973
974     return ret;
975 }
976
977
978
979 InstrumentableLevel IA_IAPI::getInstLevel(Function * context, unsigned int num_insns) const
980 {
981     InstrumentableLevel ret = InstructionAdapter::getInstLevel(context, num_insns);
982 /*    if(ret == HAS_BR_INDIR && isIPRelativeBranch())
983     {
984         return NORMAL;
985 }*/
986     return ret;
987 }