Merge branch 'master' into NewInstpoint
[dyninst.git] / symtabAPI / src / Symtab-lookup.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 /* Lookup functions defined in class Symtab. Separated to reduce file size and classify. */
33
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <string.h>
40 #include <vector>
41 #include <algorithm>
42
43 #include "common/h/Timer.h"
44 #include "common/h/debugOstream.h"
45 #include "common/h/serialize.h"
46 #include "common/h/pathName.h"
47
48 #include "Serialization.h"
49 #include "Symtab.h"
50 #include "Module.h"
51 #include "Collections.h"
52 #include "Function.h"
53 #include "Variable.h"
54 #include "annotations.h"
55
56 #include "symtabAPI/src/Object.h"
57
58 using namespace Dyninst;
59 using namespace Dyninst::SymtabAPI;
60 using namespace std;
61
62 extern SymtabError serr;
63
64 bool regexEquiv( const std::string &str,const std::string &them, bool checkCase );
65 bool pattern_match( const char *p, const char *s, bool checkCase );
66
67 static bool sort_by_sym_ptr(const Symbol *a, const Symbol *b) {
68     return a < b;
69 }
70
71 std::vector<Symbol *> *Symtab::findSymbolByOffset(Offset o)
72 {
73         //Symbol *s = NULL;
74         dyn_hash_map<Offset, std::vector<Symbol *> >::iterator iter;
75         iter = symsByOffset.find(o);
76         if (iter == symsByOffset.end()) return NULL;
77         return &(iter->second);
78 }
79
80 bool Symtab::findSymbol(std::vector<Symbol *> &ret, const std::string name,
81                         Symbol::SymbolType sType, NameType nameType,
82                         bool isRegex, bool checkCase)
83 {
84     unsigned old_size = ret.size();
85
86     std::vector<Symbol *> symsMangled;
87     std::vector<Symbol *> symsPretty;
88     std::vector<Symbol *> symsTyped;
89
90     if (!isRegex) {
91         // Easy case
92         if (nameType & mangledName) {
93             symsMangled = symsByMangledName[name];
94         }
95         if (nameType & prettyName) {
96             symsPretty = symsByPrettyName[name];
97 #if 0
98             if (name == ("DYNINSTthreadIndex")) {
99                 printf("looking for %s\n", name.c_str());
100             }
101             dyn_hash_map <std::string, std::vector<Symbol *> >::iterator 
102                 pit = symsByPrettyName.find(name);
103             if (symsByPrettyName.end() != pit) {
104                 symsPretty = symsByPrettyName[name];
105             } else {
106                 if (name == ("DYNINSTthreadIndex")) {
107                     printf("couldn't find %s\n", name.c_str());
108                 }
109             }
110 #endif
111         }
112         if (nameType & typedName) {
113             symsTyped = symsByTypedName[name];
114         }
115     }
116     else {
117         // Build the regex list of symbols
118         // We need to iterate over every single symbol. Ugh.
119         for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) {
120             if (nameType & mangledName) {
121                 if (regexEquiv(name, everyDefinedSymbol[i]->getName(), checkCase))
122                     symsMangled.push_back(everyDefinedSymbol[i]);
123             }
124             if (nameType & prettyName) {
125                 if (regexEquiv(name, everyDefinedSymbol[i]->getPrettyName(), checkCase))
126                     symsPretty.push_back(everyDefinedSymbol[i]);
127             }
128             if (nameType & typedName) {
129                 if (regexEquiv(name, everyDefinedSymbol[i]->getTypedName(), checkCase))
130                     symsTyped.push_back(everyDefinedSymbol[i]);
131             }
132         }
133     }
134
135     std::vector<Symbol *> allSyms;
136     
137     for (unsigned i = 0; i < symsMangled.size(); i++) {
138         if (   (sType == Symbol::ST_UNKNOWN) 
139             || (sType == Symbol::ST_NOTYPE)
140             || (symsMangled[i]->getType() == sType))
141             allSyms.push_back(symsMangled[i]);
142     }
143     for (unsigned i = 0; i < symsPretty.size(); i++) {
144         if    ((sType == Symbol::ST_UNKNOWN) 
145            || (sType == Symbol::ST_NOTYPE)
146            || (symsPretty[i]->getType() == sType))
147             allSyms.push_back(symsPretty[i]);
148     }
149     for (unsigned i = 0; i < symsTyped.size(); i++) {
150         if     ((sType == Symbol::ST_UNKNOWN) 
151             || (sType == Symbol::ST_NOTYPE)
152             || (symsTyped[i]->getType() == sType))
153             allSyms.push_back(symsTyped[i]);
154     }
155     
156     std::sort(allSyms.begin(), allSyms.end(), sort_by_sym_ptr);
157     std::vector<Symbol *>::iterator endIter;
158     endIter = std::unique(allSyms.begin(), allSyms.end());
159     ret.insert(ret.end(), allSyms.begin(), endIter);
160
161     if (ret.size() == old_size) {
162         serr = No_Such_Symbol;
163         return false;
164     }
165     else {
166         return true;
167     }
168 }
169
170 bool Symtab::getAllSymbols(std::vector<Symbol *> &ret)
171 {
172     ret = everyDefinedSymbol;
173
174     // add undefined symbols
175     std::vector<Symbol *> temp;
176     std::vector<Symbol *>::iterator it;
177     getAllUndefinedSymbols(temp);
178     for (it = temp.begin(); it != temp.end(); it++)
179         ret.push_back(*it);
180
181     if(ret.size() > 0)
182         return true;
183     serr = No_Such_Symbol;
184     return false;
185 }
186
187 bool Symtab::getAllSymbolsByType(std::vector<Symbol *> &ret, Symbol::SymbolType sType)
188 {
189     if (sType == Symbol::ST_UNKNOWN)
190         return getAllSymbols(ret);
191
192     unsigned old_size = ret.size();
193     // Filter by the given type
194     for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) {
195         if (everyDefinedSymbol[i]->getType() == sType)
196             ret.push_back(everyDefinedSymbol[i]);
197     }
198     // add undefined symbols
199     std::vector<Symbol *> temp;
200     getAllUndefinedSymbols(temp);
201     for (unsigned i = 0; i < temp.size(); i++) {
202         if (temp[i]->getType() == sType)
203             ret.push_back(temp[i]);
204     }
205
206     if (ret.size() > old_size) {
207         return true;
208     }
209     else {
210         serr = No_Such_Symbol;
211         return false;
212     }
213 }
214
215 bool Symtab::getAllDefinedSymbols(std::vector<Symbol *> &ret)
216 {
217     ret = everyDefinedSymbol;
218
219     if(ret.size() > 0)
220         return true;
221     serr = No_Such_Symbol;
222     return false;
223 }
224  
225 bool Symtab::getAllUndefinedSymbols(std::vector<Symbol *> &ret){
226     unsigned size = ret.size();
227     map<string, std::vector<Symbol *> >::iterator it;
228     std::vector<Symbol *>::iterator it2;
229     for (it = undefDynSyms.begin(); it != undefDynSyms.end(); it++)
230         for (it2 = it->second.begin(); it2 != it->second.end(); it2++)
231             ret.push_back(*it2);
232     if(ret.size()>size)
233         return true;
234     serr = No_Such_Symbol;
235     return false;
236 }
237
238 bool Symtab::findFuncByEntryOffset(Function *&ret, const Offset entry)
239 {
240     /* XXX
241      *
242      * When working with relocatable files, a symbol is not uniquely identified
243      * by its offset; it is uniquely identified by its Region and its offset.
244      * This discrepancy is not taken into account here.
245      */
246     if (funcsByOffset.find(entry) != funcsByOffset.end()) {
247         ret = funcsByOffset[entry];
248         return true;
249     }
250     serr = No_Such_Function;
251     return false;
252 }
253
254 bool sort_by_func_ptr(const Function *a, const Function *b) {
255     return a < b;
256 }
257
258 bool Symtab::findFunctionsByName(std::vector<Function *> &ret, const std::string name,
259                                  NameType nameType, bool isRegex, bool checkCase) {
260     std::vector<Symbol *> funcSyms;
261     if (!findSymbol(funcSyms, name, Symbol::ST_FUNCTION, nameType, isRegex, checkCase))
262         return false;
263
264     std::vector<Function *> unsortedFuncs;
265     for (unsigned i = 0; i < funcSyms.size(); i++) 
266     {
267         if (doNotAggregate(funcSyms[i])) continue;
268         if (!funcSyms[i]->getFunction())
269         {
270             fprintf(stderr, "%s[%d]:  WARNING:  internal inconsistency\n", FILE__, __LINE__);
271             fprintf(stderr, "%s[%d]:  WARNING:  %s is %s a function\n", FILE__, __LINE__, name.c_str(), funcSyms[i]->isFunction() ? "" : "not");
272             fprintf(stderr, "%s[%d]:  WARNING:  %s is %s a variable\n", FILE__, __LINE__, name.c_str(), funcSyms[i]->isVariable() ? "" : "not");
273             continue;
274         }
275         unsortedFuncs.push_back(funcSyms[i]->getFunction());
276     }
277
278     std::sort(unsortedFuncs.begin(), unsortedFuncs.end(), sort_by_func_ptr);
279     std::vector<Function *>::iterator endIter;
280     endIter = std::unique(unsortedFuncs.begin(), unsortedFuncs.end());
281     for (std::vector<Function *>::iterator iter = unsortedFuncs.begin();
282          iter != endIter;
283          iter++)
284         ret.push_back(*iter);
285
286     return true;
287 }
288
289 bool Symtab::getAllFunctions(std::vector<Function *> &ret) {
290     ret = everyFunction;
291     return (ret.size() > 0);
292 }
293
294 bool Symtab::findVariableByOffset(Variable *&ret, const Offset offset) {
295
296     /* XXX
297      *
298      * See comment in findFuncByOffset about uniqueness of symbols in
299      * relocatable files -- this discrepancy applies here as well.
300      */
301     if (varsByOffset.find(offset) != varsByOffset.end()) {
302         ret = varsByOffset[offset];
303         return true;
304     }
305     serr = No_Such_Variable;
306     return false;
307 }
308
309 static bool sort_by_var_ptr(const Variable * a, const Variable *b) {
310     return a < b;
311 }
312
313 bool Symtab::findVariablesByName(std::vector<Variable *> &ret, const std::string name,
314                                  NameType nameType, bool isRegex, bool checkCase) {
315     std::vector<Symbol *> varSyms;
316     if (!findSymbol(varSyms, name, Symbol::ST_OBJECT, nameType, isRegex, checkCase))
317         return false;
318
319     std::vector<Variable *> unsortedVars;
320     for (unsigned i = 0; i < varSyms.size(); i++) {
321         if (doNotAggregate(varSyms[i])) continue;
322         unsortedVars.push_back(varSyms[i]->getVariable());
323     }
324
325     std::sort(unsortedVars.begin(), unsortedVars.end(), sort_by_var_ptr);
326     std::vector<Variable *>::iterator endIter;
327     endIter = std::unique(unsortedVars.begin(), unsortedVars.end());
328     for (std::vector<Variable *>::iterator iter = unsortedVars.begin();
329          iter != endIter;
330          iter++)
331         ret.push_back(*iter);
332
333     return true;
334 }
335
336 bool Symtab::getAllVariables(std::vector<Variable *> &ret) 
337 {
338     ret = everyVariable;
339     return (ret.size() > 0);
340 }
341
342 bool Symtab::getAllModules(std::vector<Module *> &ret)
343 {
344     if (_mods.size() >0 )
345     {
346         ret = _mods;
347         return true;
348     }   
349
350     serr = No_Such_Module;
351     return false;
352 }
353
354 bool Symtab::findModuleByOffset(Module *&ret, Offset off)
355 {   
356    //  this should be a hash, really
357    for (unsigned int i = 0; i < _mods.size(); ++i) 
358    {
359       Module *mod = _mods[i];
360
361       if (off == mod->addr()) 
362       {
363           ret = mod;
364           return true;
365       }
366    } 
367    return false;
368 }
369
370 bool Symtab::findModuleByName(Module *&ret, const std::string name)
371 {
372    dyn_hash_map<std::string, Module *>::iterator loc;
373    loc = modsByFileName.find(name);
374
375    if (loc != modsByFileName.end()) 
376    {
377       ret = loc->second;
378       return true;
379    }
380
381    loc = modsByFullName.find(name);
382
383    if (loc != modsByFullName.end()) 
384    {
385       ret = loc->second;
386       return true;
387    }
388
389    serr = No_Such_Module;
390    ret = NULL;
391    return false;
392 }
393
394 bool Symtab::getAllRegions(std::vector<Region *>&ret)
395 {
396    if (regions_.size() > 0)
397    {
398       ret = regions_;
399       return true;
400    }
401
402    return false;
403 }
404
405 bool Symtab::getCodeRegions(std::vector<Region *>&ret)
406 {
407    if (codeRegions_.size() > 0)
408    {
409       ret = codeRegions_;
410       return true;
411    }
412
413    return false;
414 }
415
416 bool Symtab::getDataRegions(std::vector<Region *>&ret)
417 {
418    if (dataRegions_.size() > 0)
419    {
420       ret = dataRegions_;
421       return true;
422    }
423    return false;
424 }
425
426
427 bool Symtab::getAllNewRegions(std::vector<Region *>&ret)
428 {
429    std::vector<Region *> *retp = NULL;
430
431    if (!getAnnotation(retp, UserRegionsAnno))
432    {
433       fprintf(stderr, "%s[%d]:  failed to get annotations here\n", FILE__, __LINE__);
434       return false;
435    }
436
437    if (!retp)
438    {
439       fprintf(stderr, "%s[%d]:  failed to get annotations here\n", FILE__, __LINE__);
440       return false;
441    }
442
443    ret = *retp;
444
445    return true;
446 }
447
448 bool Symtab::getAllExceptions(std::vector<ExceptionBlock *> &exceptions)
449 {
450    if (excpBlocks.size()>0)
451    {
452       exceptions = excpBlocks;
453       return true;
454    }    
455
456    return false;
457 }
458
459
460 bool Symtab::findException(ExceptionBlock &excp, Offset addr)
461 {
462    for (unsigned i=0; i<excpBlocks.size(); i++)
463    {
464       if (excpBlocks[i]->contains(addr))
465       {
466          excp = *(excpBlocks[i]);
467          return true;
468       } 
469    }
470
471    return false;
472 }
473
474 /**
475  * Returns true if the Address range addr -> addr+size contains
476  * a catch block, with excp pointing to the appropriate block
477  **/
478 bool Symtab::findCatchBlock(ExceptionBlock &excp, Offset addr, unsigned size)
479 {
480     int min = 0;
481     int max = excpBlocks.size();
482     int cur = -1, last_cur;
483
484     if (max == 0)
485         return false;
486
487     //Binary search through vector for address
488     while (true)
489     {
490         last_cur = cur;
491         cur = (min + max) / 2;
492     
493         if (last_cur == cur)
494             return false;
495
496         Offset curAddr = excpBlocks[cur]->catchStart();
497         if ((curAddr <= addr && curAddr+size > addr) ||
498             (size == 0 && curAddr == addr))
499         {
500             //Found it
501             excp = *(excpBlocks[cur]);
502             return true;
503         }
504         if (addr < curAddr)
505             max = cur;
506         else if (addr > curAddr)
507             min = cur;
508     }
509 }
510  
511 bool Symtab::findRegionByEntry(Region *&ret, const Offset offset)
512 {
513     if(regionsByEntryAddr.find(offset) != regionsByEntryAddr.end())
514     {
515         ret = regionsByEntryAddr[offset];
516         return true;
517     }
518     serr = No_Such_Region;
519     return false;
520 }
521
522 /* Similar to binary search in isCode with the exception that here we
523  * search to the end of regions without regards to whether they have
524  * corresponding raw data on disk, and searches all regions.  
525  *
526  * regions_ elements that start at address 0 may overlap, ELF binaries
527  * have 0 address iff they are not loadable, but xcoff places loadable
528  * sections at address 0, including .text and .data
529  */
530 Region *Symtab::findEnclosingRegion(const Offset where)
531 {
532 #if defined (os_aix) // regions overlap so do sequential search
533     // try code regions first, then data, regions_ vector as last resort
534     for (unsigned rIdx=0; rIdx < codeRegions_.size(); rIdx++) {
535         if (where >= codeRegions_[rIdx]->getRegionAddr() &&
536             where < (codeRegions_[rIdx]->getRegionAddr() 
537                      + codeRegions_[rIdx]->getMemSize())) {
538             return codeRegions_[rIdx];
539         }
540     }
541     for (unsigned rIdx=0; rIdx < dataRegions_.size(); rIdx++) {
542         if (where >= dataRegions_[rIdx]->getRegionAddr() &&
543             where < (dataRegions_[rIdx]->getRegionAddr() 
544                      + dataRegions_[rIdx]->getMemSize())) {
545             return dataRegions_[rIdx];
546         }
547     }
548     for (unsigned rIdx=0; rIdx < regions_.size(); rIdx++) {
549         if (where >= regions_[rIdx]->getRegionAddr() &&
550             where < (regions_[rIdx]->getRegionAddr() 
551                      + regions_[rIdx]->getMemSize())) {
552             return regions_[rIdx];
553         }
554     }
555     return NULL;
556 #endif
557     int first = 0; 
558     int last = regions_.size() - 1;
559     while (last >= first) {
560         Region *curreg = regions_[(first + last) / 2];
561         if (where >= curreg->getRegionAddr()
562             && where < (curreg->getRegionAddr()
563                         + curreg->getMemSize())) {
564             return curreg;
565         }
566         else if (where < curreg->getRegionAddr()) {
567             last = ((first + last) / 2) - 1;
568         }
569         else {/* where >= (cursec->getSecAddr()
570                            + cursec->getSecSize()) */
571             first = ((first + last) / 2) + 1;
572         }
573     }
574     return NULL;
575 }
576
577 bool Symtab::findRegion(Region *&ret, const std::string secName)
578 {
579     for(unsigned index=0;index<regions_.size();index++)
580     {
581         if(regions_[index]->getRegionName() == secName)
582         {
583             ret = regions_[index];
584             return true;
585         }
586     }
587     serr = No_Such_Region;
588     return false;
589 }
590
591
592 bool Symtab::findRegion(Region *&ret, const Offset addr, const unsigned long size)
593 {
594     for(unsigned index=0;index<regions_.size();index++)
595     {
596         if(regions_[index]->getRegionAddr() == addr && regions_[index]->getRegionSize() == size)
597         {
598             ret = regions_[index];
599             return true;
600         }
601     }
602     serr = No_Such_Region;
603     return false;
604 }
605
606 ///////////////////////// REGEX //////////////////////
607
608 // Use POSIX regular expression pattern matching to check if std::string s matches
609 // the pattern in this std::string
610 bool regexEquiv( const std::string &str,const std::string &them, bool checkCase ) 
611 {
612    const char *str_ = str.c_str();
613    const char *s = them.c_str();
614    // Would this work under NT?  I don't know.
615    //#if !defined(os_windows)
616     return pattern_match(str_, s, checkCase);
617
618 }
619
620 // This function will match string s against pattern p.
621 // Asterisks match 0 or more wild characters, and a question
622 // mark matches exactly one wild character.  In other words,
623 // the asterisk is the equivalent of the regex ".*" and the
624 // question mark is the equivalent of "."
625
626 bool
627 pattern_match( const char *p, const char *s, bool checkCase ) {
628    //const char *p = ptrn;
629    //char *s = str;
630
631     while ( true ) {
632         // If at the end of the pattern, it matches if also at the end of the string
633         if( *p == '\0' )
634             return ( *s == '\0' );
635
636         // Process a '*'
637         if( *p == MULTIPLE_WILDCARD_CHARACTER ) {
638             ++p;
639
640             // If at the end of the pattern, it matches
641             if( *p == '\0' )
642                 return true;
643
644             // Try to match the remaining pattern for each remaining substring of s
645             for(; *s != '\0'; ++s )
646                 if( pattern_match( p, s, checkCase ) )
647                     return true;
648             // Failed
649             return false;
650         }
651
652         // If at the end of the string (and at this point, not of the pattern), it fails
653         if( *s == '\0' )
654             return false;
655
656         // Check if this character matches
657         bool matchChar = false;
658         if( *p == WILDCARD_CHARACTER || *p == *s )
659             matchChar = true;
660         else if( !checkCase ) {
661             if( *p >= 'A' && *p <= 'Z' && *s == ( *p + ( 'a' - 'A' ) ) )
662                 matchChar = true;
663             else if( *p >= 'a' && *p <= 'z' && *s == ( *p - ( 'a' - 'A' ) ) )
664                 matchChar = true;
665         }
666
667         if( matchChar ) {
668             ++p;
669             ++s;
670             continue;
671         }
672
673         // Did not match
674         return false;
675     }
676 }
677
678 struct Dyninst::SymtabAPI::SymbolCompareByAddr
679 {
680     bool operator()(Function *a, Function *b)
681     {
682        return (a->offset_ < b->offset_);
683     }
684 };
685
686 bool Symtab::getContainingFunction(Offset offset, Function* &func)
687 {
688    if (!isCode(offset)) {
689       return false;
690    }
691    if (everyFunction.size() && !sorted_everyFunction)
692    {
693       std::sort(everyFunction.begin(), everyFunction.end(),
694                 SymbolCompareByAddr());
695       sorted_everyFunction = true;
696    }
697    
698    unsigned low = 0;
699    unsigned high = everyFunction.size();
700    unsigned last_mid = high+1;
701    unsigned mid;
702    if (!high) return false;
703    for (;;)
704    {
705       mid = (low + high) / 2;
706       if (last_mid == mid)
707          break;
708       last_mid = mid;
709       Offset cur = everyFunction[mid]->getOffset();
710       if (cur > offset) {
711          high = mid;
712          continue;
713       }
714       if (cur < offset) {
715          low = mid;
716          continue;
717       }
718       if (cur == offset) {
719          func = everyFunction[mid];
720          return true;
721       }
722    }
723
724    if ((everyFunction[low]->getOffset() <= offset) &&
725        ((low+1 == everyFunction.size()) || 
726         (everyFunction[low+1]->getOffset() > offset)))
727    {
728          func = everyFunction[low];
729          return true;
730    }
731    return false;
732 }
733
734 Module *Symtab::getDefaultModule() {
735     Module *mod = NULL;
736     // TODO: automatically pick the module that contains this address?
737     // For now, DEFAULT_MODULE or (if we have only one) that one.
738     if (_mods.size() == 1)
739         return _mods[0];
740     else {
741         if (!findModuleByName(mod, "DEFAULT_MODULE"))
742             return NULL;
743     }
744     return mod;
745 }
746
747 unsigned Function::getSize() {
748    if (functionSize_)
749       return functionSize_;
750    for (unsigned i=0; i<symbols_.size(); i++) {
751       if (symbols_[i]->getSize()) { 
752          functionSize_ = symbols_[i]->getSize();;
753          return functionSize_;
754       }
755    }
756
757    Symtab *symtab = getFirstSymbol()->getSymtab();
758    if (symtab->everyFunction.size() && !symtab->sorted_everyFunction)
759    {
760       std::sort(symtab->everyFunction.begin(), symtab->everyFunction.end(),
761                 SymbolCompareByAddr());
762       symtab->sorted_everyFunction = true;
763    }
764
765    Offset offset = getOffset();
766    unsigned low = 0;
767    unsigned high = symtab->everyFunction.size();
768    unsigned last_mid = high+1;
769    unsigned mid;
770    for (;;)
771    {
772       mid = (low + high) / 2;
773       if (last_mid == mid)
774          return 0;
775       last_mid = mid;
776       Offset cur = symtab->everyFunction[mid]->getOffset();
777       if (cur > offset) {
778          high = mid;
779          continue;
780       }
781       if (cur < offset) {
782          low = mid;
783          continue;
784       }
785       if (cur == offset) {
786          if (mid + 1 >= symtab->everyFunction.size())
787             return 0;
788          Function *next_func = symtab->everyFunction[mid+1];
789          functionSize_ = next_func->getOffset() - getOffset();
790          return functionSize_;
791       }
792    }
793 }
794