Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / image-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 // $Id: image-power.C,v 1.23 2008/03/12 20:09:10 legendre Exp $
33
34 // Determine if the called function is a "library" function or a "user" function
35 // This cannot be done until all of the functions have been seen, verified, and
36 // classified
37 //
38
39 #include "common/h/Vector.h"
40 #include "common/h/Dictionary.h"
41 #include "common/h/Vector.h"
42 #include "image-func.h"
43 #include "instPoint.h"
44 #include "symtab.h"
45 #include "parRegion.h"
46 #include "dyninstAPI/h/BPatch_Set.h"
47 #include "InstrucIter.h"
48 #include "debug.h"
49 #include "arch.h"
50
51 bool image_func::archIsRealCall(InstrucIter &ah,
52                 bool &validTarget,
53                 bool & /*simulateJump*/)
54 {   
55     Address callTarget;
56
57     if(ah.isADynamicCallInstruction())
58         return true;
59
60     callTarget = ah.getBranchTargetAddress();
61     validTarget = img()->isValidAddress( callTarget );
62     return validTarget;
63 }
64
65 bool image_func::archCheckEntry(InstrucIter &ah, image_func * /* func */)
66 {   
67     // XXX Cheating a little -- this has nothing to do with the
68     // "check entry" as seen on x86 & sparc, but is just a convenient place
69     // to put this code.
70
71     parsing_printf("calling archCheckEntry for 0x%lx, function %s\n", *ah, symTabName().c_str());
72
73     if (ah.isReturnValueSave())
74         makesNoCalls_ = false;
75     else
76         makesNoCalls_ = true;
77
78     // end cheating
79
80     if (!ah.getInstruction().valid()) return false;
81
82     // We see if we're a procedure linkage table; if so, we are _not_
83     // a function (and return false)
84
85     // We don't consider linkage snippets "functions". 
86     dictionary_hash<Address, std::string> *pltFuncs = img()->getPltFuncs();
87     if (pltFuncs && pltFuncs->defines(*ah)) {
88         return false;
89     }
90     /*
91     Address dontcare1;
92     if (ah.isInterModuleCallSnippet(dontcare1))
93       {
94         return false;
95       }
96     */
97     return true;
98 }
99
100 // Not used on power
101 bool image_func::archIsUnparseable()
102 {   
103     return false;
104 }
105
106 // Not used on power
107 bool image_func::archAvoidParsing()
108 {   
109     return false;
110 }
111
112 // Not used on power
113 bool image_func::archNoRelocate()
114 {   
115     return false;
116 }
117
118 // Not used on power
119 void image_func::archSetFrameSize(int /* fsize */)                  
120 {
121     return;
122 }
123
124 // As Drew has noted, this really, really should not be an InstructIter
125 // operation. The extraneous arguments support architectures like x86,
126 // which (rightly) treat jump table processing as a control-sensitive
127 // data flow operation.
128 bool image_func::archGetMultipleJumpTargets(
129                                 BPatch_Set< Address >& targets,
130                                 image_basicBlock * /* currBlk */,
131                                 InstrucIter &ah,
132                                 pdvector< instruction >& /* allInstructions */)
133 {   
134     return ah.getMultipleJumpTargets( targets );
135 }
136
137 // not implemented on power
138 bool image_func::archProcExceptionBlock(Address & /* catchStart */, Address /* a */)
139 {   
140     // Agnostic about exception blocks; the policy of champions
141     return false;
142 }
143
144 // not implemented on power
145 bool image_func::archIsATailCall(InstrucIter & /* ah */,
146                                  pdvector< instruction >& /* allInstructions */)
147 {   
148     return false;
149 }
150
151 // not implemented on power
152 bool image_func::archIsIndirectTailCall(InstrucIter & /* ah */)
153 {   
154     return false;
155 }
156
157
158 // not implemented on power
159 void image_func::archInstructionProc(InstructionAdapter & /* ah */)
160 {
161     return;
162 }
163
164 /*
165 By parsing the function that actually sets up the parameters for the OMP
166 region we discover informations such as what type of parallel region we're
167 dealing with */
168 bool image_func::parseOMPParent(image_parRegion * iPar, int desiredNum, int & currentSectionNum )
169 {
170    Address funcBegin = getOffset();
171    InstrucIter ah(funcBegin, this);
172    InstrucIter callFind(funcBegin, this);
173    int currentNum = 0;
174    int regValues[10 + 1];  /* Only care about registers 3-10 (params) */
175    Address regWriteLocations[10 + 1];
176
177    for (int i = 0; i < 11; i++)
178       regValues[i] = -1;
179   
180   
181    const char * regionFuncName = iPar->getAssociatedFunc()->symTabName().c_str();
182
183    while (callFind.hasMore())
184    {
185       if( callFind.isACallInstruction() ||
186           callFind.isADynamicCallInstruction() )
187       {
188          bool isAbsolute = false;
189          Address target = callFind.getBranchTargetAddress(&isAbsolute);
190          image * im = img();
191
192          image_func *ppdf = im->findFuncByEntry(target);
193
194          if (ppdf != NULL)
195          {
196             if (strstr(ppdf->symTabName().c_str(),regionFuncName)!=NULL)
197                return 0;
198          }
199       }
200       callFind++;
201    }
202
203    while (ah.hasMore())
204    {
205       if( ah.isRegConstantAssignment(regValues, regWriteLocations) ) /* Record param values */
206       { }
207       else if( ah.isACallInstruction() ||
208                ah.isADynamicCallInstruction() )
209       {
210           
211          // XXX move this out of archIsRealCall protection... safe?
212          bool isAbsolute = false;
213          Address target = ah.getBranchTargetAddress(&isAbsolute);
214           
215           
216          /* Finding Out if the call is to OpenMP Functions */
217           
218          /* Return one of the following 
219             OMP_PARALLEL, OMP_DO_FOR, OMP_SECTIONS, OMP_SINGLE, 
220             OMP_PAR_DO, OMP_PAR_SECTIONS, OMP_MASTER, OMP_CRITICAL,
221             OMP_BARRIER, OMP_ATOMIC, OMP_FLUSH, OMP_ORDERED */
222          image * im = img();
223          image_func *ppdf = im->findFuncByEntry(target);
224           
225          if (ppdf != NULL)
226          {
227             if (strstr(ppdf->symTabName().c_str(),"_TPO_linkage")!=NULL
228                 && ( strstr(ppdf->symTabName().c_str(), "ParRegionSetup")!= NULL
229                      || strstr(ppdf->symTabName().c_str(), "WSDoSetup")     != NULL
230                      || strstr(ppdf->symTabName().c_str(), "WSSectSetup")   != NULL
231                      || strstr(ppdf->symTabName().c_str(), "SingleSetup")   != NULL                
232                      || strstr(ppdf->symTabName().c_str(), "ParallelDoSetup")!=NULL             
233                      || strstr(ppdf->symTabName().c_str(), "WSSectSetup")   != NULL))               
234             {
235
236                if (currentNum != desiredNum)
237                   currentNum++;
238                else
239                {
240                   /* Standard outlined function */
241                   if (strstr(ppdf->symTabName().c_str(), "ParRegionSetup")!=NULL)
242                      iPar->setRegionType(OMP_PARALLEL);
243                       
244                   /* Standard outlined function */
245                   else if(strstr(ppdf->symTabName().c_str(), "WSDoSetup")!=NULL)
246                   {                     
247                      iPar->setRegionType(OMP_DO_FOR);
248                      iPar->setClause("NUM_ITERATIONS",regValues[6]); 
249                      iPar->setClause("SCHEDULE",regValues[7]);
250                      iPar->setClause("CHUNK_SIZE", regValues[8]);
251                      iPar->setClauseLoc("CHUNK_SIZE", regWriteLocations[8]);
252                      iPar->setClauseLoc("SCHEDULE", regWriteLocations[7]);
253                   }
254                       
255                   /* Standard outlined function */
256                   else if(strstr(ppdf->symTabName().c_str(), "WSSectSetup")!=NULL)
257                   {
258                      iPar->setRegionType(OMP_SECTIONS);
259                      iPar->setClause("NUM_SECTIONS",regValues[5]);
260                           
261                      currentSectionNum++;
262                           
263                      if (currentSectionNum == regValues[5])
264                         currentSectionNum = 0;
265                   }
266                       
267                   /* Standard outlined function */
268                   else if(strstr(ppdf->symTabName().c_str(), "SingleSetup")!=NULL)                  
269                      iPar->setRegionType(OMP_SINGLE);
270                       
271                   /* Standard outlined function */
272                   else if(strstr(ppdf->symTabName().c_str(), "ParallelDoSetup")!=NULL)
273                   {                 
274                      iPar->setRegionType(OMP_PAR_DO);
275                      iPar->setClause("NUM_ITERATIONS",regValues[6]); 
276                      iPar->setClause("SCHEDULE",regValues[7]);
277                      iPar->setClause("CHUNK_SIZE", regValues[8]);
278                      iPar->setClauseLoc("CHUNK_SIZE", regWriteLocations[8]);
279                      iPar->setClauseLoc("SCHEDULE", regWriteLocations[7]);
280                   }
281                   /* Standard outlined function */
282                   else if(strstr(ppdf->symTabName().c_str(), "WSSectSetup")!=NULL)                  
283                      iPar->setRegionType(OMP_PAR_SECTIONS);
284                   else                
285                   {
286                      ah++;
287                      continue;
288                           
289                   }/* End Checking Different Directive Types */
290
291                   iPar->decodeClauses(regValues[3]);
292                   iPar->setParentFunc(this);
293
294                   parRegionsList.push_back(iPar);
295
296                   if (iPar->getRegionType() == OMP_DO_FOR || 
297                       iPar->getRegionType() == OMP_PAR_DO)
298                      return true;
299                   else
300                      return false;
301                     
302                }                
303             } 
304          } 
305       }
306       ah++;
307    }
308    return true;
309 }
310
311
312
313         
314 std::string image_func::calcParentFunc(const image_func * imf,
315                                     pdvector<image_parRegion *> &/*pR*/)
316 {
317   /* We need to figure out the function that called the outlined
318      parallel region function.  We do this by chopping off the
319      last @OL@number */
320    const char * nameStart = imf->prettyName().c_str();
321    char * nameEnd = strrchr(nameStart, '@');
322    int strSize = nameEnd - nameStart - 3;
323    
324    /* Make sure that the shortened string is not of size 0,
325       this would happen if a function started with @ or if there
326       was less than two characters between the beginning and @
327       This wouldn't happen for OpenMP functions, but might for imposters*/
328    if (strSize > 0)
329    {
330       char tempBuf[strlen(nameStart)];
331       strncpy(tempBuf, nameStart, strSize);
332       tempBuf[strSize] = '\0';
333       std::string tempPDS(tempBuf);
334       return tempPDS;
335    }
336    else   /* if it starts with @ just return the full function as its parent, we'll sort it out later */
337    {
338       std::string tempPDS(nameStart);
339       return tempPDS;
340    }
341 }
342
343
344 void image_func::parseOMP(image_parRegion * parReg, image_func * parentFunc, int & currentSectionNum)
345 {  
346   /* Each region is contained in a function, for the worksharing constructs
347      usually the parralel region encompasses the entire function 
348      The "desiredNum" variable is the desired construct we want to "skip" to
349      when we parse the parent function, which we do whenever we encounter
350      a new outlined function */
351   
352    int desiredNum = 0;
353        
354   /* This will fill in the directive type and all possible clauses 
355      Multiple section numbers can occur with only one call to a section setup
356      function in the parent function, so we need to always offset the desired 
357      region we are looking for with the current section number we are on*/
358       
359    int lastSecSize = 0;  // the number of sections in the most recent sections construct  
360    int totalSectionGroups = 0; // the number of sections constructs encountered (in source), 
361                                // not the number of total sections
362
363
364   /* First, we increment the desired num for each region we've already
365      parsed from the parent function.  A parent function can spawn multiple
366      outlined functions, so we don't want to mix up already parsed ones */
367    for(unsigned a = 0; a < parentFunc->parRegions().size();a++)
368    {              
369       image_parRegion * tempReg = parentFunc->parRegions()[a];
370       
371       if (tempReg->getRegionType() == OMP_PARALLEL ||
372           tempReg->getRegionType() == OMP_DO_FOR ||
373           tempReg->getRegionType() == OMP_PAR_DO ||
374           tempReg->getRegionType() == OMP_PAR_SECTIONS ||
375           tempReg->getRegionType() == OMP_SINGLE )
376       {
377          desiredNum++;
378       }
379
380       /* For the sections, we can't just count the number of section constructs
381          we run into, since multiple outlined functions line up to one section construct */
382       if (tempReg->getRegionType() == OMP_SECTIONS)
383       {
384          lastSecSize = tempReg->getClause("NUM_SECTIONS");
385          a += (lastSecSize-1);
386          totalSectionGroups++;
387       }
388    }
389    
390    
391    // if the currentSectionNum is not zero, it means there are still more outlined functions
392    // for a single section construct still out there, so we don't count the current section towards the total
393    if (currentSectionNum != 0)
394    {
395       totalSectionGroups--;
396    }
397    
398    // sets the last instruction of the region
399    parReg->setLastInsn(get_address() + get_size());
400    
401    // we need to parse the parent function to get all the information about the region, mostly for worksharing constructs
402    bool hasLoop = parentFunc->parseOMPParent(parReg, desiredNum + totalSectionGroups, currentSectionNum);           
403    
404    // we parse the outlined function to look for inlined constructs like "Master" and "Ordered"
405    parseOMPFunc(hasLoop);
406 }         
407
408
409 void image_func::parseOMPFunc(bool hasLoop)
410 {
411    if (OMPparsed_)
412       return;
413    OMPparsed_ = true;
414   
415    /* We parse the parent to get info if we are in an outlined function, but there can be some
416       inlined functions we might miss out on if we don't check those out too */
417    Address funcBegin = getOffset();
418    InstrucIter ah(funcBegin, this);
419    int regValues[10 + 1];  /* Only care about registers 3-10 (params) */
420    for (int i = 0; i < 11; i++)
421       regValues[i] = -1;
422   
423   
424    while (ah.hasMore())
425    {
426       if( /*ah.isRegConstantAssignment(regValues)*/ 0 ) /* Record param values */
427       { }
428       // Loop parsing for the Do/For constructs
429       else if( hasLoop && ah.isACondBDZInstruction())
430       {
431          InstrucIter ah2(ah.getCurrentAddress(), this);
432           
433          Address startLoop = ah.getCurrentAddress() + 4;
434           
435          while (ah2.hasMore())
436          {
437             if (ah2.isACondBDNInstruction())
438             {
439                image_parRegion * iPar = new image_parRegion(startLoop,this);
440                iPar->setRegionType(OMP_DO_FOR_LOOP_BODY);
441                iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
442                Address endLoop = ah2.getCurrentAddress();
443                iPar->setLastInsn(endLoop);
444                parRegionsList.push_back(iPar);
445                break;
446             }
447             ah2++;
448          }
449       }
450       // Here we get all the info for the inlined constructs that don't have outlined functions
451       else if( ah.isACallInstruction() ||
452                ah.isADynamicCallInstruction() )
453       {
454          bool isAbsolute = false;
455          Address target = ah.getBranchTargetAddress(&isAbsolute);
456           
457           
458          /* Finding Out if the call is to OpenMP Functions */
459           
460          /* Return one of the following 
461             OMP_PARALLEL, OMP_DO_FOR, OMP_SECTIONS, OMP_SINGLE, 
462             OMP_PAR_DO, OMP_PAR_SECTIONS, OMP_MASTER, OMP_CRITICAL,
463             OMP_BARRIER, OMP_ATOMIC, OMP_FLUSH, OMP_ORDERED */
464          image * im = img();
465          image_func *ppdf = im->findFuncByEntry(target);
466          if (ppdf != NULL)
467          {
468             if (strstr(ppdf->symTabName().c_str(),"_xlsmp")!=NULL)
469             {
470                /* Section consists of only one instruction, call to "_xlsmpBarrier_TPO" */
471                if(strstr(ppdf->symTabName().c_str(), "Barrier")!=NULL)
472                {
473                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
474                   iPar->setRegionType(OMP_BARRIER);
475                       
476                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
477                   iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
478                       
479                   parRegionsList.push_back(iPar);
480                }
481                /* Section begins with "BeginOrdered, ends with EndOrdered" */
482                else if(strstr(ppdf->symTabName().c_str(), "BeginOrdered") !=NULL)
483                {
484                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
485                   iPar->setRegionType(OMP_ORDERED);
486                       
487                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
488                       
489                   InstrucIter ah2(ah.getCurrentAddress(), this);
490                   while (ah2.hasMore())
491                   {
492                      if( ah2.isACallInstruction() ||
493                          ah2.isADynamicCallInstruction() )
494                      {
495                         Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
496                               
497                         image_func *ppdf2 = im->findFuncByEntry(target2);
498                         if (ppdf2 != NULL)
499                         {
500                            if(strstr(ppdf2->symTabName().c_str(), "EndOrdered") !=NULL)
501                               break;
502                         }
503                      }
504                      ah2++;
505                   }
506                   iPar->setLastInsn(ah2.getCurrentAddress());
507                   parRegionsList.push_back(iPar);
508                }
509                /* Master construct */
510                else if(strstr(ppdf->symTabName().c_str(), "Master") !=NULL)
511                {
512                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
513                   iPar->setRegionType(OMP_MASTER);
514                       
515                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
516                   iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
517                       
518                   parRegionsList.push_back(iPar);
519                }
520                /* Flush construct */
521                else if(strstr(ppdf->symTabName().c_str(), "Flush") !=NULL)
522                {
523                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
524                   iPar->setRegionType(OMP_FLUSH);
525                       
526                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
527                   iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
528                       
529                   parRegionsList.push_back(iPar);
530                }
531                /* Critical Construct, Starts with GetDefaultSLock, ends with RelDefaultSLock */
532                else if(strstr(ppdf->symTabName().c_str(), "GetDefaultSLock") != NULL)
533                {
534                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
535                   iPar->setRegionType(OMP_CRITICAL);
536                       
537                   InstrucIter ah2(ah.getCurrentAddress(), this);
538                   while (ah2.hasMore())
539                   {
540                      if( ah2.isACallInstruction() ||
541                          ah2.isADynamicCallInstruction() )
542                      {
543                         Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
544                               
545                         image_func *ppdf2 = im->findFuncByEntry(target2);
546                         if (ppdf2 != NULL)
547                         {
548                            if(strstr(ppdf2->symTabName().c_str(), "RelDefaultSLock") !=NULL)
549                               break;
550                         }
551                      }
552                      ah2++;
553                   }
554                   iPar->setLastInsn(ah2.getCurrentAddress());
555
556                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
557                       
558                   parRegionsList.push_back(iPar);
559                }
560                /*Atomic Construct,  Begins with GetAtomicLock, ends with RelAtomicLock */
561                else if(strstr(ppdf->symTabName().c_str(), "GetAtomicLock") != NULL)
562                {
563                   image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
564                   iPar->setRegionType(OMP_ATOMIC);
565
566                   InstrucIter ah2(ah.getCurrentAddress(), this);
567                   while (ah2.hasMore())
568                   {
569                      if( ah2.isACallInstruction() ||
570                          ah2.isADynamicCallInstruction() )
571                      {
572                         Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
573                               
574                         image_func *ppdf2 = im->findFuncByEntry(target2);
575                         if (ppdf2 != NULL)
576                         {
577                            if(strstr(ppdf2->symTabName().c_str(), "RelDefaultSLock") !=NULL)
578                               break;
579                         }
580                      }
581                      ah2++;
582                   }
583                   iPar->setLastInsn(ah2.getCurrentAddress());
584                       
585                   iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
586                   iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
587                       
588                   parRegionsList.push_back(iPar);
589                }
590                else
591                {
592                }/* End Checking Different Directive Types */
593                  
594             }
595          }
596       }
597       ah++;
598    }
599 }
600
601 /* This does a linear scan to find out which registers are used in the function,
602    it then stores these registers so the scan only needs to be done once.
603    It returns true or false based on whether the function is a leaf function,
604    since if it is not the function could call out to another function that
605    clobbers more registers so more analysis would be needed */
606 void image_func::calcUsedRegs()
607 {
608    if (usedRegisters != NULL)
609       return; 
610    else
611    {
612       usedRegisters = new image_func_registers();
613       InstrucIter ah(this);
614       
615       //while there are still instructions to check for in the
616       //address space of the function      
617       while (ah.hasMore()) 
618       {
619          if (ah.isA_RT_WriteInstruction())
620             if (ah.getRTValue() >= 3 && ah.getRTValue() <= 12)
621                usedRegisters->generalPurposeRegisters.insert(ah.getRTValue());
622          if (ah.isA_RA_WriteInstruction())
623             if (ah.getRAValue() >= 3 && ah.getRAValue() <= 12)
624                usedRegisters->generalPurposeRegisters.insert(ah.getRAValue());
625          if (ah.isA_FRT_WriteInstruction())
626             if (ah.getRTValue() <= 13)
627                usedRegisters->floatingPointRegisters.insert(ah.getRTValue());
628          if (ah.isA_FRA_WriteInstruction())
629             if (ah.getRAValue() <= 13)
630                usedRegisters->floatingPointRegisters.insert(ah.getRAValue());
631          ah++;
632       }
633    }
634    return;
635 }
636
637 bool image_func::archIsIPRelativeBranch(InstrucIter& /* ah */)
638 {
639   return false;
640 }