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