IAPI opcode fix: refer to si/addic aliased instructions by primary addic opcode.
[dyninst.git] / parseAPI / src / IA_powerDetails.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "IA_powerDetails.h"
33 #include "Visitor.h"
34 #include "Register.h"
35 #include "Dereference.h"
36 #include "Immediate.h"
37 #include "BinaryFunction.h"
38 #include "debug_parse.h"
39 #include <deque>
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 // This should only be called on a known indirect branch...
369 bool IA_powerDetails::parseJumpTable(Block* currBlk,
370                                      std::vector<std::pair< Address, EdgeTypeEnum> >& outEdges)
371 {
372
373   Address initialAddress = currentBlock->current;
374   toc_reg.reset(new RegisterAST(ppc32::r2));
375
376   TOC_address = currentBlock->_obj->cs()->getTOC();
377   toc_visitor.reset(new detail::TOCandOffsetExtractor(TOC_address));
378   toc_visitor->toc_reg = toc_reg;
379     
380   // If there are no prior instructions then we can't be looking at a
381   // jump through a jump table.
382   if(currentBlock->allInsns.size() < 2) {
383     parsing_printf("%s[%d]: allInsns.size() == %d, ret false", FILE__, __LINE__, currentBlock->allInsns.size());
384     return false;
385   }
386
387
388   // Check if the previous instruction is a move to CTR or LR;
389   // if it is, then this is the pattern we're familiar with.  The
390   // register being moved into CTR or LR has the address to jump to.
391   patternIter = currentBlock->curInsnIter;
392   patternIter--;
393   RegisterAST::Ptr jumpAddrReg;
394   static RegisterAST::Ptr linkReg(new RegisterAST(ppc32::lr));
395   static RegisterAST::Ptr countReg(new RegisterAST(ppc32::ctr));
396   std::set<RegisterAST::Ptr> regs;
397   if(patternIter->second->getOperation().getID() == power_op_mtspr &&
398      (patternIter->second->isWritten(linkReg) ||
399       patternIter->second->isWritten(countReg)))
400     {
401       regs.clear();
402       patternIter->second->getReadSet(regs);
403       if(regs.size() != 1) {
404         parsing_printf("expected mtspr to read 1 register, insn is %s\n", patternIter->second->format().c_str());
405         return false;
406       }
407       jumpAddrReg = *(regs.begin());
408       parsing_printf("%s[%d]: JUMPREG %s mtspr at prev insn %s \n", FILE__, __LINE__, jumpAddrReg->format().c_str(), patternIter->second->format().c_str());
409       dfgregs.insert(jumpAddrReg->getID());
410     }
411   else
412     {
413       parsing_printf("%s[%d]: couldn't find mtspr at prev insn %s, ret false", FILE__, __LINE__,
414                      patternIter->second->format().c_str());
415       return false;
416     }
417   assert(jumpAddrReg);
418   // In the pattern we've seen, if the instruction previous to this is
419   // an add with a result that ends up being used as the jump address,
420   // then we're adding a relative value we got from the table to a base
421   // address to get the jump address; in other words, the contents of
422   // the jump table are relative.
423   tableIsRelative = false;
424   if(patternIter != currentBlock->allInsns.begin())
425     {
426       patternIter--;
427       if(patternIter->second->getOperation().getID() == power_op_add &&
428          patternIter->second->isWritten(*(regs.begin())))
429         {
430           tableIsRelative = true;
431         }
432     }
433   parsing_printf(" TableIsRelative %d\n", tableIsRelative);
434
435   patternIter = currentBlock->curInsnIter;
436     
437   jumpStartAddress = 0;
438   adjustEntry = 0;
439   tableStartAddress = 0;
440   adjustTableStartAddress = 0;
441   foundAdjustEntry = false;
442     
443
444   if(!TOC_address)
445     {
446       // Find addi-addis instructions to determine the jump table start address.
447       // These instructions can be anywhere in the function before the 
448       // indirect jump.Hence parse through the current block and previous block
449       // till we reach the function entry.
450       Block* worklistBlock = currBlk;
451       std::set <Block*> visited;
452       std::deque<Block*> worklist;
453       worklist.insert(worklist.begin(), worklistBlock);
454       visited.insert(worklistBlock);
455       Intraproc epred;
456
457       while(!worklist.empty())
458         {
459           worklistBlock= worklist.front();
460           worklist.pop_front();
461           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());
462           Address blockStart = worklistBlock->start();
463           const unsigned char* b = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(blockStart));
464           parsing_printf(" Block start 0x%lx \n", blockStart);
465           InstructionDecoder dec(b, worklistBlock->size(), currentBlock->_isrc->getArch());
466           IA_IAPI IABlock(dec, blockStart, currentBlock->_obj, currentBlock->_cr, currentBlock->_isrc, worklistBlock);
467
468           while(IABlock.getInstruction() && !IABlock.hasCFT()) {
469             IABlock.advance();
470           }
471
472           patternIter = IABlock.curInsnIter;
473           findTableAddrNoTOC(&IABlock);
474           if(!jumpStartAddress)
475             {
476               jumpStartAddress = tableStartAddress;
477             }
478           if (tableStartAddress != 0) {
479             jumpStartAddress = tableStartAddress;
480             parsing_printf("\t\tjumpStartAddress 0x%lx \n", jumpStartAddress);
481             break;
482           }
483           Block::edgelist::iterator sit = worklistBlock->sources().begin(&epred);
484           for( ; sit != worklistBlock->sources().end(); ++sit) {
485             parsing_printf("\t\t\tIterating \n");
486             ParseAPI::Edge *e = *sit;
487
488             // FIXME debugging assert
489             assert(e->type() != CALL);
490
491             // FIXME check this algorithm... O(log n) lookup in visited
492             if((visited.find(e->src()) == visited.end()))
493               {
494                 worklist.push_back(e->src());
495                 visited.insert(e->src());
496               }
497           }
498         }
499     }
500   else if (tableIsRelative) {
501     if(!parseRelativeTableIdiom())
502       {
503         return false;
504       }
505   } else {
506     foundAdjustEntry = false;
507     while( patternIter != currentBlock->allInsns.begin() )
508       {
509         if(patternIter->second->getOperation().getID() == power_op_addi &&
510            patternIter->second->isWritten(jumpAddrReg) &&
511            !foundAdjustEntry)
512           {
513             foundAdjustEntry = true;
514             toc_visitor->clear();
515             patternIter->second->getOperand(1).getValue()->apply(toc_visitor.get());
516             adjustEntry = toc_visitor->result;
517             regs.clear();
518             patternIter->second->getReadSet(regs);
519             jumpAddrReg = *(regs.begin());
520             assert(jumpAddrReg);
521           }
522         else if(patternIter->second->getOperation().getID() == power_op_lwz &&
523                 patternIter->second->isRead(toc_reg) &&
524                 patternIter->second->isWritten(jumpAddrReg))
525           {
526             toc_visitor->clear();
527             patternIter->second->getOperand(1).getValue()->apply(toc_visitor.get());
528             tableStartAddress = toc_visitor->result;
529             break;
530           }
531         patternIter--;
532       }
533   }
534     
535   Block::edgelist & sourceEdges = currBlk->sources();
536   if(sourceEdges.size() != 1 || (*sourceEdges.begin())->type() == CALL) {
537     parsing_printf("%s[%d]: jump table not properly guarded, ret false\n", FILE__, __LINE__);
538     return false;
539   }
540
541
542     
543   // We could also set this = jumpStartAddress...
544   if (tableStartAddress == 0)  {
545     parsing_printf("%s[%d]: couldn't find table start addr, ret false\n", FILE__, __LINE__);
546     return false;
547         
548   }
549     
550   parsing_printf("%s[%d]: table start addr is 0x%x\n", FILE__, __LINE__, tableStartAddress);
551   int maxSwitch = 0;
552   
553   Block* sourceBlock = (*sourceEdges.begin())->src();
554   Address blockStart = sourceBlock->start();
555   const unsigned char* b = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(blockStart));
556   InstructionDecoder dec(b, sourceBlock->size(), currentBlock->_isrc->getArch());
557   IA_IAPI prevBlock(dec, blockStart,currentBlock->_obj,currentBlock->_cr,currentBlock->_isrc, sourceBlock);
558   while(!prevBlock.hasCFT() && prevBlock.getInstruction()) {
559     prevBlock.advance();
560   }
561
562   parsing_printf("%s[%d]: checking for max switch...\n", FILE__, __LINE__);
563   bool foundBranch = false;
564   std::map<Address, Dyninst::InstructionAPI::Instruction::Ptr>::reverse_iterator iter;
565   for(iter = prevBlock.allInsns.rbegin(); iter != prevBlock.allInsns.rend(); iter++)
566
567     {
568       parsing_printf("\t\tchecking insn 0x%x: %s for cond branch + compare\n", iter->first,
569                      iter->second->format().c_str());
570       if(iter->second->getOperation().getID() == power_op_bc) // make this a true cond. branch check
571         {
572           foundBranch = true;
573         } else if(foundBranch && 
574                   (iter->second->getOperation().getID() == power_op_cmpi ||
575                    iter->second->getOperation().getID() == power_op_cmpli))
576         {
577           maxSwitch = iter->second->getOperand(2).getValue()->eval().convert<int>() + 1;
578           break;
579                 
580         }
581     } 
582
583   parsing_printf("%s[%d]: After checking: max switch %d\n", FILE__, __LINE__, maxSwitch);
584   if(!maxSwitch){
585     return false;
586   }
587
588   Address jumpStart = 0;
589   Address tableStart = 0;
590   bool is64 = (currentBlock->_isrc->getAddressWidth() == 8);
591   std::vector<std::pair< Address, EdgeTypeEnum> > edges;
592
593   if(TOC_address)
594     {
595       if (tableIsRelative) {
596         void *jumpStartPtr = currentBlock->_isrc->getPtrToData(jumpStartAddress);
597         parsing_printf("%s[%d]: jumpStartPtr (0x%lx) = %p\n", FILE__, __LINE__, jumpStartAddress, jumpStartPtr);
598         if (jumpStartPtr)
599           jumpStart = (is64
600                        ? *((Address  *)jumpStartPtr)
601                        : *((uint32_t *)jumpStartPtr));
602         parsing_printf("%s[%d]: jumpStart 0x%lx, initialAddr 0x%lx\n",
603                        FILE__, __LINE__, jumpStart, initialAddress);
604         if (jumpStartPtr == NULL) {
605           return false;
606         }
607       }
608       void *tableStartPtr = currentBlock->_isrc->getPtrToData(tableStartAddress);
609       parsing_printf("%s[%d]: tableStartPtr (0x%lx) = %p\n", FILE__, __LINE__, tableStartAddress, tableStartPtr);
610       tableStart = *((Address *)tableStartPtr);
611       if (tableStartPtr)
612         tableStart = (is64
613                       ? *((Address  *)tableStartPtr)
614                       : *((uint32_t *)tableStartPtr));
615       else {
616         return false;
617       }
618       parsing_printf("\t... tableStart 0x%lx\n", tableStart);
619
620       bool tableData = false;
621       for(int i=0;i<maxSwitch;i++){
622         Address tableEntry = adjustEntry + tableStart + (i * 4 /*instruction::size()*/);
623         parsing_printf("\t\tTable entry at 0x%lx\n", tableEntry);
624         if (currentBlock->_isrc->isValidAddress(tableEntry)) {
625           int jumpOffset;
626           if (tableData) {
627             jumpOffset = *((int *)currentBlock->_isrc->getPtrToData(tableEntry));
628           }
629           else {
630             jumpOffset = *((int *)currentBlock->_isrc->getPtrToInstruction(tableEntry));
631           }
632
633           parsing_printf("\t\t\tjumpOffset 0x%lx\n", jumpOffset);
634           Address res = (Address)(jumpStart + jumpOffset);
635
636           if (currentBlock->_isrc->isCode(res)) {
637             edges.push_back(std::make_pair((Address)(jumpStart+jumpOffset), INDIRECT));
638             parsing_printf("\t\t\tEntry of 0x%lx\n", (Address)(jumpStart + jumpOffset));
639           }
640         }
641         else {
642           parsing_printf("\t\tAddress not valid!\n");
643         }
644       }
645     }
646   // No TOC, so we're on Power32 Linux.  Do the ELF thing.
647   else
648     {
649       jumpStart = jumpStartAddress;
650       tableStart = tableStartAddress;
651       parsing_printf(" jumpStartaddress 0x%lx tableStartAddress 0x%lx \n", jumpStartAddress, tableStartAddress);
652       if(toc_visitor->toc_contents)
653         {
654           void* tmp = NULL;
655           if(currentBlock->_isrc->isValidAddress(jumpStartAddress))
656             {
657               tmp = currentBlock->_isrc->getPtrToData(jumpStartAddress);
658               if(!tmp)
659                 {
660                   tmp = currentBlock->_isrc->getPtrToInstruction(jumpStartAddress);
661                 }
662               if(tmp)
663                 {
664                   jumpStart = *((Address*)tmp);
665                   parsing_printf("\t\tjumpStart adjusted to 0x%lx\n", jumpStart);
666                 }
667             }
668           if(currentBlock->_isrc->isValidAddress(tableStartAddress))
669             {
670               tmp = currentBlock->_isrc->getPtrToData(tableStartAddress);
671               if(!tmp)
672                 {
673                   tmp = currentBlock->_isrc->getPtrToInstruction(tableStartAddress);
674                 }
675               if(tmp)
676                 {
677                   tableStart = *((Address*)tmp);
678                   parsing_printf("\t\ttableStart adjusted to 0x%lx\n", jumpStart);
679                 }
680             }
681         }
682       if (jumpStart == 0) {
683         // If jump table address is a relocation entry, this will be filled by the loader
684         // This case is common in shared library where the table address is in the GOT section which is filled by the loader
685         // Find the relocation entry for this address and look up its value
686
687         Block* sourceBlock = (*sourceEdges.begin())->src();
688         Address blockStart = sourceBlock->start();
689         const unsigned char* b = (const unsigned char*)(currentBlock->_isrc->getPtrToInstruction(blockStart));
690         InstructionDecoder dec(b, sourceBlock->size(), currentBlock->_isrc->getArch());
691         IA_IAPI IABlock(dec, blockStart,currentBlock->_obj,currentBlock->_cr,currentBlock->_isrc, sourceBlock);
692
693         SymtabCodeSource *scs = dynamic_cast<SymtabCodeSource *>(IABlock._obj->cs());
694         SymtabAPI::Symtab * symtab = scs->getSymtabObject();
695         std::vector<SymtabAPI::Region *> regions;
696         symtab->getAllRegions(regions);
697         for (unsigned index = 0 ; index < regions.size(); index++) {
698           if (regions[index]->getRegionType() == SymtabAPI::Region::RT_RELA || 
699               regions[index]->getRegionType() == SymtabAPI::Region::RT_REL) {
700             std::vector<SymtabAPI::relocationEntry> relocs =
701               regions[index]->getRelocations(); 
702             parsing_printf(" \t\trelocation size %d looking for 0x%lx\n", relocs.size(), jumpStartAddress);
703             for (unsigned i = 0; i < relocs.size(); ++i) {
704               parsing_printf(" \t 0x%lx => 0x%lx addend 0x%lx \n", relocs[i].rel_addr(),relocs[i].target_addr(), relocs[i].addend());
705               if (relocs[i].rel_addr() == jumpStartAddress) {
706                 jumpStart = relocs[i].addend();
707                 break;
708               }
709             }
710             break;
711           }
712         }
713         
714         
715       }
716       if (tableStart == 0) tableStart = jumpStart;
717
718       if (!tableIsRelative) {
719         jumpStart = 0;
720       }
721       parsing_printf(" jumpStartaddress 0x%lx tableStartAddress 0x%lx \n", jumpStart, tableStart);
722
723       int entriesAdded = 0;
724       for(int i = 0; i < maxSwitch; i++)
725         {
726           void* ptr = NULL;
727           Address tableEntry = tableStart + i*4; // instruction::size();
728           if(currentBlock->_isrc->isValidAddress(tableEntry))
729             {
730               ptr = currentBlock->_isrc->getPtrToInstruction(tableEntry);
731             }
732           if(ptr)
733             {
734               int jumpOffset = *((int *)ptr);
735               edges.push_back(std::make_pair((Address)(jumpStart+jumpOffset), INDIRECT));
736               parsing_printf("\t\t\t[0x%lx] -> 0x%lx (0x%lx in table)\n", tableEntry,
737                              jumpStart+jumpOffset,
738                              jumpOffset);
739               ++entriesAdded;
740             }
741           else
742             {
743               parsing_printf("\t\t\t[0x%lx] -> [INVALID]\n", tableEntry);
744             }
745         }
746       if(!entriesAdded)
747         {
748           parsing_printf("%s[%d]: no entries added from jump table, returning false\n", FILE__, __LINE__);
749           return false;
750         }
751       parsing_printf("%s[%d]: Found %d entries in jump table, returning success\n", FILE__, __LINE__, entriesAdded);
752     }
753
754   // Sanity check entries in res
755   for (std::vector<std::pair<Address, EdgeTypeEnum> >::iterator iter = edges.begin();
756        iter != edges.end(); iter++) {
757     if ((iter->first) % 4) {
758       parsing_printf("Warning: found unaligned jump table destination 0x%lx for jump at 0x%lx, disregarding table\n",
759                      iter->first, initialAddress);
760       return false;
761     }
762   }
763   // If we have found a jump table, add the targets to outEdges   
764   for (std::vector<std::pair<Address, EdgeTypeEnum> >::iterator iter = edges.begin();
765        iter != edges.end(); iter++) {
766     outEdges.push_back(*iter);
767   }
768   return true;
769 }