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