Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / image-sparc.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 // $Id: image-sparc.C,v 1.20 2008/06/19 19:53:20 legendre Exp $
34
35 #include "common/h/Vector.h"
36 #include "common/h/Dictionary.h"
37 #include "common/h/Vector.h"
38 #include "image-func.h"
39 #include "instPoint.h"
40 #include "symtab.h"
41 #include "dyninstAPI/h/BPatch_Set.h"
42 #include "InstrucIter.h"
43 #include "IA_InstrucIter.h"
44 #include "debug.h"
45 #include "arch.h"
46 #include "inst-sparc.h" // REG_? should be in arch-sparc, but isn't
47
48 /****************************************************************************/
49 /****************************************************************************/
50 /****************************************************************************/
51
52
53 static inline bool CallRestoreTC(instruction instr, instruction nexti) {
54     return (instr.isCall() && nexti.isRestore());
55 }
56
57 /****************************************************************************/
58 /****************************************************************************/
59
60 static inline bool MovCallMovTC(instruction instr, instruction nexti) {
61     return (instr.isCall() && nexti.isMovToO7());
62 }
63
64 /****************************************************************************/
65 /****************************************************************************/
66
67
68 /*
69     Return bool value indicating whether instruction sequence
70      found signals tail-call jmp; nop; sequence.  Note that this should 
71      NOT include jmpl; nop;, ret; nop;, retl; nop;....
72
73     Current heuristic to detect such sequences :
74      look for jmp %reg, nop in function w/ no stack frame, if jmp, nop
75      are last 2 instructions, return true (definate TC), at any other point,
76      return false (not TC).  Otherwise, return false (no TC).
77      w/ no stack frame....
78     instr is instruction being examioned.
79     nexti is instruction after
80     addr is address of <instr>
81     func is pointer to function class object describing function
82      instructions come from....
83  */
84 static inline bool JmpNopTC(instruction instr, instruction nexti,
85                             Address addr, image_func *func) {
86
87     if (!instr.isInsnType(JMPLmask, JMPLmatch)) {
88         return 0;
89     }
90     
91     assert((*instr).resti.op3 == 0x38);
92     
93     // only looking for jump instructions which don't overwrite a register
94     //  with the PC which the jump comes from (g0 is hardwired to 0, so a write
95     //  there has no effect?)....  
96     //  instr should have gdb disass syntax : 
97     //      jmp  %reg, 
98     //  NOT jmpl %reg1, %reg2
99     if ((*instr).resti.rd != REG_G(0)) {
100         return 0;
101     }
102
103     // only looking for jump instructions in which the destination is
104     //  NOT %i7 + 8/12/16 or %o7 + 8/12/16 (ret and retl synthetic 
105     //  instructions, respectively)
106     if ((*instr).resti.i == 1) {
107         if ((*instr).resti.rs1 == REG_I(7) || (*instr).resti.rs1 == REG_O(7)) {
108             // NOTE : some return and retl instructions jump to {io}7 + 12,
109             //  or (io)7 + 16, not + 8, to have some extra space to store the size of a 
110             //  return structure....
111             if ((*instr).resti.simm13 == 0x8 || (*instr).resti.simm13 == 12 ||
112                     (*instr).resti.simm13 == 16) {
113                 return 0;
114             }
115         }
116     }  
117
118     // jmp, foloowed by NOP....
119     if (!nexti.isNop()) {
120         return 0;
121     }
122
123     // in function w/o stack frame....
124     if (!func->hasNoStackFrame()) {
125         return 0;
126     }
127     
128     // if sequence is detected, but not at end of fn 
129     //  (last 2 instructions....), return value indicating possible TC.
130     //  This should (eventually) mark the fn as uninstrumenatble....
131     if (addr != (func->getEndOffset() - 2*instruction::size())) {
132         return 0;
133     }
134     
135     return 1;
136 }
137 bool image_func::archIsRealCall(InstrucIter &ah, bool &validTarget,
138                                 bool &simulateJump)
139 {
140   simulateJump = false;
141   validTarget = true;
142     if(!ah.isADynamicCallInstruction())
143     {
144         Address callTarget = ah.getBranchTargetAddress();
145         if (callTarget == 0) {
146             // Call to self; skip
147             return false;
148         }
149
150         if(!img()->isValidAddress(callTarget))
151         {
152             validTarget = false;
153             return false;
154         }
155
156         // We have the annoying "call to return" combo like
157         // on x86. Those aren't calls, and we handle them
158         // in instrumentation
159
160         // Grab the insn at target
161         codeBuf_t *target = (codeBuf_t *)img()->getPtrToInstruction(callTarget);
162         instruction callTargetInsn;
163         callTargetInsn.setInstruction(target);
164
165         if (((*callTargetInsn).raw & 0xfffff000) == 0x81c3e000)
166         {
167             parsing_printf("Skipping call to retl at 0x%x, func %s\n",
168                             *ah, symTabName().c_str());
169             return false;
170         }
171
172         // We also have "get-my-pc" combos, which we also handle in
173         // instrumentation. These may be offset by 8 or 12 bytes from   
174         // the call, in one of these forms:
175         //
176         //  call, nop, <target>
177         // or
178         //  call, nop, unimpl, <target>
179
180         if(callTarget == *ah + 2*instruction::size() ||
181            callTarget == *ah + 3*instruction::size())
182         {
183             parsing_printf("Skipping \"get-my-pc\" combo at 0x%x\n", *ah);
184             // tell the parser to treat this call as an indirect jump
185             simulateJump = true;
186             return false;
187         }
188     }
189
190     return true;
191 }                                
192                                  
193 bool image_func::archCheckEntry( InstrucIter &ah, image_func * /* func */ )                                    
194 {                                                              
195     return ah.getInstruction().valid();
196 }
197
198 bool image_func::archIsUnparseable()
199 {
200     // And here we have hackage. Our jumptable code is b0rken, but I don't know
201     // how to fix it. So we define anything that doesn't work as... argh.
202     // Better: a size limit on a jump table.
203     if (symTabName().c_str() == "__rtboot") {
204         return true;
205     }
206
207     return false;
208 }
209
210 bool image_func::archAvoidParsing()
211 {
212     return false;
213 }
214
215
216 bool image_func::archNoRelocate()
217 {
218     return false;
219 }
220
221 void image_func::archSetFrameSize(int /* frameSize */)
222 {
223     return;
224 }
225
226 // As Drew has noted, this really, really should not be an InstructIter
227 // operation. The extraneous arguments support architectures like x86,
228 // which (rightly) treat jump table processing as a control-sensitive
229 // data flow operation.
230 bool image_func::archGetMultipleJumpTargets(
231                                 BPatch_Set< Address >& targets,
232                                 image_basicBlock * /* currBlk */,
233                                 InstrucIter &ah,
234                                 pdvector< instruction >& /* allInstructions */)
235 {
236     return ah.getMultipleJumpTargets( targets );
237 }
238
239
240 // XXX We are currently not doing anything special on SPARC with regards
241 // to tail calls. Function relocation currently does not do any unwinding
242 // of tail calls, so this is not terribly important. However, the whole
243 // notion of what a tail call is at the parsing level and where it should
244 // be handled with regards to instrumentation needs to be revisited.
245 //
246 // Currently, this function returns false regardless of whether the
247 // instruction matches our tail call heuristics.
248 bool image_func::archIsATailCall(InstrucIter &ah,
249                                  pdvector< instruction >& /* allInstructions */)
250 {
251   instruction current = ah.getInstruction();
252   InstrucIter tmp(ah);
253   tmp++;
254   instruction next = tmp.getInstruction();
255     if( CallRestoreTC(current, next) ||
256         JmpNopTC(current, next, *ah, this) ||  
257         MovCallMovTC(current, next)) 
258     {
259         parsing_printf("ERROR: tail call (?) not handled in func %s at 0x%x\n",
260                        symTabName().c_str(), *ah);
261         return false;
262     }
263     else
264         return false;
265 }
266
267 // not implemented?
268 bool image_func::archIsIndirectTailCall(InstrucIter & /* ah */)
269 {
270     return false;
271 }
272
273
274 void image_func::archInstructionProc(InstructionAdapter &ah_base)
275 {
276     // Check whether "07" is live, AKA we can't call safely.
277     // Could we just always assume this?
278     if (!o7_live) {
279        
280 #if 0
281         InsnRegister reads[7];
282         InsnRegister writes[7];
283
284         ah.getInstruction().get_register_operands(reads, writes);
285         int i;
286         for(i=0; i<7; i++) {
287           if (reads[i].is_o7()) {
288             o7_live = true;
289             break;
290           }
291         }
292 #endif
293         IA_InstrucIter& ah = dynamic_cast<IA_InstrucIter&>(ah_base);
294         instruction insn = ah.getInstruction();
295         insn.get_register_operands();
296         std::vector<InsnRegister> *read_regs_p  = NULL;
297         extern AnnotationClass<std::vector<InsnRegister> > RegisterReadSetAnno;
298         if (!insn.getAnnotation(read_regs_p, RegisterReadSetAnno))
299         {
300            return;
301         }
302         assert(read_regs_p);
303         std::vector<InsnRegister> &read_regs = *read_regs_p;
304 #if 0
305         Annotatable<InsnRegister, register_read_set_a> &read_regs = insn;
306 #endif
307         assert(read_regs.size() < 9);
308
309         for (unsigned int i = 0; i < read_regs.size(); ++i) {
310            if (read_regs[i].is_o7()) {
311               o7_live = true;
312               break;
313            }
314         }
315
316         if(o7_live) {     
317             parsing_printf("Setting o7 to live at 0x%x, func %s\n",
318                     ah.getAddr(), symTabName().c_str());
319         }
320     }
321 }
322
323 bool image_func::archProcExceptionBlock(Address & /* catchStart */, 
324                                         Address /* a */)
325 {
326     return false;
327 }
328
329
330 std::string image_func::calcParentFunc(const image_func * imf, pdvector<image_parRegion *> & pR)
331 {
332   /* We need to figure out the function that called the outlined
333      parallel region function.  
334
335      We do this by chopping off the "_$<identifier>." prefix
336   */
337
338   const char * nameStart = imf->prettyName().c_str();
339   char * newNameStart = strrchr(nameStart, '.');
340   newNameStart++;
341   
342   const char * nameEnd = nameStart + strlen(nameStart);
343   
344   int strSize = nameEnd - newNameStart;
345   char tempBuf[strSize + 1];
346   strncpy(tempBuf, newNameStart, strSize);
347   tempBuf[strSize] = '\0';
348
349
350   /* These two regions have associated functions that have the _$p beginning */
351   if (strstr(imf->prettyName().c_str(),"_$s") != NULL ||
352       strstr(imf->prettyName().c_str(),"_$d") != NULL )
353     {
354       /* We need to find the associated function */
355
356       for (unsigned i = 0; i < pR.size(); i++)
357         {
358           image_parRegion * tempParReg = pR[i];
359           image_func * imf = tempParReg->getAssociatedFunc();
360
361           const char * nameStart2 = imf->prettyName().c_str();
362           
363                   
364           if (strstr(nameStart2,tempBuf) != NULL &&
365               strstr(nameStart2, "_$p") != NULL)
366             {
367               char * endPtr = strstr(nameStart2, tempBuf);
368               int strSize2 = endPtr - nameStart2;
369               int totalStrSize = strSize2 + strlen(tempBuf);
370               char tempBuf2[totalStrSize + 1];
371               strncpy(tempBuf2, nameStart2, strSize2);
372               strncpy(tempBuf2 + strSize2, tempBuf,sizeof(tempBuf));
373               tempBuf2[totalStrSize] = '\0';
374              
375               std::string tempPDS(tempBuf2);
376               return tempPDS;
377             }
378         }
379       std::string tempPDS(tempBuf);
380       return tempPDS;
381     }
382   else if (strstr(imf->prettyName().c_str(),"_$p") != NULL)
383     {
384       std::string tempPDS(tempBuf);
385       return tempPDS;
386     }
387   else
388     {
389       return NULL;
390     }
391 }
392
393 void image_func::parseOMP(image_parRegion * parReg, image_func * parentFunc, int & currentSectionNum)
394 {
395   /* Parsing section functions */
396   if (strstr(symTabName().c_str(),"_$s")!=NULL)
397     {
398       parseOMPSectFunc(parentFunc);
399       parseOMPFunc(false);
400       parentFunc->parseOMPParent(parReg, 0, currentSectionNum);
401     }
402   /* Parsing workshare functions */
403   else if (strstr(symTabName().c_str(),"_$d")!=NULL)
404     {
405       parseOMPFunc(true);
406       parentFunc->parseOMPParent(parReg, 0, currentSectionNum);
407     }
408   /* Parsing parallel regions */
409   else if (strstr(symTabName().c_str(),"_$p") !=NULL)
410     {
411       parseOMPFunc(false);
412       parentFunc->parseOMPParent(parReg, 0, currentSectionNum);
413     }
414   parReg->setLastInsn(get_address() + get_size());
415 }
416
417 // This parses the parent functions that generated outlined do/for, parallel constructs */
418 bool image_func::parseOMPParent(image_parRegion * iPar, 
419                                 int /*desiredNum*/, int & /*currentSectionNum*/)
420 {
421    Address funcBegin = getOffset();
422    InstrucIter ah(funcBegin, this);
423
424    bool isDoFor = false;
425    while (ah.hasMore())
426    {
427
428       if( ah.isAOMPDoFor() ) /* Record param values */
429       {
430          isDoFor = true;
431       }
432       if( ah.isACallInstruction() ||
433             ah.isADynamicCallInstruction() )
434       {
435          bool isAbsolute = false;
436          Address target = ah.getBranchTargetAddress(&isAbsolute);
437
438
439          /* Finding Out if the call is to OpenMP Functions */
440
441          /* Return one of the following 
442             OMP_PARALLEL, OMP_DO_FOR, OMP_SECTIONS, OMP_SINGLE, 
443             OMP_PAR_DO, OMP_PAR_SECTIONS, OMP_MASTER, OMP_CRITICAL,
444             OMP_BARRIER, OMP_ATOMIC, OMP_FLUSH, OMP_ORDERED */
445          image * im = img();
446          image_func *ppdf = im->findFuncByEntry(target);
447          if (ppdf != NULL)
448          {
449
450             if (strstr(ppdf->symTabName().c_str(),"__mt_MasterFunction")!=NULL)
451             {
452                if (isDoFor)
453                {
454                   iPar->setRegionType(OMP_PAR_DO);
455                   iPar->setParentFunc(this);
456                   parRegionsList.push_back(iPar);
457                }
458                else
459                {
460                   iPar->setRegionType(OMP_PARALLEL);
461                   iPar->setParentFunc(this);
462                   parRegionsList.push_back(iPar);
463                }
464                return false;
465             }
466             else if(strstr(ppdf->symTabName().c_str(),"__mt_WorkSharing_")!=NULL)
467             {
468                if (isDoFor)
469                {
470                   iPar->setRegionType(OMP_DO_FOR);
471                   iPar->setParentFunc(this);
472                   parRegionsList.push_back(iPar);
473                   //return;
474                }
475                return true;
476             }
477          }
478       }
479       ah++;
480    }
481    return true;
482 }
483
484 // Parses through all the inlined sections within one outlined function for entire section construct
485
486 void image_func::parseOMPSectFunc(image_func * parentFunc)
487 {
488    Address funcBegin = getOffset();
489    InstrucIter ah(funcBegin, this);
490
491    Address sectBegin = funcBegin;
492    bool inSection = false;
493
494    while (ah.hasMore())
495    {
496       if (ah.isACondBranchInstruction())
497       {
498          if (inSection == false)
499             sectBegin = ah.getCurrentAddress();
500          inSection = true;
501       }
502       if (ah.isAReturnInstruction())
503       {
504          image_parRegion * iPar = new image_parRegion(sectBegin,this);
505          iPar->setRegionType(OMP_SECTIONS);
506
507          iPar->setParentFunc(parentFunc); 
508          iPar->setLastInsn(ah.getCurrentAddress()); 
509          parRegionsList.push_back(iPar);
510          sectBegin = ah.getCurrentAddress() + 0x8;
511       }      
512       ah++;
513    }
514 }
515
516 void image_func::parseOMPFunc(bool hasLoop)
517 {
518    if (OMPparsed_)
519       return;
520    OMPparsed_ = true;
521
522    /* We parse the parent to get info if we are in an outlined function, but there can be some
523       inlined functions we might miss out on if we don't check those out too */
524    Address funcBegin = getOffset();
525    InstrucIter ah(funcBegin, this);
526
527    while (ah.hasMore())
528    {
529       if ( hasLoop && ah.isACondBLEInstruction() )
530       {
531          if (ah.getBranchTargetAddress() < ah.getCurrentAddress())
532          {
533             image_parRegion * iPar = new image_parRegion(ah.getBranchTargetAddress()+4, this);                          
534             iPar->setRegionType(OMP_DO_FOR_LOOP_BODY);
535             iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
536             iPar->setLastInsn(ah.getCurrentAddress());
537             parRegionsList.push_back(iPar);
538          }
539       }
540       else if( ah.isACallInstruction() ||
541             ah.isADynamicCallInstruction() )
542       {
543          bool isAbsolute = false;
544          Address target = ah.getBranchTargetAddress(&isAbsolute);
545
546
547          /* Finding Out if the call is to OpenMP Functions */
548
549          /* Return one of the following 
550             OMP_PARALLEL, OMP_DO_FOR, OMP_SECTIONS, OMP_SINGLE, 
551             OMP_PAR_DO, OMP_PAR_SECTIONS, OMP_MASTER, OMP_CRITICAL,
552             OMP_BARRIER, OMP_ATOMIC, OMP_FLUSH, OMP_ORDERED */
553          image * im = img();
554          image_func *ppdf = im->findFuncByEntry(target);
555          if (ppdf != NULL)
556          {
557             if (strstr(ppdf->symTabName().c_str(),"__mt_")!=NULL)
558             {
559                /* Section consists of only one instruction, call to "_xlsmpBarrier_TPO" */
560                if(strstr(ppdf->symTabName().c_str(), "barrier")!=NULL)
561                {
562                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
563                   iPar->setRegionType(OMP_BARRIER);
564
565                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
566                   iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
567
568                   parRegionsList.push_back(iPar);
569                }
570                /* Section begins with "BeginOrdered, ends with EndOrdered" */
571                else if(strstr(ppdf->symTabName().c_str(), "begin_ordered") !=NULL)
572                {
573                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
574                   iPar->setRegionType(OMP_ORDERED);
575
576                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
577
578                   InstrucIter ah2(ah.getCurrentAddress(), this);
579                   while (ah2.hasMore())
580                   {
581                      if( ah2.isACallInstruction() ||
582                            ah2.isADynamicCallInstruction() )
583                      {
584                         Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
585
586                         image_func *ppdf2 = im->findFuncByEntry(target2);
587                         if (ppdf2 != NULL)
588                         {
589                            if(strstr(ppdf2->symTabName().c_str(), "end_ordered") !=NULL)
590                               break;
591                         }
592                      }
593                      ah2++;
594                   }
595                   iPar->setLastInsn(ah2.getCurrentAddress());
596
597                   parRegionsList.push_back(iPar);
598                }
599                /* Section begins with "single_begin, ends with single_end" */
600                else if(strstr(ppdf->symTabName().c_str(), "single_begin") !=NULL)
601                {
602                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
603                   iPar->setRegionType(OMP_SINGLE);
604
605                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
606
607                   InstrucIter ah2(ah.getCurrentAddress(), this);
608                   while (ah2.hasMore())
609                   {
610                      if( ah2.isACallInstruction() ||
611                            ah2.isADynamicCallInstruction() )
612                      {
613                         Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
614
615                         image_func *ppdf2 = im->findFuncByEntry(target2);
616                         if (ppdf2 != NULL)
617                         {
618                            if(strstr(ppdf2->symTabName().c_str(), "single_end") !=NULL)
619                               break;
620                         }
621                      }
622                      ah2++;
623                   }
624                   iPar->setLastInsn(ah2.getCurrentAddress());
625
626                   parRegionsList.push_back(iPar);
627                }
628                /* Section is precursored by a call to mt_get_thread_num followed by a nop, 
629                   then a test on that thread number, followed by a bne
630                   the instruction after the branch is the first instruction, the 
631                   branch destination is the end of the section */
632                else if(strstr(ppdf->symTabName().c_str(), "get_thread_num") !=NULL)
633                {
634                   InstrucIter ah2(ah.getCurrentAddress(), this);
635
636                   /* This should put us at the nop */
637                   ah2++;
638
639                   /* This should put us at the tst instruction */
640                   ah2++;
641                   if (ah2.isTstInsn())
642                   {
643
644                      ah2++;
645                      /* Now we should be at the branch, and we know this is a Master section */
646
647                      if (ah2.isACondBranchInstruction())
648                      {
649                         image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
650                         iPar->setRegionType(OMP_MASTER);
651
652                         iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
653
654                         bool xx = true; // I don't really think the function uses this
655                         iPar->setLastInsn(ah2.getBranchTargetAddress(&xx));
656
657                         parRegionsList.push_back(iPar);
658
659                      }
660                   }
661
662                }                      
663
664                else if(strstr(ppdf->symTabName().c_str(), "flush") !=NULL)
665                {
666                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
667                   iPar->setRegionType(OMP_FLUSH);
668
669                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
670                   iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
671
672                   parRegionsList.push_back(iPar);
673                }
674                /* Starts with BeginCritSect, ends with EndCritSect */
675                else if(strstr(ppdf->symTabName().c_str(), "BeginCritSect") != NULL)
676                {
677                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
678                   iPar->setRegionType(OMP_CRITICAL);
679
680                   InstrucIter ah2(ah.getCurrentAddress(), this);
681                   while (ah2.hasMore())
682                   {
683                      if( ah2.isACallInstruction() ||
684                            ah2.isADynamicCallInstruction() )
685                      {
686                         Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
687
688                         image_func *ppdf2 = im->findFuncByEntry(target2);
689                         if (ppdf2 != NULL)
690                         {
691                            if(strstr(ppdf2->symTabName().c_str(), "EndCritSect") !=NULL)
692                               break;
693                         }
694                      }
695                      ah2++;
696                   }
697                   iPar->setLastInsn(ah2.getCurrentAddress());
698
699                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
700
701                   parRegionsList.push_back(iPar);
702                }
703                /* Begins with b_atomic, ends with e_atomic */
704                else if(strstr(ppdf->symTabName().c_str(), "b_atomic") != NULL)
705                {
706                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
707                   iPar->setRegionType(OMP_ATOMIC);
708
709                   InstrucIter ah2(ah.getCurrentAddress(), this);
710                   while (ah2.hasMore())
711                   {
712                      if( ah2.isACallInstruction() ||
713                            ah2.isADynamicCallInstruction() )
714                      {
715                         Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
716
717                         image_func *ppdf2 = im->findFuncByEntry(target2);
718                         if (ppdf2 != NULL)
719                         {
720                            if(strstr(ppdf2->symTabName().c_str(), "e_atomic") !=NULL)
721                               break;
722                         }
723                      }
724                      ah2++;
725                   }
726                   iPar->setLastInsn(ah2.getCurrentAddress());
727
728                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
729                   iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
730
731                   parRegionsList.push_back(iPar);
732                }
733                else
734                {
735                }/* End Checking Different Directive Types */
736
737             }
738          }
739       }
740       ah++;
741    }
742 }
743
744 bool image_func::archIsIPRelativeBranch(InstrucIter& ah)
745 {
746   return false;
747 }