3 #include "dyninstAPI/src/LineInformation.h"
4 #include "dyninstAPI/src/util.h"
6 typedef FileLineInformation::tuple tuple;
8 //this function implements binary search and returns the found element.
9 //besides the found element it returns the next bigger line numbered one
10 //The found element is the first same values element in the array in existence
11 //of many same values elements.
12 //in case it is not found it will RETURN NULL. if the next element
13 //is not available it will assign NULL to the reference.
14 //the next contains the entry with the first greater line number
15 tuple* binarySearchLineFirst(tuple element,tuple* array,int howMany,tuple*& next)
23 if(element.lineNo < array[mid].lineNo)
25 else if(element.lineNo > array[mid].lineNo)
31 //if found then porepare to return and the next available
32 if(element.lineNo == array[mid].lineNo){
34 for(;(index >= 0)&&(array[index].lineNo == element.lineNo);index--);
35 ret = array+(index+1);
37 for(;(index < howMany)&&(array[index].lineNo == element.lineNo);index++);
43 else if(low == howMany)
50 //this function implements binary search and returns the found element.
51 //besides the found element it returns the previous smaller address entry
52 //The found element is the first same values element in the array in existence
53 //of many same values elements.
54 //in case it is not found it will RETURN NULL. if the next element
55 //is not available it will assign NULL to the reference.
56 //the next contains the entry with the previous smaller address
57 tuple* binarySearchAddrFirst(tuple element,tuple* array,int howMany,tuple*& next)
65 if(element.codeAddress < array[mid].codeAddress)
67 else if(element.codeAddress > array[mid].codeAddress)
73 ////if found then porepare to return and the next available
74 if(element.codeAddress == array[mid].codeAddress){
76 for(;(index>=0)&&(array[index].codeAddress == element.codeAddress);index--);
77 ret = array+(index+1);
81 Address addr = array[index].codeAddress;
82 for(;(index>=0) && (array[index].codeAddress == addr);index--);
83 next = array+(index+1);
89 Address addr = array[high].codeAddress;
90 for(;(high >=0) && (array[high].codeAddress == addr);high--);
91 next = array+(high+1);
97 FileLineInformation::FileLineInformation(string fileName)
98 : sourceFileName(fileName),
103 functionNameList(NULL),
104 lineInformationList(NULL) {}
107 FileLineInformation::~FileLineInformation(){
110 for(int i=0;i<functionCount;i++){
111 delete lineInformationList[i];
112 delete functionNameList[i];
114 delete[] functionNameList;
115 delete[] lineInformationList;
118 //returns the function info structure
119 FileLineInformation::FunctionInfo*
120 FileLineInformation::findFunctionInfo(string functionName){
121 for(int i=0;i<functionCount;i++)
122 if(functionName == *functionNameList[i])
123 return lineInformationList[i];
127 //inserts function wntry to the mapping from function name to its info
128 void FileLineInformation::insertFunction(string functionName){
129 FunctionInfo* fInfo = findFunctionInfo(functionName);
131 functionNameList = (string**)(functionCount ?
132 realloc(functionNameList,(functionCount+1)*sizeof(string*)) :
134 lineInformationList = (FunctionInfo**)(functionCount ?
135 realloc(lineInformationList,(functionCount+1)*sizeof(FunctionInfo*)) :
136 new FunctionInfo*[1]);
137 functionNameList[functionCount] = new string(functionName);
138 lineInformationList[functionCount] = new FunctionInfo;
143 //returns true if the function has an entry in the mapping
144 bool FileLineInformation::findFunction(string functionName){
145 FunctionInfo* fInfo = findFunctionInfo(functionName);
146 if(!fInfo) return false;
151 //insert a mapping from line number to address and address to line number
152 //to the corresponding structures and updates the records for the function
154 void FileLineInformation::insertLineAddress(string functionName,
155 unsigned short lineNo,
159 FunctionInfo* fInfo = findFunctionInfo(functionName);
161 cerr << "FATAL ERROR : Something wrong \n";
165 lineToAddr = !lineToAddr ? ((tuple*)malloc(sizeof(tuple))) :
166 ((tuple*)realloc(lineToAddr,sizeof(tuple)*(size+1)));
167 addrToLine = !addrToLine ? ((tuple*)malloc(sizeof(tuple))) :
168 ((tuple*)realloc(addrToLine,sizeof(tuple)*(size+1)));
170 //since the entries will come in oreder insertion sort is the best sort here
171 //to keep the list sorted and using binary search to find the entries.
172 //insertion sort comes here
175 for(index1=size-1;index1>=0;index1--)
176 if(lineToAddr[index1].lineNo > lineNo)
177 lineToAddr[index1+1] = lineToAddr[index1];
180 lineToAddr[index1] = tuple(lineNo,codeAddress);
183 //insertion sort for code address
185 for(index2=size-1;index2>=0;index2--)
186 if(addrToLine[index2].codeAddress > codeAddress)
187 addrToLine[index2+1] = addrToLine[index2];
190 addrToLine[index2] = tuple(lineNo,codeAddress);
194 if(!fInfo->validInfo){
195 fInfo->startLinePtr = (unsigned)index1;
196 fInfo->endLinePtr = (unsigned)index1;
197 fInfo->startAddrPtr = (unsigned)index2;
198 fInfo->endAddrPtr = (unsigned)index2;
199 fInfo->validInfo = true;
203 if(lineToAddr[fInfo->startLinePtr].lineNo > lineNo)
204 fInfo->startLinePtr = (unsigned)index1;
205 if(lineToAddr[fInfo->endLinePtr].lineNo <= lineNo)
206 fInfo->endLinePtr = (unsigned)index1;
208 if(addrToLine[fInfo->startAddrPtr].codeAddress > codeAddress)
209 fInfo->startAddrPtr = (unsigned)index2;
210 if(addrToLine[fInfo->endAddrPtr].codeAddress <= codeAddress)
211 fInfo->endAddrPtr = (unsigned)index2;
215 //returns true in case of success, false otherwise.
216 //this method finds the line number corresponding to an address.
217 //if name of the function is supplied and isFile is false
218 //then function level search is being applied. Otherwise file level
219 //search is applied. If there are more than 1 line found than
220 //the maximum is being returned.
221 bool FileLineInformation::getLineFromAddr(string name,unsigned short& lineNo,
222 Address codeAddress,bool isFile,
225 BPatch_Set<unsigned short> lines;
226 if(!getLineFromAddr(name,lines,codeAddress,isFile,isExactMatch))
228 lineNo = lines.maximum();
231 //returns true in case of success, false otherwise.
232 //this method finds the line numbers corresponding to an address.
233 //if name of the function is supplied and isFile is false
234 //then function level search is being applied. Otherwise file level
235 //search is applied. All the line numbers corresponding to the address
236 //is returned in a set of addresses.
237 bool FileLineInformation::getLineFromAddr(string name,
238 BPatch_Set<unsigned short>& lines,
239 Address codeAddress,bool isFile,
249 beginPtr = addrToLine;
250 endPtr = (tuple*) (addrToLine+(size-1));
254 FunctionInfo* fInfo = findFunctionInfo(name);
257 if(!fInfo->validInfo)
259 beginPtr = addrToLine+fInfo->startAddrPtr;
260 endPtr = addrToLine+fInfo->endAddrPtr;
261 howMany = fInfo->endAddrPtr-fInfo->startAddrPtr+1;
264 if((codeAddress < beginPtr->codeAddress) || (endPtr->codeAddress < codeAddress))
267 tuple toSearch(0,codeAddress);
269 tuple* ret = binarySearchAddrFirst(toSearch,beginPtr,howMany,next);
276 codeAddress = ret->codeAddress;
279 lines += ret->lineNo;
281 }while((ret <= endPtr) && (ret->codeAddress == codeAddress));
286 //method that retuns set of addresses corresponding to a given line number
287 //the level of the search is file level if isFile flag is set.
288 //If isFile level is not set, it seraches in the given function
289 //in case of success it returns true otherwise false
290 bool FileLineInformation::getAddrFromLine(string name,
291 BPatch_Set<Address>& codeAddress,
292 unsigned short lineNo,bool isFile,
302 beginPtr = lineToAddr;
303 endPtr = (tuple*) (lineToAddr+(size-1));
307 FunctionInfo* fInfo = findFunctionInfo(name);
310 if(!fInfo->validInfo)
312 beginPtr = lineToAddr+fInfo->startLinePtr;
313 endPtr = lineToAddr+fInfo->endLinePtr;
314 howMany = fInfo->endLinePtr-fInfo->startLinePtr+1;
317 (lineNo < beginPtr->lineNo) || (endPtr->lineNo < lineNo))
320 tuple toSearch(lineNo,0);
322 tuple* ret = binarySearchLineFirst(toSearch,beginPtr,howMany,next);
329 lineNo = ret->lineNo;
332 codeAddress += ret->codeAddress;
334 }while((ret <= endPtr) && (ret->lineNo == lineNo));
339 //temporary function to print info about line information
340 void FileLineInformation::print(){
341 cerr << "LINE TO ADDRESS :\n";
342 for(int j=0;j<size;j++)
343 cerr << dec << lineToAddr[j].lineNo << " ----> " << hex << lineToAddr[j].codeAddress << "\n";
344 for(int i=0;i<functionCount;i++){
345 FunctionInfo* funcinfo = lineInformationList[i];
346 cerr << "FUNCTION LINE : " << *functionNameList[i] << " : " ;
347 if(!funcinfo->validInfo)
349 cerr << dec << lineToAddr[funcinfo->startLinePtr].lineNo ;
350 cerr << " --- " << dec << lineToAddr[funcinfo->endLinePtr].lineNo << "\n";
355 //constructor whose argument is the name of the module name
356 LineInformation::LineInformation(string mName)
359 sourceFileList(NULL),
360 lineInformationList(NULL) {}
364 LineInformation::~LineInformation() {
365 for(int i=0;i<sourceFileCount;i++){
366 delete sourceFileList[i];
367 delete lineInformationList[i];
369 delete[] sourceFileList;
370 delete[] lineInformationList;
373 //method to insert entries for the given file name and function name
374 //it creates the necessary structures and inserts into the maps
375 void LineInformation::insertSourceFileName(string functionName,string fileName)
377 FileLineInformation* fInfo = getFileLineInformation(fileName);
379 fInfo = new FileLineInformation(fileName);
380 sourceFileList = (string**)(sourceFileCount ?
381 realloc(sourceFileList,(sourceFileCount+1)*sizeof(string*)) :
383 lineInformationList = (FileLineInformation**)(sourceFileCount ?
384 realloc(lineInformationList,(sourceFileCount+1)*sizeof(FileLineInformation*)) :
385 new FileLineInformation*[1]);
386 sourceFileList[sourceFileCount] = new string(fileName);
387 lineInformationList[sourceFileCount] = fInfo;
390 fInfo->insertFunction(functionName);
393 //inserts line to address and address to line mapping to the line info
394 //object of the given filename. The records for function is also updated
395 void LineInformation::insertLineAddress(string functionName,
397 unsigned short lineNo,
400 FileLineInformation* fInfo = getFileLineInformation(fileName);
402 fInfo->insertLineAddress(functionName,lineNo,codeAddress);
405 //returns line number corresponding to the the given address
406 //if isFile is set the search is file level otherwsie function level.
407 bool LineInformation::getLineFromAddr(string name,
408 unsigned short& lineNo,
413 FileLineInformation* fInfo = NULL;
415 fInfo = getFileLineInformation(name);
417 fInfo = getFunctionLineInformation(name);
419 if(!fInfo) return false;
421 return fInfo->getLineFromAddr(name,lineNo,codeAddress,isFile,isExactMatch);
424 //returns line number corresponding to the the given address
425 //if isFile is set the search is file level otherwsie function level.
426 bool LineInformation::getLineFromAddr(string name,
427 BPatch_Set<unsigned short>& lines,
432 FileLineInformation* fInfo = NULL;
434 fInfo = getFileLineInformation(name);
436 fInfo = getFunctionLineInformation(name);
438 if(!fInfo) return false;
440 return fInfo->getLineFromAddr(name,lines,codeAddress,isFile,isExactMatch);
443 //returns address corresponding to the the given line
444 //if isFile is set the search is file level otherwsie function level.
445 bool LineInformation::getAddrFromLine(string name,
446 BPatch_Set<Address>& codeAddress,
447 unsigned short lineNo,
451 FileLineInformation* fInfo = NULL;
453 fInfo = getFileLineInformation(name);
455 fInfo = getFunctionLineInformation(name);
457 if(!fInfo) return false;
459 return fInfo->getAddrFromLine(name,codeAddress,lineNo,isFile,isExactMatch);
462 bool LineInformation::getAddrFromLine(BPatch_Set<Address>& codeAddress,
463 unsigned short lineNo,
466 FileLineInformation* fInfo = getFileLineInformation(moduleName);
469 cerr << "Module " << moduleName << " is not source file name\n";
473 return fInfo->getAddrFromLine(moduleName,codeAddress,
474 lineNo,true,isExactMatch);
477 //returns the line information for the given filename
478 FileLineInformation* LineInformation::getFileLineInformation(string fileName){
479 for(int j=0;j<sourceFileCount;j++)
480 if(fileName == *sourceFileList[j])
481 return lineInformationList[j];
482 for(int i=0;i<sourceFileCount;i++){
483 char* name = new char[sourceFileList[i]->length()+1];
484 strncpy(name,sourceFileList[i]->string_of(),
485 sourceFileList[i]->length());
486 name[sourceFileList[i]->length()] = '\0';
487 char* p = strrchr(name,'/');
494 if(fileName == sname){
496 return lineInformationList[i];
504 //method retuns the file line information object which the function belongs to.
505 //if there is no entry than it retuns NULL
507 LineInformation::getFunctionLineInformation(string functionName){
508 for(int i=0;i<sourceFileCount;i++)
509 if(lineInformationList[i]->findFunction(functionName))
510 return lineInformationList[i];
514 //method that returns true if function belongs to this object
516 bool LineInformation::findFunction(string functionName){
518 for(int i=0;!ret && (i<sourceFileCount);i++)
519 ret = lineInformationList[i]->findFunction(functionName);
523 //print the line information kept in the map
524 void LineInformation::print(){
525 cerr << "**********************************************\n";
526 cerr << "MODULE : " << moduleName << "\n";
527 cerr << "**********************************************\n";
528 for(int i=0;i<sourceFileCount;i++){
529 cerr << "FILE : " << *sourceFileList[i] << "\n";
530 lineInformationList[i]->print();