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