DataflowAPI-related Power Linux build fixes
[dyninst.git] / parseAPI / src / IA_power.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
33 #include "IA_IAPI.h"
34 #include "IA_power.h"
35
36 #include "Register.h"
37 #include "Dereference.h"
38 #include "Immediate.h"
39 #include "BinaryFunction.h"
40
41 #include "common/h/arch.h"
42
43 #include "parseAPI/src/debug_parse.h"
44
45 #include <deque>
46 #include <iostream>
47 #include <sstream>
48 #include <functional>
49 #include <algorithm>
50 #include <set>
51
52 using namespace Dyninst;
53 using namespace InstructionAPI;
54 using namespace Dyninst::ParseAPI;
55 using namespace Dyninst::InsnAdapter;
56
57 static RegisterAST::Ptr ppc32_R11 (new RegisterAST (ppc32::r11));
58 static RegisterAST::Ptr ppc32_LR  (new RegisterAST (ppc32::lr));
59 static RegisterAST::Ptr ppc32_SP  (new RegisterAST (ppc32::r1));
60
61 static RegisterAST::Ptr ppc64_R11 (new RegisterAST (ppc64::r11));
62 static RegisterAST::Ptr ppc64_LR  (new RegisterAST (ppc64::lr));
63 static RegisterAST::Ptr ppc64_SP  (new RegisterAST (ppc64::r1));
64
65 bool IA_IAPI::isFrameSetupInsn(Instruction::Ptr) const
66 {
67     return false;
68 }
69
70 bool IA_IAPI::isNop() const
71 {
72     return false;
73 }
74
75 bool IA_IAPI::isThunk() const {
76     return false;
77 }
78
79 bool IA_IAPI::isTailCall(Function* /*context*/,unsigned int) const
80 {
81     parsing_printf("Checking for Tail Call \n");
82
83     if(tailCall.first) {
84         parsing_printf("\tReturning cached tail call check result: %d\n", tailCall.second);
85         return tailCall.second;
86     }
87     tailCall.first = true;
88
89     if(curInsn()->getCategory() == c_BranchInsn &&
90        _obj->findFuncByEntry(_cr,getCFT()))
91     {
92         parsing_printf("\tjump to 0x%lx, TAIL CALL\n", getCFT());
93         tailCall.second = true;
94         return tailCall.second;
95     }
96
97     if(allInsns.size() < 2) {
98         tailCall.second = false;
99         parsing_printf("\ttoo few insns to detect tail call\n");
100         return tailCall.second;
101     }
102     tailCall.second = false;
103     return tailCall.second;
104
105 }
106
107 bool IA_IAPI::savesFP() const
108 {
109     return false;
110 }
111
112 bool IA_IAPI::isStackFramePreamble() const
113 {
114     return false;
115 }
116
117 bool IA_IAPI::cleansStack() const
118 {
119     return false;
120 }
121
122 class PPCReturnPredicates : public Slicer::Predicates {
123   virtual bool widenAtPoint(Assignment::Ptr p) {
124     for (std::vector<AbsRegion>::const_iterator iter = p->inputs().begin();
125          iter != p->inputs().end(); ++iter) {
126       if ((*iter).type() != Absloc::Unknown)
127         return true;
128     }
129     return false;
130   }
131 };
132
133
134
135 bool IA_IAPI::sliceReturn(ParseAPI::Block* bit, Address ret_addr, ParseAPI::Function * func) const {
136
137   parsing_printf(" sliceReturn ret 0x%lx address 0x%lx func %s addr 0x%lx \n", ret_addr, bit->lastInsnAddr(), func->name().c_str(), func->addr() );
138   AST::Ptr pcDef;
139   AssignmentConverter converter(true);
140   vector<Assignment::Ptr>::iterator ait;
141   vector<Assignment::Ptr> assgns;
142   PPCReturnPredicates preds;
143
144   Address retnAddr = bit->lastInsnAddr();
145   InstructionDecoder retdec( _isrc->getPtrToInstruction( retnAddr ), 
146                              InstructionDecoder::maxInstructionLength, 
147                              _cr->getArch() );
148   Instruction::Ptr retn = retdec.decode();
149   converter.convert(retn, retnAddr, func, bit, assgns);
150   for (ait = assgns.begin(); assgns.end() != ait; ait++) {
151       AbsRegion & outReg = (*ait)->out();
152       if ( outReg.absloc().isPC() ) {
153           Slicer slicer(*ait,bit,func);
154           Graph::Ptr slGraph = slicer.backwardSlice(preds);
155           DataflowAPI::SymEval::Result_t slRes;
156           DataflowAPI::SymEval::expand(slGraph,slRes);
157           pcDef = slRes[*ait];
158           /*
159           for (DataflowAPI::SymEval::Result_t::const_iterator r_iter = slRes.begin();
160                r_iter != slRes.end(); ++r_iter) {
161               cout << "-----------------" << endl;
162               cout << r_iter->first->format();
163               cout << " == ";
164               cout << (r_iter->second ? r_iter->second->format() : "<NULL>") << endl;
165           }
166           */
167           if (!pcDef) assert(0);
168           break;
169       }
170   }
171
172   PPC_BLR_Visitor checker(ret_addr);
173   pcDef->accept(&checker);
174   if (checker.returnState() == PPC_BLR_Visitor::PPC_BLR_RETURN) {
175     return true;
176   } else {
177             return false;
178   }
179 }
180
181 bool IA_IAPI::isReturnAddrSave(Address& retAddr) const
182 {
183   RegisterAST::Ptr regLR, regSP;
184   switch (_isrc->getArch()) {
185   case Arch_ppc32: regLR = ppc32_LR; regSP = ppc32_SP; break;
186   case Arch_ppc64: regLR = ppc64_LR; regSP = ppc64_SP; break;
187   default: assert(0 && "Inappropriate _isrc architechture.");
188   }
189
190   std::set < RegisterAST::Ptr > regs;
191   RegisterAST::Ptr destLRReg;
192   bool foundMFLR = false;
193   Address ret = 0;
194   int cnt = 1;
195   Instruction::Ptr ci = curInsn ();
196    parsing_printf(" Examining address 0x%lx to check if LR is saved on stack \n", getAddr());
197     parsing_printf("\t\tchecking insn %s \n", ci->format().c_str());
198
199   if (ci->getOperation ().getID () == power_op_mfspr &&
200       ci->isRead (regLR))
201     {
202       foundMFLR = true;
203       ci->getWriteSet (regs);
204       if (regs.size () != 1)
205         {
206           parsing_printf ("mfspr wrote %d registers instead of 1. insn: %s\n",
207                           regs.size (), ci->format ().c_str ());
208           return 0;
209         }
210       destLRReg = *(regs.begin ());
211       retAddr = getAddr();
212       parsing_printf ("Found MFLR saved in %s at 0x%lx\n",
213                       destLRReg->format ().c_str (), getAddr());
214     }
215
216   if (foundMFLR)
217     {
218
219       // walk to first control flow transfer instruction, looking
220       // for a save of destLRReg
221       IA_IAPI copy (dec, getAddr (), _obj, _cr, _isrc, _curBlk);
222       while (!copy.hasCFT () && copy.curInsn ())
223         {
224           ci = copy.curInsn ();
225           if (ci->writesMemory () &&
226               ci->isRead (regSP) && ci->isRead (destLRReg))
227             {
228               ret = true;
229               break;
230             }
231           else if (ci->isWritten (destLRReg))
232             {
233               ret = false;
234               break;
235             }
236           copy.advance ();
237           ++cnt;
238         }
239     }
240   parsing_printf ("[%s:%d] isReturnAddrSave examined %d instructions - returning %d \n", FILE__, __LINE__, cnt, ret);
241   return ret;
242 }
243
244 bool IA_IAPI::isReturn(Dyninst::ParseAPI::Function * context, Dyninst::ParseAPI::Block* currBlk) const
245 {
246   /* Check for leaf node or lw - mflr - blr pattern */
247   if (curInsn()->getCategory() != c_ReturnInsn) {
248         parsing_printf(" Not BLR - returning false \n");
249         return false;
250    }
251   Instruction::Ptr ci = curInsn ();
252   Function *func = context;
253   parsing_printf
254     ("isblrReturn at 0x%lx Addr 0x%lx 0x%lx Function addr 0x%lx leaf %d \n",
255      current, getAddr (), currBlk->start (), context->addr (),
256      func->_is_leaf_function);
257   if (!func->_is_leaf_function)
258     {
259       parsing_printf ("\t LR saved for %s \n", func->name().c_str());
260       // Check for lwz from Stack - mtlr - blr 
261       RegisterAST::Ptr regLR, regSP, reg11;
262       switch (_isrc->getArch()) {
263       case Arch_ppc32:
264           regLR = ppc32_LR; regSP = ppc32_SP; reg11 = ppc32_R11; break;
265       case Arch_ppc64:
266           regLR = ppc64_LR; regSP = ppc64_SP; reg11 = ppc64_R11; break;
267       default: assert(0 && "Inappropriate _isrc architechture.");
268       }
269
270       std::set < RegisterAST::Ptr > regs;
271       RegisterAST::Ptr sourceLRReg;
272
273       Instruction::Ptr ci = curInsn ();
274       bool foundMTLR = false;
275       allInsns_t::reverse_iterator iter;
276       Address blockStart = currBlk->start ();
277       const unsigned char *b =
278         (const unsigned char *) (this->_isrc->
279                                  getPtrToInstruction (blockStart));
280       InstructionDecoder decCopy (b, currBlk->size (),
281                                   this->_isrc->getArch ());
282       IA_IAPI copy (decCopy, blockStart, _obj, _cr, _isrc, _curBlk);
283       while (copy.getInstruction () && !copy.hasCFT ())
284         {
285           copy.advance ();
286         }
287       for(iter = copy.allInsns.rbegin(); iter != copy.allInsns.rend(); iter++)
288         {
289           parsing_printf ("\t\tchecking insn 0x%x: %s \n", iter->first,
290                   iter->second->format ().c_str ());
291           if (iter->second->getOperation ().getID () == power_op_mtspr &&
292               iter->second->isWritten (regLR))
293             {
294               iter->second->getReadSet (regs);
295               if (regs.size () != 1)
296                 {
297                   parsing_printf
298                     ("expected mtspr to read 1 register, insn is %s\n",
299                      ci->format ().c_str ());
300                   return false;
301                 }
302               sourceLRReg = *(regs.begin ());
303               parsing_printf ("\t\t\t **** Found MTLR saved from %s \n",
304                       sourceLRReg->format ().c_str ());
305               foundMTLR = true;
306             }
307           else if (foundMTLR &&
308                    iter->second->readsMemory () &&
309                    (iter->second->isRead (regSP) ||
310                     (iter->second->isRead (reg11))) &&
311                    iter->second->isWritten (sourceLRReg))
312             {
313               parsing_printf ("\t\t\t **** Found lwz - RETURNING TRUE\n");
314               return true;
315             }
316         }
317
318       parsing_printf (" Slicing for Addr 0x%lx startAddr 0x%lx ret addr 0x%lx func %s\n",
319               getAddr (), currBlk->start (), func->_ret_addr, func->name().c_str());
320       if (sliceReturn(currBlk, func->_ret_addr, func)) {
321         parsing_printf ("\t\t\t **** Slicing - is a return instruction\n");
322         return true;
323         } else {
324         parsing_printf ("\t\t\t **** Slicing - is not a return instruction\n");
325       return false;     
326         }
327     }
328   else
329     {
330       parsing_printf ("\t leaf node  RETURNING TRUE \n");
331       return true;
332     }
333 }
334
335 bool IA_IAPI::isFakeCall() const
336 {
337     return false;
338 }
339
340 bool IA_IAPI::isIATcall() const
341 {
342     return false;
343 }
344
345 const unsigned int B_UNCOND      = 0x48000000;
346 const unsigned int ADDIS_R12_R12 = 0x3d8c0000;
347 const unsigned int ADDIS_R12_R2  = 0x3d820000;
348 const unsigned int ADDIS_R2_R2   = 0x3c420000;
349 const unsigned int ADDI_R12_R12  = 0x398c0000;
350 const unsigned int ADDI_R2_R2    = 0x38420000;
351 const unsigned int STD_R2_40R1   = 0xf8410028;
352 const unsigned int LD_R2_40R1    = 0xe8410028;
353 const unsigned int LD_R2_0R2     = 0xe8420000;
354 const unsigned int LD_R2_0R12    = 0xe84c0000;
355 const unsigned int LD_R11_0R12   = 0xe96c0000;
356 const unsigned int LD_R11_0R2    = 0xe9620000;
357 const unsigned int MTCTR_R11     = 0x7d6903a6;
358 const unsigned int BCTR          = 0x4e800420;
359
360 typedef enum {
361     STUB_UNKNOWN,
362     STUB_LONG_BRANCH,
363     STUB_TOC_BRANCH,
364     STUB_PLT_CALL
365 } linker_stub_t;
366
367 linker_stub_t checkLinkerStub(void *insn_buf, Offset &off)
368 {
369     instruction *insn = static_cast<instruction *>(insn_buf);
370
371 #if defined(ppc64_linux)
372     /*
373      * Linker stubs seen from GNU's binutils.
374      * (see the following functions in binutils' bfd/elf64-ppc.c:
375      *     ppc_build_one_stub()
376      *     build_plt_stub()
377      *     build_tls_get_addr_stub()
378      *
379      * We could be clever and create some sort of state machine that will
380      * determine the correct signature by only reading each instruction
381      * once.  However, I assume this will also make the code harder to
382      * maintain, and so I've gone the dumb route.  We can re-code this
383      * section if it's determined to be a performance bottleneck.
384      *
385      * Add stub signatures as we see more.
386      */
387
388     // ----------------------------------------------
389     // ppc_stub_plt_call:
390     //
391
392     // binutils >= 2.18 PLT stub signatures look like this:
393     // if (PPC_HA (off) != 0)
394     //   ADDIS_R12_R2 | PPC_HA (off)
395     //   STD_R2_40R1
396     //   LD_R11_0R12  | PPC_LO (off)
397     //   ADDI_R12_R12 | PPC_LO (off) if (PPC_HA (off + 16) != PPC_HA (off))
398     //   MTCTR_R11
399     //   LD_R2_0R12   | PPC_LO (off + 8)
400     //   LD_R11_0R12  | PPC_LO (off + 16)
401     //   BCTR
402     // else
403     //   STD_R2_40R1
404     //   LD_R11_0R2   | PPC_LO (off)
405     //   ADDI_R2_R2   | PPC_LO (off)
406     //   MTCTR_R11
407     //   LD_R11_0R2   | PPC_LO (off + 16)
408     //   LD_R2_0R2    | PPC_LO (off + 8)
409     //   BCTR
410     // endif
411     //
412     // This results in three possible stubs:
413
414     if (   (insn[0].asInt() & 0xffff0000) == ADDIS_R12_R2
415         &&  insn[1].asInt()               == STD_R2_40R1
416         && (insn[2].asInt() & 0xffff0000) == LD_R11_0R12
417         && (insn[2].asInt() & 0xffff0000) == ADDI_R12_R12
418         &&  insn[4].asInt()               == MTCTR_R11
419         && (insn[3].asInt() & 0xffff0000) == LD_R2_0R12
420         && (insn[5].asInt() & 0xffff0000) == LD_R11_0R12
421         &&  insn[6].asInt()               == BCTR)
422     {
423         off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
424         return STUB_PLT_CALL;
425     }
426
427     if (   (insn[0].asInt() & 0xffff0000) == ADDIS_R12_R2
428         &&  insn[1].asInt()               == STD_R2_40R1
429         && (insn[2].asInt() & 0xffff0000) == LD_R11_0R12
430         &&  insn[4].asInt()               == MTCTR_R11
431         && (insn[3].asInt() & 0xffff0000) == LD_R2_0R12
432         && (insn[5].asInt() & 0xffff0000) == LD_R11_0R12
433         &&  insn[6].asInt()               == BCTR)
434     {
435         off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
436         return STUB_PLT_CALL;
437     }
438     
439     if (    insn[1].asInt()               == STD_R2_40R1
440         && (insn[2].asInt() & 0xffff0000) == LD_R11_0R2
441         && (insn[2].asInt() & 0xffff0000) == ADDI_R2_R2
442         &&  insn[4].asInt()               == MTCTR_R11
443         && (insn[3].asInt() & 0xffff0000) == LD_R11_0R12
444         && (insn[5].asInt() & 0xffff0000) == LD_R2_0R12
445         &&  insn[6].asInt()               == BCTR)
446     {
447         off = DFORM_SI(insn[1]);
448         return STUB_PLT_CALL;
449     }
450
451     // binutils from 1.15 -> 2.18 PLT stub signatures look like this:
452     // ADDIS_R12_R2  | PPC_HA (off)
453     // STD_R2_40R1
454     // LD_R11_0R12   | PPC_LO (off)
455     // ADDIS_R12_R12 | 1            if (PPC_HA (off + 8) != PPC_HA (off))
456     // LD_R2_0R12    | PPC_LO (off)
457     // ADDIS_R12_R12 | 1            if (PPC_HA (off + 16) != PPC_HA (off))
458     // MTCTR_R11
459     // LD_R11_0R12   | PPC_LO (off)
460     // BCTR
461     //
462     // This results in three possible stubs:
463
464     if (   (insn[0].asInt() & 0xffff0000) ==  ADDIS_R12_R2
465         &&  insn[1].asInt()               ==  STD_R2_40R1
466         && (insn[2].asInt() & 0xffff0000) ==  LD_R11_0R12
467         && (insn[3].asInt() & 0xffff0000) ==  LD_R2_0R12
468         &&  insn[4].asInt()               ==  MTCTR_R11
469         && (insn[5].asInt() & 0xffff0000) ==  LD_R11_0R12
470         &&  insn[6].asInt()               ==  BCTR)
471     {
472         off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
473         return STUB_PLT_CALL;
474     }
475
476     if (   (insn[0].asInt() & 0xffff0000) ==  ADDIS_R12_R2
477         &&  insn[1].asInt()               ==  STD_R2_40R1
478         && (insn[2].asInt() & 0xffff0000) ==  LD_R11_0R12
479         && (insn[3].asInt() & 0xffff0000) ==  LD_R2_0R12
480         &&  insn[4].asInt()               == (ADDIS_R12_R12 | 1)
481         &&  insn[5].asInt()               ==  MTCTR_R11
482         && (insn[6].asInt() & 0xffff0000) ==  LD_R11_0R12
483         &&  insn[7].asInt()               ==  BCTR)
484     {
485         off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
486         return STUB_PLT_CALL;
487     }
488
489     if (   (insn[0].asInt() & 0xffff0000) ==  ADDIS_R12_R2
490         &&  insn[1].asInt()               ==  STD_R2_40R1
491         && (insn[2].asInt() & 0xffff0000) ==  LD_R11_0R12
492         &&  insn[3].asInt()               == (ADDIS_R12_R12 | 1)
493         && (insn[4].asInt() & 0xffff0000) ==  LD_R2_0R12
494         &&  insn[5].asInt()               == (ADDIS_R12_R12 | 1)
495         &&  insn[6].asInt()               ==  MTCTR_R11
496         && (insn[7].asInt() & 0xffff0000) ==  LD_R11_0R12
497         &&  insn[8].asInt()               ==  BCTR)
498     {
499         off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
500         return STUB_PLT_CALL;
501     }
502
503     // binutils < 1.15 PLT stub signatures look like this:
504     // LD_R2_40R1                   if (glink)
505     // ADDIS_R12_R2  | PPC_HA (off)
506     // STD_R2_40R1                  if (!glink)
507     // LD_R11_0R12   | PPC_LO (off)
508     // ADDIS_R12_R12 | 1            if (PPC_HA (off + 8) != PPC_HA (off))
509     // LD_R2_0R12    | PPC_LO (off)
510     // ADDIS_R12_R12 | 1            if (PPC_HA (off + 16) != PPC_HA (off))
511     // MTCTR_R11
512     // LD_R11_0R12   | PPC_LO (off)
513     // BCTR
514     //
515     // The non-glink case is identical to the cases above, so we need only
516     // handle the three glink cases:
517
518     /* Ugg.  The toc register is pulled off the stack for these cases.
519        This is most likely the toc for the callee, but we don't know
520        who the callee is yet.
521     */
522
523     if (    insn[0].asInt()               ==  LD_R2_40R1
524         && (insn[1].asInt() & 0xffff0000) ==  ADDIS_R12_R2
525         && (insn[2].asInt() & 0xffff0000) ==  LD_R11_0R12
526         && (insn[3].asInt() & 0xffff0000) ==  LD_R2_0R12
527         &&  insn[4].asInt()               ==  MTCTR_R11
528         && (insn[5].asInt() & 0xffff0000) ==  LD_R11_0R12
529         &&  insn[6].asInt()               ==  BCTR)
530     {
531         fprintf(stderr, "WARNING: Pre-binutils 1.15 linker detected. PLT call stubs may not be handled properly.\n");
532         return STUB_UNKNOWN;
533         //off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
534         //return STUB_PLT_CALL;
535     }
536
537     if (    insn[0].asInt()               ==  LD_R2_40R1
538         && (insn[1].asInt() & 0xffff0000) ==  ADDIS_R12_R2
539         && (insn[2].asInt() & 0xffff0000) ==  LD_R11_0R12
540         && (insn[3].asInt() & 0xffff0000) ==  LD_R2_0R12
541         &&  insn[4].asInt()               == (ADDIS_R12_R12 | 1)
542         &&  insn[5].asInt()               ==  MTCTR_R11
543         && (insn[6].asInt() & 0xffff0000) ==  LD_R11_0R12
544         &&  insn[7].asInt()               ==  BCTR)
545     {
546         fprintf(stderr, "WARNING: Pre-binutils 1.15 linker detected. PLT call stubs may not be handled properly.\n");
547         return STUB_UNKNOWN;
548         //off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
549         //return STUB_PLT_CALL;
550     }
551
552     if (    insn[0].asInt()               ==  LD_R2_40R1
553         && (insn[1].asInt() & 0xffff0000) ==  ADDIS_R12_R2
554         && (insn[2].asInt() & 0xffff0000) ==  LD_R11_0R12
555         &&  insn[3].asInt()               == (ADDIS_R12_R12 | 1)
556         && (insn[4].asInt() & 0xffff0000) ==  LD_R2_0R12
557         &&  insn[5].asInt()               == (ADDIS_R12_R12 | 1)
558         &&  insn[6].asInt()               ==  MTCTR_R11
559         && (insn[7].asInt() & 0xffff0000) ==  LD_R11_0R12
560         &&  insn[8].asInt()               ==  BCTR)
561     {
562         fprintf(stderr, "WARNING: Pre-binutils 1.15 linker detected. PLT call stubs may not be handled properly.\n");
563         return STUB_UNKNOWN;
564         //off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[2]);
565         //return STUB_PLT_CALL;
566     }
567
568     // ----------------------------------------------
569     // ppc_stub_long_branch:
570     // ppc_stub_long_branch_r2off:
571     if (   (insn[0].asInt() & 0xfc000000) == B_UNCOND)
572     {
573         off = IFORM_LI(insn[0]) << 2;
574         return STUB_LONG_BRANCH;
575     }
576
577     if (    insn[0].asInt()               == STD_R2_40R1
578         && (insn[1].asInt() & 0xffff0000) == ADDIS_R2_R2
579         && (insn[2].asInt() & 0xffff0000) == ADDI_R2_R2
580         && (insn[3].asInt() & 0xfc000003) == B_UNCOND)
581     {
582         off = (3 * 4) + (IFORM_LI(insn[3]) << 2);
583         return STUB_LONG_BRANCH;
584     }
585
586     if (    insn[0].asInt()               == STD_R2_40R1
587         && (insn[1].asInt() & 0xffff0000) == ADDI_R2_R2
588         && (insn[2].asInt() & 0xfc000003) == B_UNCOND)
589     {
590         off = (2 * 4) + (IFORM_LI(insn[2]) << 2);
591         return STUB_LONG_BRANCH;
592     }
593
594     // ----------------------------------------------
595     // ppc_stub_plt_branch:
596     //
597     if (   (insn[0].asInt() & 0xffff0000) == ADDIS_R12_R2
598         && (insn[1].asInt() & 0xffff0000) == LD_R11_0R12
599         &&  insn[2].asInt()               == MTCTR_R11
600         &&  insn[3].asInt()               == BCTR)
601     {
602         off = (DFORM_SI(insn[0]) << 16) + DFORM_SI(insn[1]);
603         return STUB_TOC_BRANCH;
604     }
605
606     if (   (insn[0].asInt() & 0xffff0000) == LD_R11_0R2
607         &&  insn[1].asInt()               == MTCTR_R11
608         &&  insn[2].asInt()               == BCTR)
609     {
610         off = DFORM_SI(insn[0]);
611         return STUB_TOC_BRANCH;
612     }
613
614     // ----------------------------------------------
615     // ppc_stub_plt_branch_r2off:
616     //
617
618     // With offset > 16 bits && r2offset > 16 bits
619     if (    insn[0].asInt()               == STD_R2_40R1
620         && (insn[1].asInt() & 0xffff0000) == ADDIS_R12_R2
621         && (insn[2].asInt() & 0xffff0000) == LD_R11_0R12
622         && (insn[3].asInt() & 0xffff0000) == ADDIS_R2_R2
623         && (insn[4].asInt() & 0xffff0000) == ADDI_R2_R2
624         &&  insn[5].asInt()               == MTCTR_R11
625         &&  insn[6].asInt()               == BCTR)
626     {
627         off = (DFORM_SI(insn[1]) << 16) + DFORM_SI(insn[2]);
628         return STUB_TOC_BRANCH;
629     }
630
631     // With offset > 16 bits && r2offset <= 16 bits
632     if (    insn[0].asInt()               == STD_R2_40R1
633         && (insn[1].asInt() & 0xffff0000) == ADDIS_R12_R2
634         && (insn[2].asInt() & 0xffff0000) == LD_R11_0R12
635         && (insn[3].asInt() & 0xffff0000) == ADDI_R2_R2
636         &&  insn[4].asInt()               == MTCTR_R11
637         &&  insn[5].asInt()               == BCTR)
638     {
639         off = (DFORM_SI(insn[1]) << 16) + DFORM_SI(insn[2]);
640         return STUB_TOC_BRANCH;
641     }
642
643     // With offset <= 16 bits && r2offset > 16 bits
644     if (    insn[0].asInt()               == STD_R2_40R1
645         && (insn[1].asInt() & 0xffff0000) == LD_R11_0R2
646         && (insn[2].asInt() & 0xffff0000) == ADDIS_R2_R2
647         && (insn[3].asInt() & 0xffff0000) == ADDI_R2_R2
648         &&  insn[4].asInt()               == MTCTR_R11
649         &&  insn[5].asInt()               == BCTR)
650     {
651         off = DFORM_SI(insn[1]);
652         return STUB_TOC_BRANCH;
653     }
654
655     // With offset <= 16 bits && r2offset <= 16 bits
656     if (    insn[0].asInt()               == STD_R2_40R1
657         && (insn[1].asInt() & 0xffff0000) == LD_R11_0R2
658         && (insn[2].asInt() & 0xffff0000) == ADDI_R2_R2
659         &&  insn[3].asInt()               == MTCTR_R11
660         &&  insn[4].asInt()               == BCTR)
661     {
662         off = DFORM_SI(insn[1]);
663         return STUB_TOC_BRANCH;
664     }
665 #endif
666
667     off = 0;
668     return STUB_UNKNOWN;
669 }
670
671 bool IA_IAPI::isLinkerStub() const
672 {
673     if (validLinkerStubState)
674         return cachedLinkerStubState;
675
676     if (!validCFT)
677         return false;
678
679     if (!isCall()) {
680         cachedLinkerStubState = false;
681         validLinkerStubState = true;
682         return cachedLinkerStubState;
683     }
684
685     void *insn_buf = _isrc->getPtrToInstruction(cachedCFT);
686     if (!insn_buf)
687         return false;
688
689     Offset off;
690     linker_stub_t stub_type = checkLinkerStub(insn_buf, off);
691
692     switch (stub_type) {
693       case STUB_UNKNOWN:
694         // It's not a linker stub (that we know of).  Allow processing to
695         // continue unmodified, probably leading to the eventual creation
696         // of a targXXXXX function.
697         break;
698
699       case STUB_LONG_BRANCH:
700         cachedCFT += off;
701         break;
702
703       case STUB_TOC_BRANCH:
704         cachedCFT += off;
705         assert(0 && "STUB_TOC_BRANCH not implemented yet.");
706
707         // Although tempting, we cannot just read the word directly from the
708         // mutatee, and find the symbol that matches.  There may be no
709         // child process to read from.
710         //
711         // In theory, we can use the relocations to determine the final
712         // address/symbol.  But, I can't get binutils to actually generate
713         // this kind of stub.  Let's deal with this once we find a binary
714         // that uses it.
715         break;
716
717       case STUB_PLT_CALL:
718         cachedCFT = _obj->cs()->getTOC(current) + off;
719         break;
720     }
721
722     cachedLinkerStubState = (stub_type != STUB_UNKNOWN);
723     validLinkerStubState = true;
724
725     return cachedLinkerStubState;
726 }
727
728 AST::Ptr PPC_BLR_Visitor::visit(AST *a) {
729   return a->ptr(); 
730 }
731
732 AST::Ptr PPC_BLR_Visitor::visit(DataflowAPI::BottomAST *b) {
733   return_ = PPC_BLR_UNKNOWN;
734   return b->ptr();
735 }
736
737 AST::Ptr PPC_BLR_Visitor::visit(DataflowAPI::ConstantAST *c) {
738   // Very odd case, but claiming not a return
739   return_ = PPC_BLR_NOTRETURN;
740   return c->ptr();
741 }
742
743 AST::Ptr PPC_BLR_Visitor::visit(DataflowAPI::VariableAST *v) {
744   if ((v->val().reg == AbsRegion(ppc32::lr)) &&
745       (v->val().addr == ret_)) {
746     return_ = PPC_BLR_RETURN;
747   }
748   // Check the stack
749   else if ((v->val().reg.type() == Absloc::Unknown) &&
750       (v->val().reg.absloc().type() == Absloc::Stack) &&
751       (v->val().reg.absloc().off() == 4)) {
752     // FIXME WORDSIZE
753     return_ = PPC_BLR_RETURN;
754   }
755   else {
756     return_ = PPC_BLR_UNKNOWN;
757   }
758   return v->ptr();
759 }
760 /*
761 AST::Ptr PPC_BLR_Visitor::visit(StackAST *s) {
762   return_ = UNKNOWN;
763   return s->Ptr();
764 }
765 */
766 AST::Ptr PPC_BLR_Visitor::visit(DataflowAPI::RoseAST *r) {
767   if (return_ != PPC_BLR_UNSET) {
768     return r->ptr();
769   }
770
771   switch(r->val().op) {
772   case DataflowAPI::ROSEOperation::andOp: {
773     assert(r->numChildren() == 2);
774     if (r->child(1)->getID() != AST::V_ConstantAST) {
775       return_ = PPC_BLR_UNKNOWN;
776       return r->ptr();
777     }
778     DataflowAPI::ConstantAST::Ptr mask = DataflowAPI::ConstantAST::convert(r->child(1));
779     if (mask->val().val != 0xfffffffc) {
780       return_ = PPC_BLR_UNKNOWN;
781       return r->ptr();
782     }
783
784     r->child(0)->accept(this);
785     break;
786   }
787   default:
788     return_ = PPC_BLR_UNKNOWN;
789     break;
790   }
791   return r->ptr();
792 }
793       
794
795  
796 ParseAPI::StackTamper
797 IA_IAPI::tampersStack(ParseAPI::Function *, Address &) const
798 {
799     return TAMPER_NONE;
800 }