00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <assert.h>
00038 #include <string.h>
00039 #include <vector>
00040 #include <algorithm>
00041
00042 #include "common/h/Timer.h"
00043 #include "common/h/debugOstream.h"
00044 #include "common/h/serialize.h"
00045 #include "common/h/pathName.h"
00046
00047 #include "Serialization.h"
00048 #include "Symtab.h"
00049 #include "Module.h"
00050 #include "Collections.h"
00051 #include "Function.h"
00052 #include "Variable.h"
00053 #include "annotations.h"
00054
00055 #include "symtabAPI/src/Object.h"
00056
00057 using namespace Dyninst;
00058 using namespace Dyninst::SymtabAPI;
00059 using namespace std;
00060
00061 extern SymtabError serr;
00062
00063 bool regexEquiv( const std::string &str,const std::string &them, bool checkCase );
00064 bool pattern_match( const char *p, const char *s, bool checkCase );
00065
00066 std::vector<Symbol *> *Symtab::findSymbolByOffset(Offset o)
00067 {
00068
00069 dyn_hash_map<Offset, std::vector<Symbol *> >::iterator iter;
00070 iter = symsByOffset.find(o);
00071 if (iter == symsByOffset.end()) return NULL;
00072 return &(iter->second);
00073 }
00074
00075 bool Symtab::findSymbol(std::vector<Symbol *> &ret, const std::string& name,
00076 Symbol::SymbolType sType, NameType nameType,
00077 bool isRegex, bool checkCase, bool includeUndefined)
00078 {
00079
00080 unsigned old_size = ret.size();
00081
00082 std::vector<Symbol *> candidates;
00083
00084 if (!isRegex) {
00085
00086 if (nameType & mangledName) {
00087 candidates.insert(candidates.end(), symsByMangledName[name].begin(), symsByMangledName[name].end());
00088 if (includeUndefined) candidates.insert(candidates.end(),
00089 undefDynSymsByMangledName[name].begin(),
00090 undefDynSymsByMangledName[name].end());
00091 }
00092 if (nameType & prettyName) {
00093 candidates.insert(candidates.end(), symsByPrettyName[name].begin(), symsByPrettyName[name].end());
00094 if (includeUndefined) candidates.insert(candidates.end(),
00095 undefDynSymsByPrettyName[name].begin(),
00096 undefDynSymsByPrettyName[name].end());
00097 }
00098 if (nameType & typedName) {
00099 candidates.insert(candidates.end(), symsByTypedName[name].begin(), symsByTypedName[name].end());
00100 if (includeUndefined) candidates.insert(candidates.end(),
00101 undefDynSymsByTypedName[name].begin(),
00102 undefDynSymsByTypedName[name].end());
00103 }
00104 }
00105 else {
00106
00107
00108 if (includeUndefined) {
00109 cerr << "Warning: regex search of undefined symbols is not supported" << endl;
00110 }
00111
00112 for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) {
00113 if (nameType & mangledName) {
00114 if (regexEquiv(name, everyDefinedSymbol[i]->getMangledName(), checkCase))
00115 candidates.push_back(everyDefinedSymbol[i]);
00116
00117 }
00118 if (nameType & prettyName) {
00119 if (regexEquiv(name, everyDefinedSymbol[i]->getPrettyName(), checkCase))
00120 candidates.push_back(everyDefinedSymbol[i]);
00121 }
00122 if (nameType & typedName) {
00123 if (regexEquiv(name, everyDefinedSymbol[i]->getTypedName(), checkCase))
00124 candidates.push_back(everyDefinedSymbol[i]);
00125 }
00126 }
00127 }
00128
00129 std::set<Symbol *> matches;
00130
00131 for (std::vector<Symbol *>::iterator iter = candidates.begin();
00132 iter != candidates.end(); ++iter) {
00133 if (sType == Symbol::ST_UNKNOWN ||
00134 sType == Symbol::ST_NOTYPE ||
00135 sType == (*iter)->getType()) {
00136 matches.insert(*iter);
00137 }
00138 }
00139 ret.insert(ret.end(), matches.begin(), matches.end());
00140
00141 if (ret.size() == old_size) {
00142 serr = No_Such_Symbol;
00143 return false;
00144 }
00145 else {
00146 return true;
00147 }
00148 }
00149
00150 bool Symtab::getAllSymbols(std::vector<Symbol *> &ret)
00151 {
00152 ret = everyDefinedSymbol;
00153
00154
00155 std::vector<Symbol *> temp;
00156 std::vector<Symbol *>::iterator it;
00157 getAllUndefinedSymbols(temp);
00158 for (it = temp.begin(); it != temp.end(); it++)
00159 ret.push_back(*it);
00160
00161 if(ret.size() > 0)
00162 return true;
00163 serr = No_Such_Symbol;
00164 return false;
00165 }
00166
00167 bool Symtab::getAllSymbolsByType(std::vector<Symbol *> &ret, Symbol::SymbolType sType)
00168 {
00169 if (sType == Symbol::ST_UNKNOWN)
00170 return getAllSymbols(ret);
00171
00172 unsigned old_size = ret.size();
00173
00174 for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) {
00175 if (everyDefinedSymbol[i]->getType() == sType)
00176 ret.push_back(everyDefinedSymbol[i]);
00177 }
00178
00179 std::vector<Symbol *> temp;
00180 getAllUndefinedSymbols(temp);
00181 for (unsigned i = 0; i < temp.size(); i++) {
00182 if (temp[i]->getType() == sType)
00183 ret.push_back(temp[i]);
00184 }
00185
00186 if (ret.size() > old_size) {
00187 return true;
00188 }
00189 else {
00190 serr = No_Such_Symbol;
00191 return false;
00192 }
00193 }
00194
00195 bool Symtab::getAllDefinedSymbols(std::vector<Symbol *> &ret)
00196 {
00197 ret = everyDefinedSymbol;
00198
00199 if(ret.size() > 0)
00200 return true;
00201 serr = No_Such_Symbol;
00202 return false;
00203 }
00204
00205 bool Symtab::getAllUndefinedSymbols(std::vector<Symbol *> &ret){
00206 unsigned size = ret.size();
00207 ret.insert(ret.end(), undefDynSyms.begin(), undefDynSyms.end());
00208 if(ret.size()>size)
00209 return true;
00210 serr = No_Such_Symbol;
00211 return false;
00212 }
00213
00214 bool Symtab::findFuncByEntryOffset(Function *&ret, const Offset entry)
00215 {
00216
00217
00218
00219
00220
00221
00222 if (funcsByOffset.find(entry) != funcsByOffset.end()) {
00223 ret = funcsByOffset[entry];
00224 return true;
00225 }
00226 serr = No_Such_Function;
00227 return false;
00228 }
00229
00230 bool sort_by_func_ptr(const Function *a, const Function *b) {
00231 return a < b;
00232 }
00233
00234 bool Symtab::findFunctionsByName(std::vector<Function *> &ret, const std::string name,
00235 NameType nameType, bool isRegex, bool checkCase) {
00236 std::vector<Symbol *> funcSyms;
00237 if (!findSymbol(funcSyms, name, Symbol::ST_FUNCTION, nameType, isRegex, checkCase)) {
00238 return false;
00239 }
00240 std::vector<Function *> unsortedFuncs;
00241 for (unsigned i = 0; i < funcSyms.size(); i++)
00242 {
00243 if (doNotAggregate(funcSyms[i])) {
00244 continue;
00245 }
00246 if (!funcSyms[i]->getFunction())
00247 {
00248 fprintf(stderr, "%s[%d]: WARNING: internal inconsistency\n", FILE__, __LINE__);
00249 fprintf(stderr, "%s[%d]: WARNING: %s is %s a function\n", FILE__, __LINE__, name.c_str(), funcSyms[i]->isFunction() ? "" : "not");
00250 fprintf(stderr, "%s[%d]: WARNING: %s is %s a variable\n", FILE__, __LINE__, name.c_str(), funcSyms[i]->isVariable() ? "" : "not");
00251 continue;
00252 }
00253 unsortedFuncs.push_back(funcSyms[i]->getFunction());
00254 }
00255 std::sort(unsortedFuncs.begin(), unsortedFuncs.end(), sort_by_func_ptr);
00256 std::vector<Function *>::iterator endIter;
00257 endIter = std::unique(unsortedFuncs.begin(), unsortedFuncs.end());
00258 for (std::vector<Function *>::iterator iter = unsortedFuncs.begin();
00259 iter != endIter;
00260 iter++)
00261 ret.push_back(*iter);
00262
00263 return true;
00264 }
00265
00266 bool Symtab::getAllFunctions(std::vector<Function *> &ret) {
00267 ret = everyFunction;
00268 return (ret.size() > 0);
00269 }
00270
00271 bool Symtab::findVariableByOffset(Variable *&ret, const Offset offset) {
00272
00273
00274
00275
00276
00277
00278 if (varsByOffset.find(offset) != varsByOffset.end()) {
00279 ret = varsByOffset[offset];
00280 return true;
00281 }
00282 serr = No_Such_Variable;
00283 return false;
00284 }
00285
00286 static bool sort_by_var_ptr(const Variable * a, const Variable *b) {
00287 return a < b;
00288 }
00289
00290 bool Symtab::findVariablesByName(std::vector<Variable *> &ret, const std::string name,
00291 NameType nameType, bool isRegex, bool checkCase) {
00292 std::vector<Symbol *> varSyms;
00293 if (!findSymbol(varSyms, name, Symbol::ST_OBJECT, nameType, isRegex, checkCase))
00294 return false;
00295
00296 std::vector<Variable *> unsortedVars;
00297 for (unsigned i = 0; i < varSyms.size(); i++) {
00298 if (doNotAggregate(varSyms[i])) continue;
00299 unsortedVars.push_back(varSyms[i]->getVariable());
00300 }
00301
00302 std::sort(unsortedVars.begin(), unsortedVars.end(), sort_by_var_ptr);
00303 std::vector<Variable *>::iterator endIter;
00304 endIter = std::unique(unsortedVars.begin(), unsortedVars.end());
00305 for (std::vector<Variable *>::iterator iter = unsortedVars.begin();
00306 iter != endIter;
00307 iter++)
00308 ret.push_back(*iter);
00309
00310 return true;
00311 }
00312
00313 bool Symtab::getAllVariables(std::vector<Variable *> &ret)
00314 {
00315 ret = everyVariable;
00316 return (ret.size() > 0);
00317 }
00318
00319 bool Symtab::getAllModules(std::vector<Module *> &ret)
00320 {
00321 if (_mods.size() >0 )
00322 {
00323 ret = _mods;
00324 return true;
00325 }
00326
00327 serr = No_Such_Module;
00328 return false;
00329 }
00330
00331 bool Symtab::findModuleByOffset(Module *&ret, Offset off)
00332 {
00333
00334 for (unsigned int i = 0; i < _mods.size(); ++i)
00335 {
00336 Module *mod = _mods[i];
00337
00338 if (off == mod->addr())
00339 {
00340 ret = mod;
00341 return true;
00342 }
00343 }
00344 return false;
00345 }
00346
00347 bool Symtab::findModuleByName(Module *&ret, const std::string name)
00348 {
00349 dyn_hash_map<std::string, Module *>::iterator loc;
00350 loc = modsByFullName.find(name);
00351
00352 if (loc != modsByFullName.end())
00353 {
00354 ret = loc->second;
00355 return true;
00356 }
00357
00358 std::string tmp = extract_pathname_tail(name);
00359
00360 loc = modsByFileName.find(tmp);
00361
00362 if (loc != modsByFileName.end())
00363 {
00364 ret = loc->second;
00365 return true;
00366 }
00367
00368 serr = No_Such_Module;
00369 ret = NULL;
00370 return false;
00371 }
00372
00373 bool Symtab::getAllRegions(std::vector<Region *>&ret)
00374 {
00375 if (regions_.size() > 0)
00376 {
00377 ret = regions_;
00378 return true;
00379 }
00380
00381 return false;
00382 }
00383
00384 bool Symtab::getCodeRegions(std::vector<Region *>&ret)
00385 {
00386 if (codeRegions_.size() > 0)
00387 {
00388 ret = codeRegions_;
00389 return true;
00390 }
00391
00392 return false;
00393 }
00394
00395 bool Symtab::getDataRegions(std::vector<Region *>&ret)
00396 {
00397 if (dataRegions_.size() > 0)
00398 {
00399 ret = dataRegions_;
00400 return true;
00401 }
00402 return false;
00403 }
00404
00405
00406 bool Symtab::getAllNewRegions(std::vector<Region *>&ret)
00407 {
00408 std::vector<Region *> *retp = NULL;
00409
00410 if (!getAnnotation(retp, UserRegionsAnno))
00411 {
00412 return false;
00413 }
00414
00415 if (!retp)
00416 {
00417 return false;
00418 }
00419
00420 ret = *retp;
00421
00422 return true;
00423 }
00424
00425 bool Symtab::getAllExceptions(std::vector<ExceptionBlock *> &exceptions)
00426 {
00427 if (excpBlocks.size()>0)
00428 {
00429 exceptions = excpBlocks;
00430 return true;
00431 }
00432
00433 return false;
00434 }
00435
00436
00437 bool Symtab::findException(ExceptionBlock &excp, Offset addr)
00438 {
00439 for (unsigned i=0; i<excpBlocks.size(); i++)
00440 {
00441 if (excpBlocks[i]->contains(addr))
00442 {
00443 excp = *(excpBlocks[i]);
00444 return true;
00445 }
00446 }
00447
00448 return false;
00449 }
00450
00451
00452
00453
00454
00455 bool Symtab::findCatchBlock(ExceptionBlock &excp, Offset addr, unsigned size)
00456 {
00457 int min = 0;
00458 int max = excpBlocks.size();
00459 int cur = -1, last_cur;
00460
00461 if (max == 0)
00462 return false;
00463
00464
00465 while (true)
00466 {
00467 last_cur = cur;
00468 cur = (min + max) / 2;
00469
00470 if (last_cur == cur)
00471 return false;
00472
00473 Offset curAddr = excpBlocks[cur]->catchStart();
00474 if ((curAddr <= addr && curAddr+size > addr) ||
00475 (size == 0 && curAddr == addr))
00476 {
00477
00478 excp = *(excpBlocks[cur]);
00479 return true;
00480 }
00481 if (addr < curAddr)
00482 max = cur;
00483 else if (addr > curAddr)
00484 min = cur;
00485 }
00486 }
00487
00488 bool Symtab::findRegionByEntry(Region *&ret, const Offset offset)
00489 {
00490 if(regionsByEntryAddr.find(offset) != regionsByEntryAddr.end())
00491 {
00492 ret = regionsByEntryAddr[offset];
00493 return true;
00494 }
00495 serr = No_Such_Region;
00496 return false;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 Region *Symtab::findEnclosingRegion(const Offset where)
00508 {
00509 int first = 0;
00510 int last = regions_.size() - 1;
00511 while (last >= first) {
00512 Region *curreg = regions_[(first + last) / 2];
00513 if (where >= curreg->getMemOffset()
00514 && where < (curreg->getMemOffset()
00515 + curreg->getMemSize())) {
00516 return curreg;
00517 }
00518 else if (where < curreg->getMemOffset()) {
00519 last = ((first + last) / 2) - 1;
00520 }
00521 else {
00522
00523 first = ((first + last) / 2) + 1;
00524 }
00525 }
00526 return NULL;
00527 }
00528
00529 bool Symtab::findRegion(Region *&ret, const std::string secName)
00530 {
00531 for(unsigned index=0;index<regions_.size();index++)
00532 {
00533 if(regions_[index]->getRegionName() == secName)
00534 {
00535 ret = regions_[index];
00536 return true;
00537 }
00538 }
00539 serr = No_Such_Region;
00540 return false;
00541 }
00542
00543
00544 bool Symtab::findRegion(Region *&ret, const Offset addr, const unsigned long size)
00545 {
00546 ret = NULL;
00547 for(unsigned index=0;index<regions_.size();index++) {
00548 if(regions_[index]->getMemOffset() == addr && regions_[index]->getMemSize() == size) {
00549 if (ret) {
00550 #if 0
00551 cerr << "Error: region inconsistency" << endl;
00552 cerr << "\t" << ret->getRegionName() << " @ "
00553 << hex << ret->getMemOffset() << "/" << ret->getMemSize()
00554 << ", type " << Region::regionType2Str(ret->getRegionType()) << endl;
00555 cerr << "\t" << regions_[index]->getRegionName() << " @ "
00556 << regions_[index]->getMemOffset() << "/" << regions_[index]->getMemSize()
00557 << ", type " << Region::regionType2Str(regions_[index]->getRegionType()) << endl;
00558 #endif
00559 assert((addr == 0) ||
00560 (ret->getRegionType() == Region::RT_BSS) ||
00561 (regions_[index]->getRegionType() == Region::RT_BSS));
00562
00563
00564 if (ret->getRegionType() == Region::RT_BSS) {
00565 ret = regions_[index];
00566 }
00567
00568
00569 serr = Multiple_Region_Matches;
00570 return false;
00571 }
00572 ret = regions_[index];
00573 }
00574 }
00575 if (ret) return true;
00576 serr = No_Such_Region;
00577 return false;
00578 }
00579
00580
00581
00582
00583
00584 bool regexEquiv( const std::string &str,const std::string &them, bool checkCase )
00585 {
00586 const char *str_ = str.c_str();
00587 const char *s = them.c_str();
00588
00589
00590 return pattern_match(str_, s, checkCase);
00591
00592 }
00593
00594
00595
00596
00597
00598
00599
00600 bool
00601 pattern_match( const char *p, const char *s, bool checkCase ) {
00602
00603
00604
00605 while ( true ) {
00606
00607 if( *p == '\0' )
00608 return ( *s == '\0' );
00609
00610
00611 if( *p == MULTIPLE_WILDCARD_CHARACTER ) {
00612 ++p;
00613
00614
00615 if( *p == '\0' )
00616 return true;
00617
00618
00619 for(; *s != '\0'; ++s )
00620 if( pattern_match( p, s, checkCase ) )
00621 return true;
00622
00623 return false;
00624 }
00625
00626
00627 if( *s == '\0' )
00628 return false;
00629
00630
00631 bool matchChar = false;
00632 if( *p == WILDCARD_CHARACTER || *p == *s )
00633 matchChar = true;
00634 else if( !checkCase ) {
00635 if( *p >= 'A' && *p <= 'Z' && *s == ( *p + ( 'a' - 'A' ) ) )
00636 matchChar = true;
00637 else if( *p >= 'a' && *p <= 'z' && *s == ( *p - ( 'a' - 'A' ) ) )
00638 matchChar = true;
00639 }
00640
00641 if( matchChar ) {
00642 ++p;
00643 ++s;
00644 continue;
00645 }
00646
00647
00648 return false;
00649 }
00650 }
00651
00652 struct Dyninst::SymtabAPI::SymbolCompareByAddr
00653 {
00654 bool operator()(Function *a, Function *b)
00655 {
00656 return (a->offset_ < b->offset_);
00657 }
00658 };
00659
00660 bool Symtab::getContainingFunction(Offset offset, Function* &func)
00661 {
00662 if (!isCode(offset)) {
00663 return false;
00664 }
00665 if (everyFunction.size() && !sorted_everyFunction)
00666 {
00667 std::sort(everyFunction.begin(), everyFunction.end(),
00668 SymbolCompareByAddr());
00669 sorted_everyFunction = true;
00670 }
00671
00672 unsigned low = 0;
00673 unsigned high = everyFunction.size();
00674 unsigned last_mid = high+1;
00675 unsigned mid;
00676 if (!high) return false;
00677 for (;;)
00678 {
00679 mid = (low + high) / 2;
00680 if (last_mid == mid)
00681 break;
00682 last_mid = mid;
00683 Offset cur = everyFunction[mid]->getOffset();
00684 if (cur > offset) {
00685 high = mid;
00686 continue;
00687 }
00688 if (cur < offset) {
00689 low = mid;
00690 continue;
00691 }
00692 if (cur == offset) {
00693 func = everyFunction[mid];
00694 return true;
00695 }
00696 }
00697
00698 if ((everyFunction[low]->getOffset() <= offset) &&
00699 ((low+1 == everyFunction.size()) ||
00700 (everyFunction[low+1]->getOffset() > offset)))
00701 {
00702 func = everyFunction[low];
00703 return true;
00704 }
00705 return false;
00706 }
00707
00708 Module *Symtab::getDefaultModule() {
00709 Module *mod = NULL;
00710
00711
00712 if (_mods.size() == 1)
00713 return _mods[0];
00714 else {
00715 if (!findModuleByName(mod, "DEFAULT_MODULE"))
00716 return NULL;
00717 }
00718 return mod;
00719 }
00720
00721 unsigned Function::getSize() {
00722 if (functionSize_)
00723 return functionSize_;
00724 for (unsigned i=0; i<symbols_.size(); i++) {
00725 if (symbols_[i]->getSize()) {
00726 functionSize_ = symbols_[i]->getSize();;
00727 return functionSize_;
00728 }
00729 }
00730
00731 Symtab *symtab = getFirstSymbol()->getSymtab();
00732 if (symtab->everyFunction.size() && !symtab->sorted_everyFunction)
00733 {
00734 std::sort(symtab->everyFunction.begin(), symtab->everyFunction.end(),
00735 SymbolCompareByAddr());
00736 symtab->sorted_everyFunction = true;
00737 }
00738
00739 Offset offset = getOffset();
00740 unsigned low = 0;
00741 unsigned high = symtab->everyFunction.size();
00742 unsigned last_mid = high+1;
00743 unsigned mid;
00744 for (;;)
00745 {
00746 mid = (low + high) / 2;
00747 if (last_mid == mid)
00748 return 0;
00749 last_mid = mid;
00750 Offset cur = symtab->everyFunction[mid]->getOffset();
00751 if (cur > offset) {
00752 high = mid;
00753 continue;
00754 }
00755 if (cur < offset) {
00756 low = mid;
00757 continue;
00758 }
00759 if (cur == offset) {
00760 if (mid + 1 >= symtab->everyFunction.size())
00761 return 0;
00762 Function *next_func = symtab->everyFunction[mid+1];
00763 functionSize_ = next_func->getOffset() - getOffset();
00764 return functionSize_;
00765 }
00766 }
00767 }
00768
00769 Dyninst::Offset Symtab::fileToDiskOffset(Dyninst::Offset fileOffset) const {
00770 for (unsigned j = 0; j < regions_.size(); ++j) {
00771 if (regions_[j]->getFileOffset() <= fileOffset &&
00772 ((regions_[j]->getFileOffset() + regions_[j]->getDiskSize()) > fileOffset)) {
00773 return fileOffset - regions_[j]->getFileOffset() + regions_[j]->getDiskOffset();
00774 }
00775 }
00776 return (Dyninst::Offset) -1;
00777 }
00778
00779 Dyninst::Offset Symtab::fileToMemOffset(Dyninst::Offset fileOffset) const {
00780 for (unsigned j = 0; j < regions_.size(); ++j) {
00781 if (regions_[j]->getFileOffset() <= fileOffset &&
00782 ((regions_[j]->getFileOffset() + regions_[j]->getDiskSize()) > fileOffset)) {
00783 return fileOffset - regions_[j]->getFileOffset() + regions_[j]->getMemOffset();
00784 }
00785 }
00786 return (Dyninst::Offset) -1;
00787 }