Update parseAPI functions to be boost::graph compatible.
[dyninst.git] / parseAPI / src / IA_powerDetails.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 "IA_powerDetails.h"
32 #include "Visitor.h"
33 #include "Register.h"
34 #include "Dereference.h"
35 #include "Immediate.h"
36 #include "BinaryFunction.h"
37 #include "debug_parse.h"
38 #include <deque>
39 #include <boost/bind.hpp>
40
41 using namespace Dyninst;
42 using namespace InstructionAPI;
43 using namespace Dyninst::InsnAdapter;
44 using namespace Dyninst::ParseAPI;
45
46
47 namespace Dyninst
48 {
49   namespace InsnAdapter
50   {
51     namespace detail
52     {
53       class TOCandOffsetExtractor : public Dyninst::InstructionAPI::Visitor
54       {
55       public:
56         TOCandOffsetExtractor(Address TOCvalue) : toc_contents(TOCvalue) {}
57         virtual ~TOCandOffsetExtractor() {}
58         virtual void visit(BinaryFunction* b) {
59           Address arg1 = m_stack.front();
60           m_stack.pop_front();
61           Address arg2 = m_stack.front();
62           m_stack.pop_front();
63           if(b->isAdd()) {
64             result = arg1 + arg2;
65           } else if(b->isMultiply()) {
66             result = arg1 * arg2;
67           } else {
68             assert(!"unexpected binary function!");
69             result = 0;
70           }
71           parsing_printf("\tTOC visitor visiting binary function, result is 0x%lx\n",
72                          result);
73           m_stack.push_front(result);
74         }
75         virtual void visit(Immediate* i) {
76           Address tmp = i->eval().convert<Address>();
77           result = tmp;
78           parsing_printf("\tTOC visitor visiting immediate, result is 0x%lx\n",
79                          result);
80           m_stack.push_front(tmp);
81         }
82         virtual void visit(RegisterAST* r) {
83           if(r->getID() == toc_reg->getID()) {
84             m_stack.push_front(toc_contents);
85           } else {
86             m_stack.push_front(0);
87           }
88           result = m_stack.front();
89           parsing_printf("\tTOC visitor visiting register, result is 0x%lx\n",
90                          result);
91         }
92         virtual void visit(Dereference*) {}
93         void clear() {
94           m_stack.clear();
95           result = 0;
96         }
97         std::deque<Address> m_stack;
98         Address result;
99         Address toc_contents;
100         RegisterAST::Ptr toc_reg;
101       };
102     }
103   }
104 };
105
106
107 bool IA_powerDetails::findTableAddrNoTOC(const IA_IAPI* blockToCheck)
108 {
109   std::set<RegisterAST::Ptr> regs;
110   std::set<RegisterAST::Ptr> writeregs, readregs;
111   RegisterAST::Ptr writereg, readreg;
112   int dfgreg;
113   std::set<RegisterAST::Ptr>::iterator itw, itr;
114   std::set<int>::iterator itd;
115   toc_visitor->clear();
116   bool foundAddis = false;
117   bool foundAddi = false;
118   bool foundDep = false;
119   while(patternIter != blockToCheck->allInsns.begin())
120     {
121       patternIter--;
122       // Do backward dataflow analysis to match the registers that compute the jump table address 
123       parsing_printf("\tchecking insn %s at 0x%lx\n", patternIter->second->format().c_str(),
124                      patternIter->first);
125       // Ignore rlwinm instruction since its used for the index and not the table start.
126       // Also, remove it from the backwards DFG
127       if(patternIter->second->getOperation().getID() == power_op_rlwinm){
128         patternIter->second->getWriteSet(writeregs);
129         for(itw=writeregs.begin(); itw!= writeregs.end(); itw++){
130           writereg=*(itw);
131           for(itd=dfgregs.begin(); itd!= dfgregs.end(); itd++){
132             dfgreg = *itd;
133             if (writereg->getID() == dfgreg) {
134               parsing_printf("found Match - erasing rlwinm  \n");
135               dfgregs.erase(*itd);
136             }
137           }
138         }
139         continue;
140       }
141
142       writeregs.clear();
143       patternIter->second->getWriteSet(writeregs);
144       foundDep =false;
145
146       for(itw=writeregs.begin(); itw!= writeregs.end(); itw++){
147         writereg=*(itw); 
148         parsing_printf("Register Written %s \n", writereg->format().c_str());
149         for(itd=dfgregs.begin(); itd!= dfgregs.end(); itd++){
150           dfgreg = *itd;
151           parsing_printf("DFG has %d \n", dfgreg);
152           if (writereg->getID() == dfgreg) {
153             parsing_printf("found Match \n");
154             dfgregs.erase(*itd);
155             readregs.clear();
156             patternIter->second->getReadSet(readregs);
157             for(itr=readregs.begin(); itr!= readregs.end(); itr++){
158               readreg=*(itr); 
159               dfgregs.insert(readreg->getID());
160               parsing_printf("Reading %s \n", readreg->format().c_str());
161             }
162             foundDep = true;
163             break;
164           }
165         }
166       }
167       // We look for addi-addis combination. 
168       // These instruction can occur in any order and in any block before the indirect branch. 
169       // Also, there may be more than one addi instruction.
170       // Hence, we use adjustTableStartAddress to keep track of immediate values from addi instructions.
171       if(foundDep && !foundAddis && 
172          (patternIter->second->getOperation().getID() == power_op_addi || 
173           patternIter->second->getOperation().getID() == power_op_addic))
174         {
175           std::set<RegisterAST::Ptr> tmpregs;
176           patternIter->second->getReadSet(tmpregs);
177           if(tmpregs.size() != 1) {
178             continue;
179           }
180           regs.clear();
181           patternIter->second->getReadSet(regs);
182           if(regs.size() != 1) {
183             continue;
184           }
185           parsing_printf("\tfound 0x%lx: %s, checking for addis previous\n",
186                          patternIter->first,
187                          patternIter->second->format().c_str());
188           foundAddi = true;
189           toc_visitor->clear();
190           patternIter->second->getOperand(2).getValue()->apply(toc_visitor.get());
191           adjustTableStartAddress += toc_visitor->result;
192         }
193       else if(foundDep && !foundAddi && patternIter->second->getOperation().getID() == power_op_addis)
194         {
195           std::set<RegisterAST::Ptr> tmpregs;
196           patternIter->second->getReadSet(tmpregs);
197           if(tmpregs.size() != 1) {
198             continue;
199           }
200           regs.clear();
201           patternIter->second->getReadSet(regs);
202           if(regs.size() != 1) {
203             continue;
204           }
205           parsing_printf("\tfound 0x%lx: %s, checking for addi previous\n",
206                          patternIter->first,
207                          patternIter->second->format().c_str());
208           foundAddis = true;
209           toc_visitor->clear();
210           patternIter->second->getOperand(2).getValue()->apply(toc_visitor.get());
211           tableStartAddress = toc_visitor->result;
212           tableStartAddress *= 10000;
213           tableStartAddress &= 0xFFFF0000;
214            
215         } else if( foundDep && foundAddi &&
216                    patternIter->second &&
217                    (patternIter->second->getOperation().getID() == power_op_addis) &&
218                    patternIter->second->isWritten(*(regs.begin())))
219         {
220           foundAddis = true;
221           parsing_printf("\tfound 0x%lx: %s, setting tableStartAddress\n",
222                          patternIter->first,
223                          patternIter->second->format().c_str());
224           toc_visitor->clear();
225           patternIter->second->getOperand(2).getValue()->apply(toc_visitor.get());
226           tableStartAddress += (toc_visitor->result * 0x10000) & 0xFFFF0000;
227           parsing_printf("\ttableStartAddress = 0x%lx\n",
228                          tableStartAddress);
229           break;
230         } else if( foundDep && foundAddis && 
231                    patternIter->second &&
232                    ((patternIter->second->getOperation().getID() == power_op_addi) ||
233                     (patternIter->second->getOperation().getID() == power_op_addic)) &&
234                    patternIter->second->isWritten(*(regs.begin())))
235         {
236           foundAddi = true;
237           parsing_printf("\tfound 0x%lx: %s, setting tableStartAddress\n",
238                          patternIter->first,
239                          patternIter->second->format().c_str());
240           toc_visitor->clear();
241           patternIter->second->getOperand(2).getValue()->apply(toc_visitor.get());
242           tableStartAddress += toc_visitor->result;
243           parsing_printf("\ttableStartAddress = 0x%lx\n", tableStartAddress);
244           break;
245         }
246     }
247   if (!foundAddi || !foundAddis)
248     tableStartAddress = 0;
249   else
250     tableStartAddress += adjustTableStartAddress;
251
252   parsing_printf(" TABLE START 0x%lx 0x%lx %ld\n", tableStartAddress, adjustTableStartAddress, adjustTableStartAddress);
253
254   // If we've found an addi/addis combination and it's a relative table, look for a mfspr/thunk combination that
255   // feeds that...
256   if(tableStartAddress && tableIsRelative)
257     {
258       parsing_printf("\ttableStartAddress non-zero, tableIsRelative true\n");
259       bool foundThunk = false;
260       bool foundMFSPR = false;
261       Address GOTaddress = 0;
262       while(patternIter != blockToCheck->allInsns.begin())
263         {
264           patternIter--;
265           if(patternIter->second->getOperation().getID() == power_op_mfspr &&
266              patternIter->second->isWritten(*(regs.begin())))
267             {
268               foundMFSPR = true;
269               break;
270             }
271         }
272       while(patternIter != blockToCheck->allInsns.begin())
273         {
274           patternIter--;
275           if(patternIter->second->getCategory() == c_CallInsn) // mid-block call, must be a thunk
276             {
277               patternIter++;
278               parsing_printf("\tfound thunk/mfspr combo, adjusting tableStartAddress by 0x%lx\n", patternIter->first);
279               GOTaddress = tableStartAddress + patternIter->first;
280               foundThunk = true;
281               break;
282             }
283         }
284       if(foundThunk && foundMFSPR)
285         {
286           toc_visitor->toc_reg = *(regs.begin());
287           toc_reg = toc_visitor->toc_reg;
288           toc_visitor->toc_contents = GOTaddress;
289           tableStartAddress = 0;
290           patternIter = currentBlock->curInsnIter;
291           parsing_printf("\t calling parseRelativeTableIdiom with toc_reg %s\n", toc_visitor->toc_reg->format().c_str());
292           return parseRelativeTableIdiom();
293         }
294     }
295   else
296     {
297       parsing_printf("\ttableStartAddress = 0x%lx, tableIsRelative = %s\n", tableStartAddress,
298                      tableIsRelative ? "true" : "false");
299     }
300   return tableStartAddress == 0;
301 }
302
303 bool IA_powerDetails::parseRelativeTableIdiom()
304 {
305   bool foundAddress = false;
306   while(patternIter != currentBlock->allInsns.begin())
307     {
308       patternIter--;
309       parsing_printf("\t checking 0x%lx: %s for lwz/ld\n", patternIter->first, patternIter->second->format().c_str());
310       if((patternIter->second->getOperation().getID() == power_op_lwz ||
311           patternIter->second->getOperation().getID() == power_op_ld) &&
312          patternIter->second->isRead(toc_reg))
313         {
314           toc_visitor->clear();
315           patternIter->second->getOperand(1).getValue()->apply(toc_visitor.get());
316           parsing_printf("%s[%d]: setting jumpStartAddress to 0x%lx, insn %s, TOC 0x%lx\n", FILE__, __LINE__,
317                          toc_visitor->result, patternIter->second->format().c_str(), toc_visitor->toc_contents);
318           jumpStartAddress = toc_visitor->result;
319           foundAddress = true;
320           tableStartAddress = jumpStartAddress;
321           adjustEntry = 0;
322           break;
323         }
324     }
325   if(patternIter == currentBlock->allInsns.begin())
326     {
327       if (foundAddress) {
328         return true;
329       } else {
330
331         // If we've already backed up to the beginning, we're not going to find a legit table
332         // start address; bail now.
333         parsing_printf("%s[%d]: jumpStartAddress insn was first in block w/relative table, ret false\n",
334                        FILE__, __LINE__);
335         return false;
336       } 
337     }
338   // Anyone know what this does?
339   patternIter--;
340   if((patternIter->second->getOperation().getID() == power_op_lwz ||
341       patternIter->second->getOperation().getID() == power_op_ld))
342     {
343       toc_visitor->clear();
344       patternIter->second->getOperand(1).getValue()->apply(toc_visitor.get());
345       adjustEntry = toc_visitor->result;
346       foundAdjustEntry = true;
347       parsing_printf("%s[%d]: setting adjustEntry to 0x%lx, insn %s, TOC 0x%lx\n", FILE__, __LINE__,
348                      toc_visitor->result, patternIter->second->format().c_str(), toc_visitor->toc_contents);
349     }
350
351   while(patternIter != currentBlock->allInsns.begin()){
352     patternIter--;
353     if((patternIter->second->getOperation().getID() == power_op_lwz ||
354         patternIter->second->getOperation().getID() == power_op_ld) &&
355        patternIter->second->isRead(toc_reg))
356       {
357         toc_visitor->clear();
358         patternIter->second->getOperand(1).getValue()->apply(toc_visitor.get());
359         tableStartAddress = toc_visitor->result;
360         parsing_printf("%s[%d]: setting tableStartAddress to 0x%lx, insn %s, TOC 0x%lx\n", FILE__, __LINE__,
361                        toc_visitor->result, patternIter->second->format().c_str(), toc_visitor->toc_contents);
362         break;
363       }
364   }
365   return true;
366 }
367
368 namespace detail_ppc
369 {
370     bool isNonCallEdge(ParseAPI::Edge* e)
371     {
372         return e->type() != CALL;
373     }
374     bool leadsToVisitedBlock(ParseAPI::Edge* e, const std::set<Block*>& visited)
375     {
376         Block* src = e->src();
377         return visited.find(src) != visited.end();
378     }
379   void processPredecessor(Edge* e, std::set<Block*>& visited, std::deque<Block*>& worklist)
380   {
381     parsing_printf("\t\tblock %x, edge type %s\n",
382                    e->src()->start(),
383                    format(e->type()).c_str());
384     
385     // FIXME debugging assert
386     assert(isNonCallEdge(e));
387     
388     // FIXME check this algorithm... O(log n) lookup in visited
389     if(!leadsToVisitedBlock(e, visited))
390     {
391       worklist.push_back(e->src());
392       visited.insert(e->src());
393     }  
394   }
395 };
396
397
398 // This should only be called on a known indirect branch...
399 bool IA_powerDetails::parseJumpTable(Block* currBlk,
400                                      std::vector<std::pair< Address, EdgeTypeEnum> >& outEdges)
401 {
402
403   Address initialAddress = currentBlock->current;
404   toc_reg.reset(new RegisterAST(ppc32::r2));
405
406   TOC_address = currentBlock->_obj->cs()->getTOC();
407   toc_visitor.reset(new detail::TOCandOffsetExtractor(TOC_address));
408   toc_visitor->toc_reg = toc_reg;
409     
410   // If there are no prior instructions then we can't be looking at a
411   // jump through a jump table.
412   if(currentBlock->allInsns.size() < 2) {
413     parsing_printf("%s[%d]: allInsns.size() == %d, ret false", FILE__, __LINE__, currentBlock->allInsns.size());
414     return false;
415   }
416
417
418   // Check if the previous instruction is a move to CTR or LR;
419   // if it is, then this is the pattern we're familiar with.  The
420   // register being moved into CTR or LR has the address to jump to.
421   patternIter = currentBlock->curInsnIter;
422   patternIter--;
423   RegisterAST::Ptr jumpAddrReg;
424   static RegisterAST::Ptr linkReg(new RegisterAST(ppc32::lr));
425   static RegisterAST::Ptr countReg(new RegisterAST(ppc32::ctr));
426   std::set<RegisterAST::Ptr> regs;
427   if(patternIter->second->getOperation().getID() == power_op_mtspr &&
428      (patternIter->second->isWritten(linkReg) ||
429       patternIter->second->isWritten(countReg)))
430     {
431       regs.clear();
432       patternIter->second->getReadSet(regs);
433       if(regs.size() != 1) {
434         parsing_printf("expected mtspr to read 1 register, insn is %s\n", patternIter->second->format().c_str());
435         return false;
436       }
437       jumpAddrReg = *(regs.begin());
438       parsing_printf("%s[%d]: JUMPREG %s mtspr at prev insn %s \n", FILE__, __LINE__, jumpAddrReg->format().c_str(), patternIter->second->format().c_str());
439       dfgregs.insert(jumpAddrReg->getID());
440     }
441   else
442     {
443       parsing_printf("%s[%d]: couldn't find mtspr at prev insn %s, ret false", FILE__, __LINE__,
444                      patternIter->second->format().c_str());
445       return false;
446     }
447   assert(jumpAddrReg);
448   // In the pattern we've seen, if the instruction previous to this is
449   // an add with a result that ends up being used as the jump address,
450   // then we're adding a relative value we got from the table to a base
451   // address to get the jump address; in other words, the contents of
452   // the jump table are relative.
453   tableIsRelative = false;
454   if(patternIter != currentBlock->allInsns.begin())
455     {
456       patternIter--;
457       if(patternIter->second->getOperation().getID() == power_op_add &&
458          patternIter->second->isWritten(*(regs.begin())))
459         {
460           tableIsRelative = true;
461         }
462     }
463   parsing_printf(" TableIsRelative %d\n", tableIsRelative);
464
465   patternIter = currentBlock->curInsnIter;
466     
467   jumpStartAddress = 0;
468   adjustEntry = 0;
469   tableStartAddress = 0;
470   adjustTableStartAddress = 0;
471   foundAdjustEntry = false;
472     
473
474   if(!TOC_address)
475     {
476       // Find addi-addis instructions to determine the jump table start address.
477       // These instructions can be anywhere in the function before the 
478       // indirect jump.Hence parse through the current block and previous block
479       // till we reach the function entry.
480       Block* worklistBlock = currBlk;
481       std::set <Block*> visited;
482       std::deque<Block*> worklist;
483       worklist.insert(worklist.begin(), worklistBlock);
484       visited.insert(worklistBlock);
485       Intraproc epred;
486
487       while(!worklist.empty())
488         {
489           worklistBlock= worklist.front();
490           worklist.pop_front();
491           parsing_printf("\tAddress low 0x%lx high 0x%lx current block 0x%lx low 0x%lx high 0x%lx \n", worklistBlock->low(), worklistBlock->high(), currentBlock->current, currBlk->low(), currBlk->high());
492           Address blockStart = worklistBlock->start();
493           const unsigned char* b = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(blockStart));
494           parsing_printf(" Block start 0x%lx \n", blockStart);
495           InstructionDecoder dec(b, worklistBlock->size(), currentBlock->_isrc->getArch());
496           IA_IAPI IABlock(dec, blockStart, currentBlock->_obj, currentBlock->_cr, currentBlock->_isrc, worklistBlock);
497
498           while(IABlock.getInstruction() && !IABlock.hasCFT()) {
499             IABlock.advance();
500           }
501
502           patternIter = IABlock.curInsnIter;
503           findTableAddrNoTOC(&IABlock);
504           if(!jumpStartAddress)
505             {
506               jumpStartAddress = tableStartAddress;
507             }
508           if (tableStartAddress != 0) {
509             jumpStartAddress = tableStartAddress;
510             parsing_printf("\t\tjumpStartAddress 0x%lx \n", jumpStartAddress);
511             break;
512           }
513           std::for_each(boost::make_filter_iterator(epred, worklistBlock->sources().begin(), worklistBlock->sources().end()),
514                         boost::make_filter_iterator(epred, worklistBlock->sources().end(), worklistBlock->sources().end()),
515                         boost::bind(detail_ppc::processPredecessor, _1, boost::ref(visited), boost::ref(worklist)));
516           /*      Block::edgelist::const_iterator sit = worklistBlock->sources().begin(&epred);
517           for( ; sit != worklistBlock->sources().end(&epred); ++sit) {
518             parsing_printf("\t\t\tIterating \n");
519             ParseAPI::Edge *e = *sit;
520
521             // FIXME debugging assert
522             assert(e->type() != CALL);
523
524             // FIXME check this algorithm... O(log n) lookup in visited
525             if((visited.find(e->src()) == visited.end()))
526               {
527                 worklist.push_back(e->src());
528                 visited.insert(e->src());
529               }
530           }
531           */
532         }
533
534     }
535   else if (tableIsRelative) {
536     if(!parseRelativeTableIdiom())
537       {
538         return false;
539       }
540   } else {
541     foundAdjustEntry = false;
542     while( patternIter != currentBlock->allInsns.begin() )
543       {
544         if(patternIter->second->getOperation().getID() == power_op_addi &&
545            patternIter->second->isWritten(jumpAddrReg) &&
546            !foundAdjustEntry)
547           {
548             foundAdjustEntry = true;
549             toc_visitor->clear();
550             patternIter->second->getOperand(1).getValue()->apply(toc_visitor.get());
551             adjustEntry = toc_visitor->result;
552             regs.clear();
553             patternIter->second->getReadSet(regs);
554             jumpAddrReg = *(regs.begin());
555             assert(jumpAddrReg);
556           }
557         else if(patternIter->second->getOperation().getID() == power_op_lwz &&
558                 patternIter->second->isRead(toc_reg) &&
559                 patternIter->second->isWritten(jumpAddrReg))
560           {
561             toc_visitor->clear();
562             patternIter->second->getOperand(1).getValue()->apply(toc_visitor.get());
563             tableStartAddress = toc_visitor->result;
564             break;
565           }
566         patternIter--;
567       }
568   }
569     
570   const Block::edgelist & sourceEdges = currBlk->sources();
571   if(sourceEdges.size() != 1 || (*sourceEdges.begin())->type() == CALL) {
572     parsing_printf("%s[%d]: jump table not properly guarded, ret false\n", FILE__, __LINE__);
573     return false;
574   }
575
576
577     
578   // We could also set this = jumpStartAddress...
579   if (tableStartAddress == 0)  {
580     parsing_printf("%s[%d]: couldn't find table start addr, ret false\n", FILE__, __LINE__);
581     return false;
582         
583   }
584     
585   parsing_printf("%s[%d]: table start addr is 0x%x\n", FILE__, __LINE__, tableStartAddress);
586   int maxSwitch = 0;
587   
588   Block* sourceBlock = (*sourceEdges.begin())->src();
589   Address blockStart = sourceBlock->start();
590   const unsigned char* b = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(blockStart));
591   InstructionDecoder dec(b, sourceBlock->size(), currentBlock->_isrc->getArch());
592   IA_IAPI prevBlock(dec, blockStart,currentBlock->_obj,currentBlock->_cr,currentBlock->_isrc, sourceBlock);
593   while(!prevBlock.hasCFT() && prevBlock.getInstruction()) {
594     prevBlock.advance();
595   }
596
597   parsing_printf("%s[%d]: checking for max switch...\n", FILE__, __LINE__);
598   bool foundBranch = false;
599   IA_IAPI::allInsns_t::reverse_iterator iter;
600   for(iter = prevBlock.allInsns.rbegin(); iter != prevBlock.allInsns.rend(); iter++)
601
602     {
603       parsing_printf("\t\tchecking insn 0x%x: %s for cond branch + compare\n", iter->first,
604                      iter->second->format().c_str());
605       if(iter->second->getOperation().getID() == power_op_bc) // make this a true cond. branch check
606         {
607           foundBranch = true;
608         } else if(foundBranch && 
609                   (iter->second->getOperation().getID() == power_op_cmpi ||
610                    iter->second->getOperation().getID() == power_op_cmpli))
611         {
612           maxSwitch = iter->second->getOperand(2).getValue()->eval().convert<int>() + 1;
613           break;
614                 
615         }
616     } 
617
618   parsing_printf("%s[%d]: After checking: max switch %d\n", FILE__, __LINE__, maxSwitch);
619   if(!maxSwitch){
620     return false;
621   }
622
623   Address jumpStart = 0;
624   Address tableStart = 0;
625   bool is64 = (currentBlock->_isrc->getAddressWidth() == 8);
626   std::vector<std::pair< Address, EdgeTypeEnum> > edges;
627
628   if(TOC_address)
629     {
630       if (tableIsRelative) {
631         void *jumpStartPtr = currentBlock->_isrc->getPtrToData(jumpStartAddress);
632         parsing_printf("%s[%d]: jumpStartPtr (0x%lx) = %p\n", FILE__, __LINE__, jumpStartAddress, jumpStartPtr);
633         if (jumpStartPtr)
634           jumpStart = (is64
635                        ? *((Address  *)jumpStartPtr)
636                        : *((uint32_t *)jumpStartPtr));
637         parsing_printf("%s[%d]: jumpStart 0x%lx, initialAddr 0x%lx\n",
638                        FILE__, __LINE__, jumpStart, initialAddress);
639         if (jumpStartPtr == NULL) {
640           return false;
641         }
642       }
643       void *tableStartPtr = currentBlock->_isrc->getPtrToData(tableStartAddress);
644       parsing_printf("%s[%d]: tableStartPtr (0x%lx) = %p\n", FILE__, __LINE__, tableStartAddress, tableStartPtr);
645       tableStart = *((Address *)tableStartPtr);
646       if (tableStartPtr)
647         tableStart = (is64
648                       ? *((Address  *)tableStartPtr)
649                       : *((uint32_t *)tableStartPtr));
650       else {
651         return false;
652       }
653       parsing_printf("\t... tableStart 0x%lx\n", tableStart);
654
655       bool tableData = false;
656       for(int i=0;i<maxSwitch;i++){
657         Address tableEntry = adjustEntry + tableStart + (i * 4 /*instruction::size()*/);
658         parsing_printf("\t\tTable entry at 0x%lx\n", tableEntry);
659         if (currentBlock->_isrc->isValidAddress(tableEntry)) {
660           int jumpOffset;
661           if (tableData) {
662             jumpOffset = *((int *)currentBlock->_isrc->getPtrToData(tableEntry));
663           }
664           else {
665             jumpOffset = *((int *)currentBlock->_isrc->getPtrToInstruction(tableEntry));
666           }
667
668           parsing_printf("\t\t\tjumpOffset 0x%lx\n", jumpOffset);
669           Address res = (Address)(jumpStart + jumpOffset);
670
671           if (currentBlock->_isrc->isCode(res)) {
672             edges.push_back(std::make_pair((Address)(jumpStart+jumpOffset), INDIRECT));
673             parsing_printf("\t\t\tEntry of 0x%lx\n", (Address)(jumpStart + jumpOffset));
674           }
675         }
676         else {
677           parsing_printf("\t\tAddress not valid!\n");
678         }
679       }
680     }
681   // No TOC, so we're on Power32 Linux.  Do the ELF thing.
682   else
683     {
684       jumpStart = jumpStartAddress;
685       tableStart = tableStartAddress;
686       parsing_printf(" jumpStartaddress 0x%lx tableStartAddress 0x%lx \n", jumpStartAddress, tableStartAddress);
687       if(toc_visitor->toc_contents)
688         {
689           void* tmp = NULL;
690           if(currentBlock->_isrc->isValidAddress(jumpStartAddress))
691             {
692               tmp = currentBlock->_isrc->getPtrToData(jumpStartAddress);
693               if(!tmp)
694                 {
695                   tmp = currentBlock->_isrc->getPtrToInstruction(jumpStartAddress);
696                 }
697               if(tmp)
698                 {
699                   jumpStart = *((Address*)tmp);
700                   parsing_printf("\t\tjumpStart adjusted to 0x%lx\n", jumpStart);
701                 }
702             }
703           if(currentBlock->_isrc->isValidAddress(tableStartAddress))
704             {
705               tmp = currentBlock->_isrc->getPtrToData(tableStartAddress);
706               if(!tmp)
707                 {
708                   tmp = currentBlock->_isrc->getPtrToInstruction(tableStartAddress);
709                 }
710               if(tmp)
711                 {
712                   tableStart = *((Address*)tmp);
713                   parsing_printf("\t\ttableStart adjusted to 0x%lx\n", jumpStart);
714                 }
715             }
716         }
717       if (jumpStart == 0) {
718         // If jump table address is a relocation entry, this will be filled by the loader
719         // This case is common in shared library where the table address is in the GOT section which is filled by the loader
720         // Find the relocation entry for this address and look up its value
721
722         Block* sourceBlock = (*sourceEdges.begin())->src();
723         Address blockStart = sourceBlock->start();
724         const unsigned char* b = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(blockStart));
725         InstructionDecoder dec(b, sourceBlock->size(), currentBlock->_isrc->getArch());
726         IA_IAPI IABlock(dec, blockStart,currentBlock->_obj,currentBlock->_cr,currentBlock->_isrc, sourceBlock);
727
728         SymtabCodeSource *scs = dynamic_cast<SymtabCodeSource *>(IABlock._obj->cs());
729         SymtabAPI::Symtab * symtab = scs->getSymtabObject();
730         std::vector<SymtabAPI::Region *> regions;
731         symtab->getAllRegions(regions);
732         for (unsigned index = 0 ; index < regions.size(); index++) {
733           if (regions[index]->getRegionType() == SymtabAPI::Region::RT_RELA || 
734               regions[index]->getRegionType() == SymtabAPI::Region::RT_REL) {
735             std::vector<SymtabAPI::relocationEntry> relocs =
736               regions[index]->getRelocations(); 
737             parsing_printf(" \t\trelocation size %d looking for 0x%lx\n", relocs.size(), jumpStartAddress);
738             for (unsigned i = 0; i < relocs.size(); ++i) {
739               parsing_printf(" \t 0x%lx => 0x%lx addend 0x%lx \n", relocs[i].rel_addr(),relocs[i].target_addr(), relocs[i].addend());
740               if (relocs[i].rel_addr() == jumpStartAddress) {
741                 jumpStart = relocs[i].addend();
742                 break;
743               }
744             }
745             break;
746           }
747         }
748         
749         
750       }
751       if (tableStart == 0) tableStart = jumpStart;
752
753       if (!tableIsRelative) {
754         jumpStart = 0;
755       }
756       parsing_printf(" jumpStartaddress 0x%lx tableStartAddress 0x%lx \n", jumpStart, tableStart);
757
758       int entriesAdded = 0;
759       for(int i = 0; i < maxSwitch; i++)
760         {
761           void* ptr = NULL;
762           Address tableEntry = tableStart + i*4; // instruction::size();
763           if(currentBlock->_isrc->isValidAddress(tableEntry))
764             {
765               ptr = currentBlock->_isrc->getPtrToInstruction(tableEntry);
766             }
767           if(ptr)
768             {
769               int jumpOffset = *((int *)ptr);
770               edges.push_back(std::make_pair((Address)(jumpStart+jumpOffset), INDIRECT));
771               parsing_printf("\t\t\t[0x%lx] -> 0x%lx (0x%lx in table)\n", tableEntry,
772                              jumpStart+jumpOffset,
773                              jumpOffset);
774               ++entriesAdded;
775             }
776           else
777             {
778               parsing_printf("\t\t\t[0x%lx] -> [INVALID]\n", tableEntry);
779             }
780         }
781       if(!entriesAdded)
782         {
783           parsing_printf("%s[%d]: no entries added from jump table, returning false\n", FILE__, __LINE__);
784           return false;
785         }
786       parsing_printf("%s[%d]: Found %d entries in jump table, returning success\n", FILE__, __LINE__, entriesAdded);
787     }
788
789   // Sanity check entries in res
790   for (std::vector<std::pair<Address, EdgeTypeEnum> >::iterator iter = edges.begin();
791        iter != edges.end(); iter++) {
792     if ((iter->first) % 4) {
793       parsing_printf("Warning: found unaligned jump table destination 0x%lx for jump at 0x%lx, disregarding table\n",
794                      iter->first, initialAddress);
795       return false;
796     }
797   }
798   // If we have found a jump table, add the targets to outEdges   
799   for (std::vector<std::pair<Address, EdgeTypeEnum> >::iterator iter = edges.begin();
800        iter != edges.end(); iter++) {
801     outEdges.push_back(*iter);
802   }
803   return true;
804 }