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