Warning cleanup. Applying RH's Dyninst patches to 8.1, this one originally by Willia...
[dyninst.git] / parseAPI / src / SymtabCodeSource.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include <vector>
31 #include <map>
32
33 #include <boost/assign/list_of.hpp>
34
35 #include "common/h/stats.h"
36 #include "dyntypes.h"
37
38 #include "symtabAPI/h/Symtab.h"
39 #include "symtabAPI/h/Function.h"
40
41 #include "CodeSource.h"
42 #include "debug_parse.h"
43 #include "util.h"
44
45 using namespace std;
46 using namespace Dyninst;
47 using namespace Dyninst::ParseAPI;
48
49
50 /** SymtabCodeRegion **/
51
52 SymtabCodeRegion::~SymtabCodeRegion()
53 {
54
55 }
56
57 SymtabCodeRegion::SymtabCodeRegion(
58         SymtabAPI::Symtab * st,
59         SymtabAPI::Region * reg) :
60     _symtab(st),
61     _region(reg)
62 {
63 }
64
65 void
66 SymtabCodeRegion::names(Address entry, vector<string> & names)
67 {
68     // FIXME SymtabAPI currently doesn't handle ambiguous
69     //       functions at the same linear address within
70     //       two address spaces. That error is reflected
71     //       here.
72     SymtabAPI::Function * f = NULL;
73     bool found = _symtab->findFuncByEntryOffset(f,entry);
74     if(found) {
75         // just pretty names?
76         const vector<string> & pretty = f->getAllPrettyNames();
77         names.insert(names.begin(),pretty.begin(),pretty.end());
78     }
79         else {
80                 cerr << "\t Failed to find name" << endl;
81         }
82 }
83
84 bool
85 SymtabCodeRegion::findCatchBlock(Address addr, Address & catchStart)
86 {
87     if(!contains(addr)) return false;
88
89     // FIXME SymtabAPI doesn't handle per-region catch block
90     //       lookups either, so faking it for now.
91     SymtabAPI::ExceptionBlock e;
92     if(_symtab->findCatchBlock(e,addr)) {
93         catchStart = e.catchStart();
94         return true;
95     }
96     return false;
97 }
98
99 bool
100 SymtabCodeRegion::isValidAddress(const Address addr) const
101 {
102     if(!contains(addr)) return false;
103
104     return isAligned(addr) && (isCode(addr) || isData(addr));
105 }
106
107 void *
108 SymtabCodeRegion::getPtrToInstruction(const Address addr) const
109 {
110     if(!contains(addr)) return NULL;
111
112     if(isCode(addr))
113         return (void*)((Address)_region->getPtrToRawData() + 
114                        addr - _region->getMemOffset());
115     else if(isData(addr))
116         return getPtrToData(addr);
117     else
118         return NULL;
119 }
120
121 void *
122 SymtabCodeRegion::getPtrToData(const Address addr) const
123 {
124     if(!contains(addr)) return NULL;
125
126     if(isData(addr))
127         return (void*)((Address)_region->getPtrToRawData() +
128                         addr - _region->getMemOffset());
129     else
130         return NULL;
131 }
132
133 unsigned int
134 SymtabCodeRegion::getAddressWidth() const
135 {
136     return _symtab->getAddressWidth();
137 }
138
139 Architecture
140 SymtabCodeRegion::getArch() const
141 {
142 #if defined(arch_power)
143     if(getAddressWidth() == 8)
144         return Arch_ppc64;
145     else
146         return Arch_ppc32;
147 #elif defined(arch_x86) || defined(arch_x86_64)
148     if(getAddressWidth() == 8)
149         return Arch_x86_64;
150     else
151         return Arch_x86;
152 #else
153     return Arch_none;
154 #endif
155 }
156
157 bool
158 SymtabCodeRegion::isCode(const Address addr) const
159 {
160     if(!contains(addr)) return false;
161
162     // XXX this is the predicate from Symtab::isCode(a) +
163     //     the condition by which Symtab::codeRegions_ is filled
164     return !_region->isBSS() && 
165            (_region->getRegionType() == SymtabAPI::Region::RT_TEXT ||
166             _region->getRegionType() == SymtabAPI::Region::RT_TEXTDATA ||
167             (_symtab->isDefensiveBinary() && _region->isLoadable()) );
168 }
169
170 bool
171 SymtabCodeRegion::isData(const Address addr) const
172 {
173     if(!contains(addr)) return false;
174
175     // XXX Symtab::isData(a) tests both RT_DATA (Region::isData(a))
176     //     and RT_TEXTDATA. Mimicking that behavior
177     return _region->isData() || 
178            _region->getRegionType()==SymtabAPI::Region::RT_TEXTDATA;
179 }
180
181 Address
182 SymtabCodeRegion::offset() const
183 {
184     return _region->getMemOffset();
185 }
186
187 Address
188 SymtabCodeRegion::length() const
189 {
190     return _region->getDiskSize();
191 }
192
193 /** SymtabCodeSource **/
194
195 SymtabCodeSource::~SymtabCodeSource()
196 {
197     _have_stats = false;
198     free(stats_parse);
199     if(owns_symtab && _symtab)
200         SymtabAPI::Symtab::closeSymtab(_symtab);
201     for(unsigned i=0;i<_regions.size();++i)
202         delete _regions[i];
203 }
204
205 SymtabCodeSource::SymtabCodeSource(SymtabAPI::Symtab * st, 
206                                    hint_filt * filt,
207                                    bool allLoadedRegions) : 
208     _symtab(st),
209     owns_symtab(false),
210     _lookup_cache(NULL),
211     stats_parse(new ::StatContainer()),
212     _have_stats(false)
213 {
214     init_stats();
215     init(filt,allLoadedRegions);
216 }
217
218 SymtabCodeSource::SymtabCodeSource(SymtabAPI::Symtab * st) : 
219     _symtab(st),
220     owns_symtab(false),
221     _lookup_cache(NULL),
222     stats_parse(new ::StatContainer()),
223     _have_stats(false)
224 {
225     init_stats();
226     init(NULL,false);
227 }
228
229 SymtabCodeSource::SymtabCodeSource(char * file) :
230     _symtab(NULL),
231     owns_symtab(true),
232     _lookup_cache(NULL),
233     stats_parse(new ::StatContainer()),
234     _have_stats(false)
235 {
236     init_stats();
237     
238     bool valid;
239
240     valid = SymtabAPI::Symtab::openFile(_symtab,file);
241     if(!valid) {
242         fprintf(stderr,"[%s] FATAL: can't create Symtab object for file %s\n",
243             FILE__,file);
244         _symtab = NULL;
245         return;
246     }
247     init(NULL,false);
248 }
249
250 bool
251 SymtabCodeSource::init_stats() {
252     if ((getenv("DYNINST_STATS_PARSING"))) {
253         parsing_printf("[%s] Enabling ParseAPI parsing statistics\n", FILE__);
254         // General counts
255         stats_parse->add(PARSE_BLOCK_COUNT, CountStat);
256         stats_parse->add(PARSE_FUNCTION_COUNT, CountStat);
257         
258         // Basic block size information
259         stats_parse->add(PARSE_BLOCK_SIZE, CountStat);
260
261         // Function return status counts
262         stats_parse->add(PARSE_NORETURN_COUNT, CountStat);
263         stats_parse->add(PARSE_RETURN_COUNT, CountStat);
264         stats_parse->add(PARSE_UNKNOWN_COUNT, CountStat);
265         stats_parse->add(PARSE_NORETURN_HEURISTIC, CountStat);
266
267         // Heuristic information
268         stats_parse->add(PARSE_JUMPTABLE_COUNT, CountStat);
269         stats_parse->add(PARSE_JUMPTABLE_FAIL, CountStat);
270         stats_parse->add(PARSE_TAILCALL_COUNT, CountStat);
271         stats_parse->add(PARSE_TAILCALL_FAIL, CountStat);
272
273         _have_stats = true;
274     }
275
276     return _have_stats;
277 }
278
279 void
280 SymtabCodeSource::print_stats() const {
281     
282     if (_have_stats) {
283         fprintf(stderr, "[%s] Printing ParseAPI statistics\n", FILE__);
284         fprintf(stderr, "\t Basic Stats:\n");
285         fprintf(stderr, "\t\t Block Count: %ld\n", (*stats_parse)[PARSE_BLOCK_COUNT]->value());
286         fprintf(stderr, "\t\t Function Count: %ld\n", (*stats_parse)[PARSE_FUNCTION_COUNT]->value());
287         
288         long int blockSize = (*stats_parse)[PARSE_BLOCK_SIZE]->value();
289         if (blockSize) {
290             fprintf(stderr, "\t Basic Block Stats:\n");
291             fprintf(stderr, "\t\t Sum of block sizes (in bytes): %ld\n", blockSize);
292             fprintf(stderr, "\t\t Average block size (in bytes): %lf\n", (double)blockSize/(double)(*stats_parse)[PARSE_BLOCK_COUNT]->value());
293             fprintf(stderr, "\t\t Average blocks per function: %lf\n", 
294                     (double)(*stats_parse)[PARSE_BLOCK_COUNT]->value()/(double)(*stats_parse)[PARSE_FUNCTION_COUNT]->value());
295         } 
296         fprintf(stderr, "\t Function Return Status Stats:\n");
297         fprintf(stderr, "\t\t NORETURN Count: %ld", (*stats_parse)[PARSE_NORETURN_COUNT]->value());
298         long int noretHeuristicCount = (*stats_parse)[PARSE_NORETURN_HEURISTIC]->value();
299         if (noretHeuristicCount) {
300             fprintf(stderr, " (Labled based on heuristic: %ld)", noretHeuristicCount);
301         }
302         fprintf(stderr, "\n");
303         fprintf(stderr, "\t\t RETURN Count: %ld\n", (*stats_parse)[PARSE_RETURN_COUNT]->value());
304         fprintf(stderr, "\t\t UNKNOWN Count: %ld\n", (*stats_parse)[PARSE_UNKNOWN_COUNT]->value());
305
306         fprintf(stderr, "\t Heuristic Stats:\n");
307         fprintf(stderr, "\t\t parseJumpTable attempts: %ld\n", (*stats_parse)[PARSE_JUMPTABLE_COUNT]->value());
308         fprintf(stderr, "\t\t parseJumpTable failures: %ld\n", (*stats_parse)[PARSE_JUMPTABLE_FAIL]->value());
309         fprintf(stderr, "\t\t isTailCall attempts: %ld\n", (*stats_parse)[PARSE_TAILCALL_COUNT]->value());
310         fprintf(stderr, "\t\t isTailCall failures: %ld\n", (*stats_parse)[PARSE_TAILCALL_FAIL]->value());
311
312     }
313 }
314
315 void
316 SymtabCodeSource::incrementCounter(std::string name) const
317 {
318     if (_have_stats) {
319         stats_parse->incrementCounter(name);
320     }
321 }
322
323 void 
324 SymtabCodeSource::addCounter(std::string name, int num) const
325 {
326     if (_have_stats) {
327         stats_parse->addCounter(name, num);
328     }
329 }
330
331 void
332 SymtabCodeSource::decrementCounter(std::string name) const
333 {
334     if (_have_stats) {
335         stats_parse->decrementCounter(name);
336     }
337 }
338
339 void
340 SymtabCodeSource::init(hint_filt * filt , bool allLoadedRegions)
341 {
342     // regions (and hints)
343     init_regions(filt, allLoadedRegions);
344
345     // external linkage
346     init_linkage();
347
348     // table of contents (only exists for some binary types)
349     _table_of_contents = _symtab->getTOCoffset();
350 }
351
352 void 
353 SymtabCodeSource::init_regions(hint_filt * filt , bool allLoadedRegions)
354 {
355     dyn_hash_map<void*,CodeRegion*> rmap;
356     vector<SymtabAPI::Region *> regs;
357     vector<SymtabAPI::Region *> dregs;
358     vector<SymtabAPI::Region *>::iterator rit;
359
360     if ( ! allLoadedRegions ) {
361         _symtab->getCodeRegions(regs);
362         _symtab->getDataRegions(dregs);
363         regs.insert(regs.end(),dregs.begin(),dregs.end());
364     }
365     else {
366         _symtab->getMappedRegions(regs);
367     }
368
369     parsing_printf("[%s:%d] processing %d symtab regions in %s\n",
370         FILE__,__LINE__,regs.size(),_symtab->name().c_str());
371     for(rit = regs.begin(); rit != regs.end(); ++rit) {
372         parsing_printf("   %lx %s",(*rit)->getMemOffset(),
373             (*rit)->getRegionName().c_str());
374     
375         // XXX only TEXT, DATA, TEXTDATA?
376         SymtabAPI::Region::RegionType rt = (*rit)->getRegionType();
377         if(false == allLoadedRegions &&
378            rt != SymtabAPI::Region::RT_TEXT &&
379            rt != SymtabAPI::Region::RT_DATA &&
380            rt != SymtabAPI::Region::RT_TEXTDATA)
381         {
382             parsing_printf(" [skipped]\n");
383             continue;
384         }
385
386         //#if defined(os_vxworks)
387         if(0 == (*rit)->getMemSize()) {
388             parsing_printf(" [skipped null region]\n");
389             continue;
390         }
391         //#endif
392         parsing_printf("\n");
393
394         if(HASHDEF(rmap,*rit)) {
395             parsing_printf("[%s:%d] duplicate region at address %lx\n",
396                 FILE__,__LINE__,(*rit)->getMemOffset());
397         }
398         CodeRegion * cr = new SymtabCodeRegion(_symtab,*rit);
399         rmap[*rit] = cr;
400         addRegion(cr);
401     }
402
403     // Hints are initialized at the SCS level rather than the SCR level
404     // because there is currently no per-Region lookup of functions in
405     // SymtabAPI.
406     init_hints(rmap,filt);
407 }
408
409 void
410 SymtabCodeSource::init_hints(dyn_hash_map<void*, CodeRegion*> & rmap,
411     hint_filt * filt)
412 {
413     vector<SymtabAPI::Function *> fsyms;
414     vector<SymtabAPI::Function *>::iterator fsit;
415     dyn_hash_map<Address,bool> seen;
416     int dupes = 0;
417
418     if(!_symtab->getAllFunctions(fsyms))
419         return;
420
421     parsing_printf("[%s:%d] processing %d symtab hints\n",FILE__,__LINE__,
422         fsyms.size());
423     for(fsit = fsyms.begin(); fsit != fsyms.end(); ++fsit) {
424         if(filt && (*filt)(*fsit))
425         {
426             parsing_printf("    == filtered hint %s [%lx] ==\n",
427                 FILE__,__LINE__,(*fsit)->getOffset(),
428                 (*fsit)->getFirstSymbol()->getPrettyName().c_str());
429             continue;
430         }
431
432         if(HASHDEF(seen,(*fsit)->getOffset())) {
433             // XXX it looks as though symtabapi now does de-duplication
434             //     of function symbols automatically, so this code should
435             //     never be reached, except in the case of overlapping
436             //     regions
437            parsing_printf("[%s:%d] duplicate function at address %lx: %s\n",
438                 FILE__,__LINE__,
439                 (*fsit)->getOffset(),
440                 (*fsit)->getFirstSymbol()->getPrettyName().c_str());
441             ++dupes;
442         }
443         seen[(*fsit)->getOffset()] = true;
444
445         SymtabAPI::Region * sr = (*fsit)->getRegion();
446         if(!sr) {
447             parsing_printf("[%s:%d] missing Region in function at %lx\n",
448                 FILE__,__LINE__,(*fsit)->getOffset());
449             continue;
450         }
451         if(!HASHDEF(rmap,sr)) {
452             parsing_printf("[%s:%d] unrecognized Region %lx in function %lx\n",
453                 FILE__,__LINE__,sr->getMemOffset(),(*fsit)->getOffset());
454             continue;
455         }
456         CodeRegion * cr = rmap[sr];
457         if(!cr->isCode((*fsit)->getOffset()))
458         {
459             parsing_printf("\t<%lx> skipped non-code, region [%lx,%lx)\n",
460                 (*fsit)->getOffset(),
461                 sr->getMemOffset(),
462                 sr->getMemOffset()+sr->getDiskSize());
463         } else {
464             _hints.push_back( Hint((*fsit)->getOffset(),
465                                cr,
466                                (*fsit)->getFirstSymbol()->getPrettyName()) );
467             parsing_printf("\t<%lx,%s,[%lx,%lx)>\n",
468                 (*fsit)->getOffset(),
469                 (*fsit)->getFirstSymbol()->getPrettyName().c_str(),
470                 cr->offset(),
471                 cr->offset()+cr->length());
472         }
473     }
474 }
475
476 void
477 SymtabCodeSource::init_linkage()
478 {
479     vector<SymtabAPI::relocationEntry> fbt;
480     vector<SymtabAPI::relocationEntry>::iterator fbtit;
481
482     if(!_symtab->getFuncBindingTable(fbt))
483         return;
484
485     for(fbtit = fbt.begin(); fbtit != fbt.end(); ++fbtit)
486         _linkage[(*fbtit).target_addr()] = (*fbtit).name(); 
487 }
488
489 bool
490 SymtabCodeSource::nonReturning(Address addr)
491 {
492     SymtabAPI::Function * f = NULL;
493    
494     _symtab->findFuncByEntryOffset(f,addr); 
495
496     if(f) {
497       const std::vector<std::string> &names = f->getAllMangledNames();
498       for (unsigned i = 0; i < names.size(); ++i) {
499         if (nonReturning(names[i])) {
500           return true;
501         }
502       }
503     }
504     return false;
505 }
506
507 dyn_hash_map<std::string, bool>
508 SymtabCodeSource::non_returning_funcs =
509     boost::assign::map_list_of
510         ("exit",true)
511         ("abort",true)
512         ("__f90_stop",true)
513         ("fancy_abort",true)
514         ("__stack_chk_fail",true)
515         ("__assert_fail",true)
516         ("ExitProcess",true)
517         ("_ZSt17__throw_bad_allocv",true)
518         ("_ZSt20__throw_length_errorPKc",true)
519         ("_Unwind_Resume",true)
520         ("longjmp",true)
521         ("siglongjmp",true)
522         ("_ZSt16__throw_bad_castv",true)
523         ("_ZSt19__throw_logic_errorPKc",true)
524         ("_ZSt20__throw_out_of_rangePKc",true)
525         ("__cxa_rethrow",true)
526         ("__cxa_throw",true)
527         ("_ZSt21__throw_runtime_errorPKc",true)
528         ("_gfortran_os_error",true)
529         ("_gfortran_runtime_error",true)
530         ("_gfortran_stop_numeric", true)
531    ("for_stop_core", true)
532   ("__sys_exit", true);
533
534 bool
535 SymtabCodeSource::nonReturning(string name)
536 {
537 #if defined(os_windows)
538         // We see MSVCR<N>.exit
539         // Of course, it's often reached via indirect call, but hope never fails.
540         if ((name.compare(0, strlen("MSVCR"), "MSVCR") == 0) &&
541                 (name.find("exit") != name.npos)) return true;
542 #endif
543         parsing_printf("Checking non-returning (Symtab) for %s\n", name.c_str());
544     return non_returning_funcs.find(name) != non_returning_funcs.end();
545 }
546
547 Address
548 SymtabCodeSource::baseAddress() const
549 {
550     return _symtab->getBaseOffset();
551 }
552
553 Address
554 SymtabCodeSource::loadAddress() const
555 {
556     return _symtab->getLoadOffset();
557 }
558
559 Address
560 SymtabCodeSource::getTOC(Address addr) const
561 {
562     SymtabAPI::Function *func;
563
564     if (_symtab->getContainingFunction(addr, func)) {
565         return func->getTOCOffset();
566     }
567     return _table_of_contents;
568 }
569
570 inline CodeRegion *
571 SymtabCodeSource::lookup_region(const Address addr) const
572 {
573     CodeRegion * ret = NULL;
574     if(_lookup_cache && _lookup_cache->contains(addr))
575         ret = _lookup_cache;
576     else {
577         set<CodeRegion *> stab;
578         int rcnt = findRegions(addr,stab);
579     
580         assert(rcnt <= 1 || regionsOverlap());
581
582 #if defined(os_aix)    
583         // XXX AIX objects frequently have overlapping regions.
584         //     Prefer code over data regions, following 
585         //     SymtabAPI::findEnclosingRegion()
586         if(rcnt) {
587             set<CodeRegion*>::iterator sit = stab.begin();
588             for( ; sit != stab.end(); ++sit) {
589                 CodeRegion * tmp = *sit;
590                 if(tmp->isCode(addr)) {
591                     ret = tmp;
592                     break;
593                 } else {
594                     // XXX hold the first non-code region as 
595                     //     the default return. Don't stop looking,
596                     //     however; might find a code region
597                     if(!ret)
598                         ret = tmp;
599                 }
600             } 
601             _lookup_cache = ret; 
602         }
603 #else
604         if(rcnt) {
605             ret = *stab.begin();
606             _lookup_cache = ret;
607         } 
608 #endif
609     }
610     return ret;
611 }
612
613 inline void 
614 SymtabCodeSource::overlapping_warn(const char * file, unsigned line) const
615 {
616     // XXX AIX objects frequently have overlapping regions; just deal.
617 #if !defined(os_aix)
618     if(regionsOverlap()) {
619         fprintf(stderr,"Invocation of routine at %s:%d is ambiguous for "
620                        "binaries with overlapping code regions\n",
621             file,line);
622     }
623 #endif
624 }
625
626 bool
627 SymtabCodeSource::isValidAddress(const Address addr) const
628 {
629     overlapping_warn(FILE__,__LINE__);
630
631     CodeRegion * cr = lookup_region(addr);
632     if(cr)
633         return cr->isValidAddress(addr);
634     else
635         return false;
636 }
637
638 void *
639 SymtabCodeSource::getPtrToInstruction(const Address addr) const
640 {
641     overlapping_warn(FILE__,__LINE__);
642
643     CodeRegion * cr = lookup_region(addr);
644     if(cr)
645         return cr->getPtrToInstruction(addr);
646     else
647         return NULL;
648 }
649
650 void *
651 SymtabCodeSource::getPtrToData(const Address addr) const
652 {
653     overlapping_warn(FILE__,__LINE__);
654
655     CodeRegion * cr = lookup_region(addr);
656     if(cr)
657         return cr->getPtrToData(addr);
658     else
659         return NULL;
660 }
661
662 unsigned int
663 SymtabCodeSource::getAddressWidth() const
664 {
665     return _symtab->getAddressWidth();
666 }
667
668 Architecture
669 SymtabCodeSource::getArch() const
670 {
671 #if defined(arch_power)
672     if(getAddressWidth() == 8)
673         return Arch_ppc64;
674     else
675         return Arch_ppc32;
676 #elif defined(arch_x86) || defined(arch_x86_64)
677     if(getAddressWidth() == 8)
678         return Arch_x86_64;
679     else
680         return Arch_x86;
681 #else
682     return Arch_none;
683 #endif
684 }
685
686 bool
687 SymtabCodeSource::isCode(const Address addr) const
688 {
689     overlapping_warn(FILE__,__LINE__);
690
691     CodeRegion * cr = lookup_region(addr);
692     if(cr)
693         return cr->isCode(addr);
694     else
695         return false;
696 }
697
698 bool
699 SymtabCodeSource::isData(const Address addr) const
700 {
701     overlapping_warn(FILE__,__LINE__);
702
703     CodeRegion * cr = lookup_region(addr);
704     if(cr)
705         return cr->isData(addr);
706     else
707         return false;
708 }
709
710 Address
711 SymtabCodeSource::offset() const
712 {
713     return _symtab->imageOffset();
714 }
715
716 Address
717 SymtabCodeSource::length() const
718 {
719     return _symtab->imageLength();
720 }
721
722
723 void 
724 SymtabCodeSource::removeRegion(CodeRegion &cr)
725 {
726     _region_tree.remove( &cr );
727
728     for (vector<CodeRegion*>::iterator rit = _regions.begin(); 
729          rit != _regions.end(); rit++) 
730     {
731         if ( &cr == *rit ) {
732             _regions.erase( rit );
733             break;
734         }
735     }
736 }
737
738 // fails and returns false if it can't find a CodeRegion
739 // to match the SymtabAPI::region
740 // has to remove the region before modifying the region's size, 
741 // otherwise the region can't be found
742 bool
743 SymtabCodeSource::resizeRegion(SymtabAPI::Region *sr, Address newDiskSize)
744 {
745     // find region
746     std::set<CodeRegion*> regions;
747     findRegions(sr->getMemOffset(), regions);
748     bool found_it = false;
749     set<CodeRegion*>::iterator rit = regions.begin();
750     for (; rit != regions.end(); rit++) {
751         if (sr == ((SymtabCodeRegion*)(*rit))->symRegion()) {
752             found_it = true;
753             break;
754         }
755     }
756
757     if (!found_it) {
758         return false;
759     }
760
761     // remove, resize, reinsert
762     removeRegion( **rit );
763     sr->setDiskSize( newDiskSize );
764     addRegion( *rit );
765     return true;
766 }
767
768 void
769 SymtabCodeSource::addNonReturning(std::string func_name)
770 {
771     non_returning_funcs[func_name] = true;
772 }