3 #include "dyninstAPI/src/LineInformation.h"
4 #include "dyninstAPI/src/util.h"
7 //this function implements binary search and returns the found element.
8 //besides the found element it returns the next bigger line numbered one
9 //The found element is the first same values element in the array in existence
10 //of many same values elements.
11 //in case it is not found it will RETURN NULL. if the next element
12 //is not available it will assign NULL to the reference.
13 //the next contains the entry with the first greater line number
14 tuple** binarySearchLineFirst(tuple element,tuple** array,int howMany,tuple**& next)
22 if(element.lineNo < array[mid]->lineNo)
24 else if(element.lineNo > array[mid]->lineNo)
30 //if found then porepare to return and the next available
31 if(element.lineNo == array[mid]->lineNo){
33 for(;(index >= 0)&&(array[index]->lineNo == element.lineNo);index--);
34 ret = array+(index+1);
36 for(;(index < howMany)&&(array[index]->lineNo == element.lineNo);index++);
42 else if(low == howMany)
49 //this function implements binary search and returns the found element.
50 //besides the found element it returns the previous smaller address entry
51 //The found element is the first same values element in the array in existence
52 //of many same values elements.
53 //in case it is not found it will RETURN NULL. if the next element
54 //is not available it will assign NULL to the reference.
55 //the next contains the entry with the previous smaller address
56 tuple** binarySearchAddrFirst(tuple element,tuple** array,int howMany,tuple**& next)
64 if(element.codeAddress < array[mid]->codeAddress)
66 else if(element.codeAddress > array[mid]->codeAddress)
72 ////if found then porepare to return and the next available
73 if(element.codeAddress == array[mid]->codeAddress){
75 for(;(index>=0)&&(array[index]->codeAddress == element.codeAddress);index--);
76 ret = array+(index+1);
80 Address addr = array[index]->codeAddress;
81 for(;(index>=0) && (array[index]->codeAddress == addr);index--);
82 next = array+(index+1);
88 Address addr = array[high]->codeAddress;
89 for(;(high >=0) && (array[high]->codeAddress == addr);high--);
90 next = array+(high+1);
96 FileLineInformation::FileLineInformation(string fileName)
97 : sourceFileName(fileName),
102 functionNameList(NULL),
103 lineInformationList(NULL) {}
106 FileLineInformation::~FileLineInformation(){
109 delete lineToAddr[i];
112 for(i=0;i<functionCount;i++){
113 delete lineInformationList[i];
114 delete functionNameList[i];
116 free(functionNameList);
117 free(lineInformationList);
120 //returns the function info structure
121 FunctionInfo *FileLineInformation::findFunctionInfo(string functionName){
122 for(int i=0;i<functionCount;i++)
123 if(functionName == *functionNameList[i])
124 return lineInformationList[i];
128 //inserts function wntry to the mapping from function name to its info
129 void FileLineInformation::insertFunction(string functionName){
130 FunctionInfo* fInfo = findFunctionInfo(functionName);
132 functionNameList = (string**)(functionCount ?
133 realloc(functionNameList,(functionCount+1)*sizeof(string*)) :
134 malloc(sizeof(string*)));
135 lineInformationList = (FunctionInfo**)(functionCount ?
136 realloc(lineInformationList,(functionCount+1)*sizeof(FunctionInfo*)) :
137 malloc(sizeof(FunctionInfo*)));
138 functionNameList[functionCount] = new string(functionName);
139 lineInformationList[functionCount] = new FunctionInfo();
144 //returns true if the function has an entry in the mapping
145 bool FileLineInformation::findFunction(string functionName){
146 FunctionInfo* fInfo = findFunctionInfo(functionName);
147 if(!fInfo) return false;
151 //delete the records for function
152 void FileLineInformation::deleteFunction(string functionName){
154 for(i=0;i<functionCount;i++)
155 if(functionName == *functionNameList[i])
157 if(i >= functionCount)
162 free(functionNameList);
163 free(lineInformationList);
164 functionNameList = NULL;
165 lineInformationList = NULL;
168 delete functionNameList[i];
170 functionNameList[i] = functionNameList[functionCount];
172 (string**)realloc(functionNameList,functionCount*sizeof(string*));
173 lineInformationList[i] = lineInformationList[functionCount];
174 lineInformationList =
175 (FunctionInfo**)realloc(lineInformationList,functionCount*sizeof(FunctionInfo*));
178 //updates records for a function
179 bool FileLineInformation::insertFunction(string functionName,Address baseAddr,
180 Address functionSize)
182 tuple toSearchBegin(0,baseAddr);
183 tuple toSearchEnd(0,baseAddr+functionSize-1);
186 tuple** retBegin = binarySearchAddrFirst(toSearchBegin,
187 addrToLine,size,next);
189 unsigned short beginLineIndex = retBegin[0]->linePtr;
190 unsigned short beginAddrIndex = retBegin[0]->addrPtr;
192 tuple** retEnd = binarySearchAddrFirst(toSearchEnd,
193 addrToLine,size,next);
197 unsigned short endLineIndex;
198 unsigned short endAddrIndex;
200 endLineIndex = retEnd[0]->linePtr;
201 endAddrIndex = retEnd[0]->addrPtr;
204 endLineIndex = next[0]->linePtr;
205 endAddrIndex = next[0]->addrPtr;
208 //cerr << "FOUND " << " LINE RANGE ( "
209 // << beginLineIndex << "," << endLineIndex << " ) -- "
210 // << " ADDRESS RANGE ( " << beginAddrIndex << ","
211 // << endAddrIndex << " )\n";
212 functionNameList = (string**)(functionCount ?
213 realloc(functionNameList,(functionCount+1)*sizeof(string*)) :
214 malloc(sizeof(string*)));
215 lineInformationList = (FunctionInfo**)(functionCount ?
216 realloc(lineInformationList,(functionCount+1)*sizeof(FunctionInfo*)) :
217 malloc(sizeof(FunctionInfo*)));
218 functionNameList[functionCount] = new string(functionName);
220 FunctionInfo* fInfo = new FunctionInfo();
221 fInfo->startLinePtr = lineToAddr[beginLineIndex];
222 fInfo->endLinePtr = lineToAddr[endLineIndex];
223 fInfo->startAddrPtr = addrToLine[beginAddrIndex];
224 fInfo->endAddrPtr = addrToLine[endAddrIndex];
225 fInfo->validInfo = true;
226 lineInformationList[functionCount] = fInfo;
234 //insert a mapping from line number to address and address to line number
235 //to the corresponding structures and updates the records for the function
237 void FileLineInformation::insertLineAddress(string functionName,
238 unsigned short lineNo,
242 FunctionInfo* fInfo = findFunctionInfo(functionName);
244 cerr << "FATAL ERROR : Something wrong \n";
248 lineToAddr = !lineToAddr ? ((tuple**)malloc(sizeof(tuple*))) :
249 ((tuple**)realloc(lineToAddr,sizeof(tuple*)*(size+1)));
250 addrToLine = !addrToLine ? ((tuple**)malloc(sizeof(tuple*))) :
251 ((tuple**)realloc(addrToLine,sizeof(tuple*)*(size+1)));
253 //since the entries will come in oreder insertion sort is the best sort here
254 //to keep the list sorted and using binary search to find the entries.
255 //insertion sort comes here
257 tuple* newTuple = new tuple(lineNo,codeAddress);
260 for(index1=size-1;index1>=0;index1--)
261 if(lineToAddr[index1]->lineNo > lineNo){
262 lineToAddr[index1+1] = lineToAddr[index1];
263 lineToAddr[index1+1]->linePtr = (unsigned)(index1+1);
267 lineToAddr[index1] = newTuple;
268 lineToAddr[index1]->linePtr = (unsigned)index1;
271 for(index2=size-1;index2>=0;index2--)
272 if(addrToLine[index2]->codeAddress > codeAddress){
273 addrToLine[index2+1] = addrToLine[index2];
274 addrToLine[index2+1]->addrPtr = (unsigned)(index2+1);
278 addrToLine[index2] = newTuple;
279 addrToLine[index2]->addrPtr = (unsigned)index2;
283 if(!fInfo->validInfo){
284 fInfo->startLinePtr = lineToAddr[index1];
285 fInfo->endLinePtr = lineToAddr[index1];
286 fInfo->startAddrPtr = addrToLine[index2];
287 fInfo->endAddrPtr = addrToLine[index2];
288 fInfo->validInfo = true;
291 if(fInfo->startLinePtr->lineNo > lineNo)
292 fInfo->startLinePtr = lineToAddr[index1];
294 if(fInfo->endLinePtr->lineNo <= lineNo)
295 fInfo->endLinePtr = lineToAddr[index1];
297 if(fInfo->startAddrPtr->codeAddress > codeAddress)
298 fInfo->startAddrPtr = addrToLine[index2];
300 if(fInfo->endAddrPtr->codeAddress <= codeAddress)
301 fInfo->endAddrPtr = addrToLine[index2];
304 //returns true in case of success, false otherwise.
305 //this method finds the line number corresponding to an address.
306 //if name of the function is supplied and isFile is false
307 //then function level search is being applied. Otherwise file level
308 //search is applied. If there are more than 1 line found than
309 //the maximum is being returned.
310 bool FileLineInformation::getLineFromAddr(string name,unsigned short& lineNo,
311 Address codeAddress,bool isFile,
314 BPatch_Set<unsigned short> lines;
315 if(!getLineFromAddr(name,lines,codeAddress,isFile,isExactMatch))
317 lineNo = lines.maximum();
320 //returns true in case of success, false otherwise.
321 //this method finds the line numbers corresponding to an address.
322 //if name of the function is supplied and isFile is false
323 //then function level search is being applied. Otherwise file level
324 //search is applied. All the line numbers corresponding to the address
325 //is returned in a set of addresses.
326 bool FileLineInformation::getLineFromAddr(string name,
327 BPatch_Set<unsigned short>& lines,
328 Address codeAddress,bool isFile,
338 beginPtr = addrToLine;
339 endPtr = (tuple**) (addrToLine+(size-1));
343 FunctionInfo* fInfo = findFunctionInfo(name);
346 if(!fInfo->validInfo)
348 beginPtr = (tuple**)(addrToLine+fInfo->startAddrPtr->addrPtr);
349 endPtr = (tuple**)(addrToLine+fInfo->endAddrPtr->addrPtr);
350 howMany = (fInfo->endAddrPtr->addrPtr - fInfo->startAddrPtr->addrPtr)+1;
353 if((codeAddress < (*beginPtr)->codeAddress) ||
354 ((*endPtr)->codeAddress < codeAddress))
357 tuple toSearch(0,codeAddress);
359 tuple** ret = binarySearchAddrFirst(toSearch,beginPtr,howMany,next);
366 codeAddress = (*ret)->codeAddress;
369 lines += (*ret)->lineNo;
371 }while((ret <= endPtr) && ((*ret)->codeAddress == codeAddress));
376 //method that retuns set of addresses corresponding to a given line number
377 //the level of the search is file level if isFile flag is set.
378 //If isFile level is not set, it seraches in the given function
379 //in case of success it returns true otherwise false
380 bool FileLineInformation::getAddrFromLine(string name,
381 BPatch_Set<Address>& codeAddress,
382 unsigned short lineNo,bool isFile,
392 beginPtr = lineToAddr;
393 endPtr = (tuple**) (lineToAddr+(size-1));
397 FunctionInfo* fInfo = findFunctionInfo(name);
400 if(!fInfo->validInfo)
402 beginPtr = (tuple**)(lineToAddr+fInfo->startLinePtr->linePtr);
403 endPtr = (tuple**)(lineToAddr+fInfo->endLinePtr->linePtr);
404 howMany = (fInfo->endLinePtr->linePtr-fInfo->startLinePtr->linePtr)+1;
407 (lineNo < (*beginPtr)->lineNo) || ((*endPtr)->lineNo < lineNo))
410 tuple toSearch(lineNo,0);
412 tuple** ret = binarySearchLineFirst(toSearch,beginPtr,howMany,next);
419 lineNo = (*ret)->lineNo;
422 codeAddress += (*ret)->codeAddress;
424 }while((ret <= endPtr) && ((*ret)->lineNo == lineNo));
429 bool FileLineInformation::getMinMaxAddress(int n,Address& min,Address& max){
430 FunctionInfo* fi = lineInformationList[n];
433 min = fi->startAddrPtr->codeAddress;
434 max = fi->endAddrPtr->codeAddress;
438 unsigned short FileLineInformation::getFunctionCount(){
439 return functionCount;
442 string** FileLineInformation::getFunctionNameList(){
443 return functionNameList;
447 //constructor whose argument is the name of the module name
448 LineInformation::LineInformation(string mName)
451 sourceFileList(NULL),
452 lineInformationList(NULL) {}
456 LineInformation::~LineInformation() {
457 for(int i=0;i<sourceFileCount;i++){
458 delete sourceFileList[i];
459 delete lineInformationList[i];
461 free(sourceFileList);
462 free(lineInformationList);
465 //method to insert entries for the given file name and function name
466 //it creates the necessary structures and inserts into the maps
467 void LineInformation::insertSourceFileName(string functionName,string fileName)
469 FileLineInformation* fInfo = getFileLineInformation(fileName);
471 fInfo = new FileLineInformation(fileName);
472 sourceFileList = (string**)(sourceFileCount ?
473 realloc(sourceFileList,(sourceFileCount+1)*sizeof(string*)) :
474 malloc(sizeof(string*)));
475 lineInformationList = (FileLineInformation**)(sourceFileCount ?
476 realloc(lineInformationList,(sourceFileCount+1)*sizeof(FileLineInformation*)) :
477 malloc(sizeof(FileLineInformation*)));
478 sourceFileList[sourceFileCount] = new string(fileName);
479 lineInformationList[sourceFileCount] = fInfo;
482 fInfo->insertFunction(functionName);
485 //inserts line to address and address to line mapping to the line info
486 //object of the given filename. The records for function is also updated
487 void LineInformation::insertLineAddress(string functionName,
489 unsigned short lineNo,
492 FileLineInformation* fInfo = getFileLineInformation(fileName);
494 fInfo->insertLineAddress(functionName,lineNo,codeAddress);
497 //returns line number corresponding to the the given address
498 //if isFile is set the search is file level otherwsie function level.
499 bool LineInformation::getLineFromAddr(string name,
500 unsigned short& lineNo,
505 FileLineInformation* fInfo = NULL;
507 fInfo = getFileLineInformation(name);
509 fInfo = getFunctionLineInformation(name);
511 if(!fInfo) return false;
513 return fInfo->getLineFromAddr(name,lineNo,codeAddress,isFile,isExactMatch);
516 //returns line number corresponding to the the given address
517 //if isFile is set the search is file level otherwsie function level.
518 bool LineInformation::getLineFromAddr(string name,
519 BPatch_Set<unsigned short>& lines,
524 FileLineInformation* fInfo = NULL;
526 fInfo = getFileLineInformation(name);
528 fInfo = getFunctionLineInformation(name);
530 if(!fInfo) return false;
532 return fInfo->getLineFromAddr(name,lines,codeAddress,isFile,isExactMatch);
535 //returns address corresponding to the the given line
536 //if isFile is set the search is file level otherwsie function level.
537 bool LineInformation::getAddrFromLine(string name,
538 BPatch_Set<Address>& codeAddress,
539 unsigned short lineNo,
543 FileLineInformation* fInfo = NULL;
545 fInfo = getFileLineInformation(name);
547 fInfo = getFunctionLineInformation(name);
549 if(!fInfo) return false;
551 return fInfo->getAddrFromLine(name,codeAddress,lineNo,isFile,isExactMatch);
554 bool LineInformation::getAddrFromLine(BPatch_Set<Address>& codeAddress,
555 unsigned short lineNo,
558 FileLineInformation* fInfo = getFileLineInformation(moduleName);
561 cerr << "Module " << moduleName << " is not source file name\n";
565 return fInfo->getAddrFromLine(moduleName,codeAddress,
566 lineNo,true,isExactMatch);
569 //returns the line information for the given filename
570 FileLineInformation* LineInformation::getFileLineInformation(string fileName){
571 for(int j=0;j<sourceFileCount;j++)
572 if(fileName == *sourceFileList[j])
573 return lineInformationList[j];
574 for(int i=0;i<sourceFileCount;i++){
575 char* name = new char[sourceFileList[i]->length()+1];
576 strncpy(name,sourceFileList[i]->string_of(),
577 sourceFileList[i]->length());
578 name[sourceFileList[i]->length()] = '\0';
579 char* p = strrchr(name,'/');
586 if(fileName == sname){
588 return lineInformationList[i];
596 //method retuns the file line information object which the function belongs to.
597 //if there is no entry than it retuns NULL
599 LineInformation::getFunctionLineInformation(string functionName){
600 for(int i=0;i<sourceFileCount;i++)
601 if(lineInformationList[i]->findFunction(functionName))
602 return lineInformationList[i];
606 //method that returns true if function belongs to this object
608 bool LineInformation::findFunction(string functionName){
610 for(int i=0;!ret && (i<sourceFileCount);i++)
611 ret = lineInformationList[i]->findFunction(functionName);
615 //delete the records for function
616 void LineInformation::deleteFunction(string functionName){
617 for(int i=0;i<sourceFileCount;i++)
618 lineInformationList[i]->deleteFunction(functionName);
621 //updates records for a function
622 void LineInformation::insertFunction(string functionName,Address baseAddr,
623 Address functionSize)
625 if(findFunction(functionName))
628 for(int i=0;!ret && (i<sourceFileCount);i++)
629 ret = lineInformationList[i]->insertFunction(functionName,
630 baseAddr,functionSize);
633 string** LineInformation::getSourceFileList(){
634 return sourceFileList;
637 unsigned short LineInformation::getSourceFileCount(){
638 return sourceFileCount;
641 FileLineInformation** LineInformation::getLineInformationList(){
642 return lineInformationList;
645 ostream& operator<<(ostream& os,FileLineInformation& linfo){
647 cerr << "\tLINE TO ADDRESS \t\t ADDRESS TO LINE:\n";
648 for(int j=0;j<linfo.size;j++){
649 os << dec << j << "\t";
650 os << dec << linfo.lineToAddr[j]->lineNo << " ----> ";
651 os << hex << linfo.lineToAddr[j]->codeAddress << "\t\t";
652 os << hex << linfo.addrToLine[j]->codeAddress << " ----> ";
653 os << dec << linfo.addrToLine[j]->lineNo << "\n";
655 for(int i=0;i<linfo.functionCount;i++){
656 FunctionInfo* funcinfo = linfo.lineInformationList[i];
657 os << "FUNCTION LINE : " << *(linfo.functionNameList[i]) << " : " ;
658 if(!funcinfo->validInfo)
660 os << dec << funcinfo->startLinePtr->lineNo << " --- ";
661 os << dec << funcinfo->endLinePtr->lineNo << "\t\t";
662 os << hex << funcinfo->startAddrPtr->codeAddress << " --- ";
663 os << hex << funcinfo->endAddrPtr->codeAddress << "\n";
668 ostream& operator<<(ostream& os,LineInformation& linfo){
669 os << "**********************************************\n";
670 os << "MODULE : " << linfo.moduleName << "\n";
671 os << "**********************************************\n";
672 for(int i=0;i<linfo.sourceFileCount;i++){
673 os << "FILE : " << *(linfo.sourceFileList[i]) << "\n";
674 os << *(linfo.lineInformationList[i]);