Intermidiate commit for AIX build fix.
[dyninst.git] / dynC_API / src / snippetGen.C
1 /*
2  * Copyright (c) 1996-2011 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 #include "snippetGen.h"  
32
33 extern "C" {
34    void getErrorBase(char *errbase, int length); 
35 }
36
37
38 BPatch_snippet *SnippetGenerator::findOrCreateVariable(const char * name, const char * type, const void * initialValue){
39    lastError.str() = "";
40    int zero = 0;
41    if(initialValue == NULL){
42            //expand?
43       if (strcmp(type, "int") == 0)
44          initialValue = &zero; 
45       if (strcmp(type, "char *") == 0)
46          initialValue = "";
47    }
48    
49    BPatch_variableExpr *varExpr = image->findVariable(name, false);
50    if(varExpr != NULL){
51       return varExpr;
52    }
53    BPatch_type *bptype = image->findType(type);
54    
55    if(bptype == NULL){
56       lastError << "Unable to find type:" << type;
57       lastErrorInfo.type = SG_LookUpFailure;
58       lastErrorInfo.fatal = true;
59       return NULL;
60    }
61 //   varExpr = addSpace->malloc(*bptype);
62    varExpr = addSpace->createVariable(std::string(name), (Dyninst::Address)NULL, bptype);
63
64    if(varExpr == NULL){
65       lastError << "FIXME: varExpr is null!";
66       lastErrorInfo.type = SG_InternalError;
67       lastErrorInfo.fatal = true;
68       return NULL;
69    }
70    
71    if(!(varExpr->writeValue(initialValue))){
72       //unable to initialize... what to do?
73       lastError << "Internal: Variable initialization failed";
74       lastErrorInfo.type = SG_InternalError;
75       lastErrorInfo.fatal = false;
76    }
77    
78    return varExpr;
79
80 }
81 BPatch_snippet *SnippetGenerator::findOrCreateArray(const char * name, const char * elementType, long size){
82    lastError.str() = "";        
83         BPatch_variableExpr *varExpr = image->findVariable(name, false);
84         if(varExpr != NULL){
85            return varExpr;
86         }
87
88         std::stringstream arrayTypeName;
89         arrayTypeName << elementType << "[" << size << "]";
90         BPatch_type *type = image->findType(elementType);
91        
92         if(type == NULL){
93            lastError << "Unable to find type:" << elementType;
94            lastErrorInfo.type = SG_LookUpFailure;
95            lastErrorInfo.fatal = true;
96            return NULL;
97         }
98         
99         BPatch_type *array = BPatch::bpatch->createArray(arrayTypeName.str().c_str(), type, 0, size - 1);
100
101         if(array == NULL){
102            lastError << "Failed to create array";
103            lastErrorInfo.type = SG_InternalError;
104            lastErrorInfo.fatal = true;
105            return NULL;
106         }
107
108         varExpr = addSpace->malloc(*array);
109         varExpr = addSpace->createVariable(std::string(name), (Dyninst::Address)varExpr->getBaseAddr(), array);
110         
111         if(varExpr == NULL){
112            lastError << "FIXME: varExpr is null!";
113            lastErrorInfo.type = SG_InternalError;
114            lastErrorInfo.fatal = true;
115            return NULL;
116         }
117
118         return varExpr;
119
120 }
121 BPatch_snippet *SnippetGenerator::findOrCreateStruct(){
122    return NULL;
123 }
124 BPatch_snippet *SnippetGenerator::findOrCreateUnion(){
125    return NULL;
126 }
127
128 BPatch_snippet *SnippetGenerator::findAppVariable(const char * name, bool global, bool local){
129    lastError.str() = "";
130    if(global && local){
131       lastError << "Cannot specify a variable as both global and local.";
132       lastErrorInfo.type = SG_SyntaxError;
133       lastErrorInfo.fatal = true;
134       return NULL;
135    }
136    BPatch_variableExpr *varExpr = NULL;
137    if(point != NULL){
138       varExpr = image->findVariable(*point, name, false);;
139    }
140    if(global || point == NULL){
141       varExpr = image->findVariable(name, false);
142    }else if(local){
143       varExpr = image->findVariable(*point, name, false);
144    }
145    if(varExpr == NULL){ // If var not found
146       lastError << "Can't find ";
147       lastError << (local ? "local " : (global ? "global " : ""));
148 //      printf("%s\n", name);
149       lastError << "variable \"" << name << "\"";
150       lastErrorInfo.type = SG_LookUpFailure;
151       lastErrorInfo.fatal = true;
152       return NULL;
153    }
154    BPatch_variableExpr *varExprGbl = image->findVariable(name);    
155    if(!global && point != NULL){
156       if(local && NULL != varExprGbl && varExpr == varExprGbl){
157          lastError << "Can't find local variable \"" << name << "\". There is a global variable of the same name.";
158          lastErrorInfo.type = SG_LookUpFailure;
159          lastErrorInfo.fatal = true;
160          return NULL;
161       }
162       if(NULL == varExprGbl || (local && NULL != varExprGbl && varExprGbl != varExpr)){ // if var is local
163          if (point->getPointType() == BPatch_entry || point->getPointType() == BPatch_exit){
164             lastError << "Cannot access local variables at entry or exit points.";
165             lastErrorInfo.type = SG_ScopeViolation;
166             lastErrorInfo.fatal = true;
167             return NULL;
168          }
169          return varExpr; //found a local variable
170       }
171    }
172    if(point != NULL && !local && !global && (NULL != varExprGbl && varExprGbl != varExpr)){// if BPatch_AppVar && both local and global
173       if (point->getPointType() != BPatch_entry && point->getPointType() != BPatch_exit){
174          return varExpr; //found a local variable`
175       }
176    }
177    
178    return varExprGbl; //found a global variable
179    
180 }
181 BPatch_snippet *SnippetGenerator::findParameter(const char * name){
182    lastError.str() = "";
183    if(point == NULL){
184       lastError << "Cannot access local varaibles without point information.";
185       lastErrorInfo.type = SG_ScopeViolation;
186       lastErrorInfo.fatal = true;
187       return NULL;
188    }
189    if(point->getPointType() != BPatch_entry){
190       lastError << "Parameters only valid at entry points.";
191       lastErrorInfo.type = SG_ScopeViolation;
192       lastErrorInfo.fatal = true;
193       return NULL;
194    }
195    char fnName[512] = "";   
196    std::vector<BPatch_localVar *> *locals = point->getFunction()->getParams();
197    if(locals->size() == 0){
198       lastError << "No parameters for " << point->getFunction()->getTypedName(fnName, 512) << "";
199       lastErrorInfo.type = SG_LookUpFailure;
200       lastErrorInfo.fatal = false; //should this be false?
201       return NULL;
202    }
203          
204    for(unsigned int i = 0; i < locals->size(); ++i){
205       if (strcmp(((*locals)[i])->getName(), name) == 0){
206          return new BPatch_paramExpr(i);
207       }
208    }
209
210    lastError << "Parameter \'" << name << "\' not found for " << point->getFunction()->getTypedName(fnName, 512) << "" ;
211    lastErrorInfo.type = SG_LookUpFailure;
212    lastErrorInfo.fatal = false; //should this be false?
213    return NULL;
214 }
215 BPatch_snippet *SnippetGenerator::findParameter(int index){
216    lastError.str() = "";       
217    if(point == NULL){
218       lastError << "Cannot access local varaibles without point information.";
219       lastErrorInfo.type = SG_ScopeViolation;
220       lastErrorInfo.fatal = true;
221       return NULL;
222    }
223    if(point->getPointType() != BPatch_entry){
224       lastError << "Parameters only valid at entry points.";
225       lastErrorInfo.type = SG_ScopeViolation;
226       lastErrorInfo.fatal = true;
227       return NULL;
228    }
229
230    char fnName[512] = "";
231    std::vector<BPatch_localVar *> *locals = point->getFunction()->getParams();
232    if(locals->size() == 0){
233       
234       lastError << "No parameters for " << point->getFunction()->getTypedName(fnName, 512) << "";
235       lastErrorInfo.type = SG_LookUpFailure;
236       lastErrorInfo.fatal = false; //should this be false?
237       return NULL;
238    }
239          
240    if(locals->size() <= (const unsigned int)index || index < 0){
241       lastError << "Parameter index out of range:" << index << "for " << point->getFunction()->getTypedName(fnName, 512) << "";
242       lastErrorInfo.type = SG_LookUpFailure;
243       lastErrorInfo.fatal = false; //should this be false?
244       return NULL;
245    }   
246    return new BPatch_paramExpr(index);
247 }
248 BPatch_snippet *SnippetGenerator::findInstVariable(const char *mangledStub, const char * name){
249    lastError.str() = "";
250    std::vector<BPatch_variableExpr *> *vars = image->getGlobalVariables();
251    if(vars->size() == 0){
252       lastError << "No global variables!";
253       lastErrorInfo.type = SG_InternalError ; lastErrorInfo.fatal = true;
254       return NULL;
255    }
256    //  BPatch_variableExpr *varExpr = NULL;
257    BPatch_variableExpr *varExprGbl = NULL;
258    for(unsigned int i = 0; i < vars->size(); ++i){
259       const char *substr = strstr((*vars)[i]->getName(), mangledStub);
260       if(substr != NULL){
261          return (*vars)[i];            
262       }
263    }
264    if(varExprGbl != NULL){
265       return varExprGbl;
266    }
267    lastError << "Unable to find InstVar \"" << name << "\"";
268    lastErrorInfo.type = SG_LookUpFailure; 
269    lastErrorInfo.fatal = true; //should this be false?
270    return NULL;
271 }
272 BPatch_snippet *SnippetGenerator::generateArrayRef(BPatch_snippet *base, BPatch_snippet *index){
273    lastError.str() = "";
274    if(base->getType() != NULL && base->getType()->getDataClass() != BPatch_dataArray){
275       lastError << "Base of array reference is not an array";
276       lastErrorInfo.type = SG_TypeError; 
277       lastErrorInfo.fatal = true;
278       return NULL;
279    }
280    if(index->getType() != NULL && index->getType()->getDataClass() != BPatch_scalar){
281       lastError << "Array index is not a scalar";
282       lastErrorInfo.type = SG_TypeError; 
283       lastErrorInfo.fatal = true;
284       return NULL;
285    }
286
287    BPatch_arithExpr *ref = new BPatch_arithExpr(BPatch_ref, *base, *index);
288    if(ref == NULL){
289       lastError << "Array reference cannot be generated - received null pointer";
290       lastErrorInfo.type = SG_InternalError;
291       lastErrorInfo.fatal = true;
292       return NULL;
293    }
294    return ref;
295 }
296
297 BPatch_function *SnippetGenerator::findFunction(const char * name, std::vector<BPatch_snippet *> params){
298    lastError.str() = "";
299    
300    std::vector<BPatch_function *> functions;
301    
302    if(NULL == image->findFunction(name, functions, false)){
303       lastError << "Couldn't find function \'" << name << "\'";
304       lastErrorInfo.type = SG_LookUpFailure; 
305       lastErrorInfo.fatal = true;
306       return NULL;
307    }
308    char funcName[512];
309    bool foundDebugInfo, foundMatch, setFunc;
310    BPatch_function *noParamFunc = NULL; //for storing potentially variadic functions
311    foundDebugInfo = false;
312    foundMatch = false;
313    setFunc = false;
314    std::vector<BPatch_localVar *> *funcParams;
315    BPatch_function *func = functions[0];
316    std::vector<Dyninst::SymtabAPI::localVar *>SymTabParams;
317
318    for(unsigned int n = 0; n < functions.size(); ++n){
319       //if has debug info for params
320       if(functions[n]->hasParamDebugInfo()){
321          foundDebugInfo = true;
322          funcParams = functions[n]->getParams();
323          if(funcParams->size() == 0){
324             noParamFunc = functions[n]; //store a potentially variadic function
325          }
326          foundMatch = true;
327          if(funcParams->size() == params.size()){
328             for(unsigned int i = 0; i < funcParams->size(); ++i){
329                if(!(*funcParams)[i]->getType()->isCompatible(params[i]->getType())){
330                   foundMatch = false;
331                   break;
332                }
333             }
334             if(foundMatch){
335                func = functions[n];
336                setFunc = true;
337                break;
338             }
339          }                           
340       }
341    }
342
343    char errorHeader[256];
344    getErrorBase(errorHeader, 256);
345    if(noParamFunc != NULL && !setFunc){
346          func = noParamFunc;
347    }else if(!setFunc && foundDebugInfo){
348       lastError << "No matching function for call to '" << name << "(";
349       if(params.size() > 0){
350          lastError << params[0]->getType()->getName();
351       }
352       for(unsigned int m = 1; m < params.size(); ++m){
353          lastError << ", ";
354          if(params[m]->getType() == NULL){
355             lastError << "...";
356          }else{
357             lastError << params[m]->getType()->getName();
358          }
359       }
360       lastError << ")'.\n";
361       for(unsigned int i = 0; i < strlen(errorHeader); ++i){
362             lastError << ' ';
363       }
364       lastError << "  note: candidates are: ";
365       lastError << functions[0]->getTypedName(funcName, 512);
366       for(unsigned int n = 1; n < functions.size(); ++n){
367          lastError << "\n";
368          for(unsigned int i = 0; i < strlen(errorHeader); ++i){
369             lastError << ' ';
370          }
371          lastError << "  note:                ";
372          lastError << functions[n]->getTypedName(funcName, 512);
373       }
374       lastError << "\n";
375       lastErrorInfo.type = SG_LookUpFailure ; lastErrorInfo.fatal = true;
376       return NULL;
377    }
378    
379    if(!foundDebugInfo){
380       func = functions[0]; //<- Pick the first one if there is no debug info
381    }
382    return func;
383 }
384 BPatch_snippet *SnippetGenerator::getContextInfo(SGContext context){
385    char name[512];
386    lastError.str() = "";
387    if(point == NULL){
388       lastError << "Cannot provide context information without a point";
389       lastErrorInfo.type = SG_ScopeViolation ;
390       lastErrorInfo.fatal = true;
391       return NULL;
392    }
393    switch(context){
394       case SG_FunctionName:
395           point->getFunction()->getName(name, 512);
396           return new BPatch_constExpr(const_cast<char *>(name));
397           break;
398       case SG_ModuleName:
399          point->getFunction()->getModuleName(name, 512);
400          return new BPatch_constExpr(const_cast<char *>(name));
401          break;
402       case SG_TID:
403          if(image->getProcess() == NULL){
404             lastError << "Process is null!"; // doesn't do anything
405             lastErrorInfo.type = SG_InternalError;
406             lastErrorInfo.fatal = true;
407             return NULL;
408         }      
409         return new BPatch_tidExpr(image->getProcess());
410       default:
411          lastError << "Internal: Unrecognized SGContext!";
412          lastErrorInfo.type = SG_InternalError;
413          lastErrorInfo.fatal = true;
414          return NULL;
415    }
416 }
417