Compile fix after removing deprecated SymtabAPI methods.
[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     char *p;
253
254     if ((p = getenv("DYNINST_STATS_PARSING"))) {
255         parsing_printf("[%s] Enabling ParseAPI parsing statistics\n", FILE__);
256         // General counts
257         stats_parse->add(PARSE_BLOCK_COUNT, CountStat);
258         stats_parse->add(PARSE_FUNCTION_COUNT, CountStat);
259         
260         // Basic block size information
261         stats_parse->add(PARSE_BLOCK_SIZE, CountStat);
262
263         // Function return status counts
264         stats_parse->add(PARSE_NORETURN_COUNT, CountStat);
265         stats_parse->add(PARSE_RETURN_COUNT, CountStat);
266         stats_parse->add(PARSE_UNKNOWN_COUNT, CountStat);
267         stats_parse->add(PARSE_NORETURN_HEURISTIC, CountStat);
268
269         // Heuristic information
270         stats_parse->add(PARSE_JUMPTABLE_COUNT, CountStat);
271         stats_parse->add(PARSE_JUMPTABLE_FAIL, CountStat);
272         stats_parse->add(PARSE_TAILCALL_COUNT, CountStat);
273         stats_parse->add(PARSE_TAILCALL_FAIL, CountStat);
274
275         _have_stats = true;
276     }
277
278     return _have_stats;
279 }
280
281 void
282 SymtabCodeSource::print_stats() const {
283     
284     if (_have_stats) {
285         fprintf(stderr, "[%s] Printing ParseAPI statistics\n", FILE__);
286         fprintf(stderr, "\t Basic Stats:\n");
287         fprintf(stderr, "\t\t Block Count: %ld\n", (*stats_parse)[PARSE_BLOCK_COUNT]->value());
288         fprintf(stderr, "\t\t Function Count: %ld\n", (*stats_parse)[PARSE_FUNCTION_COUNT]->value());
289         
290         long int blockSize = (*stats_parse)[PARSE_BLOCK_SIZE]->value();
291         if (blockSize) {
292             fprintf(stderr, "\t Basic Block Stats:\n");
293             fprintf(stderr, "\t\t Sum of block sizes (in bytes): %ld\n", blockSize);
294             fprintf(stderr, "\t\t Average block size (in bytes): %lf\n", (double)blockSize/(double)(*stats_parse)[PARSE_BLOCK_COUNT]->value());
295             fprintf(stderr, "\t\t Average blocks per function: %lf\n", 
296                     (double)(*stats_parse)[PARSE_BLOCK_COUNT]->value()/(double)(*stats_parse)[PARSE_FUNCTION_COUNT]->value());
297         } 
298         fprintf(stderr, "\t Function Return Status Stats:\n");
299         fprintf(stderr, "\t\t NORETURN Count: %ld", (*stats_parse)[PARSE_NORETURN_COUNT]->value());
300         long int noretHeuristicCount = (*stats_parse)[PARSE_NORETURN_HEURISTIC]->value();
301         if (noretHeuristicCount) {
302             fprintf(stderr, " (Labled based on heuristic: %ld)", noretHeuristicCount);
303         }
304         fprintf(stderr, "\n");
305         fprintf(stderr, "\t\t RETURN Count: %ld\n", (*stats_parse)[PARSE_RETURN_COUNT]->value());
306         fprintf(stderr, "\t\t UNKNOWN Count: %ld\n", (*stats_parse)[PARSE_UNKNOWN_COUNT]->value());
307
308         fprintf(stderr, "\t Heuristic Stats:\n");
309         fprintf(stderr, "\t\t parseJumpTable attempts: %ld\n", (*stats_parse)[PARSE_JUMPTABLE_COUNT]->value());
310         fprintf(stderr, "\t\t parseJumpTable failures: %ld\n", (*stats_parse)[PARSE_JUMPTABLE_FAIL]->value());
311         fprintf(stderr, "\t\t isTailCall attempts: %ld\n", (*stats_parse)[PARSE_TAILCALL_COUNT]->value());
312         fprintf(stderr, "\t\t isTailCall failures: %ld\n", (*stats_parse)[PARSE_TAILCALL_FAIL]->value());
313
314     }
315 }
316
317 void
318 SymtabCodeSource::incrementCounter(std::string name) const
319 {
320     if (_have_stats) {
321         stats_parse->incrementCounter(name);
322     }
323 }
324
325 void 
326 SymtabCodeSource::addCounter(std::string name, int num) const
327 {
328     if (_have_stats) {
329         stats_parse->addCounter(name, num);
330     }
331 }
332
333 void
334 SymtabCodeSource::decrementCounter(std::string name) const
335 {
336     if (_have_stats) {
337         stats_parse->decrementCounter(name);
338     }
339 }
340
341 void
342 SymtabCodeSource::init(hint_filt * filt , bool allLoadedRegions)
343 {
344     // regions (and hints)
345     init_regions(filt, allLoadedRegions);
346
347     // external linkage
348     init_linkage();
349
350     // table of contents (only exists for some binary types)
351     _table_of_contents = _symtab->getTOCoffset();
352 }
353
354 void 
355 SymtabCodeSource::init_regions(hint_filt * filt , bool allLoadedRegions)
356 {
357     dyn_hash_map<void*,CodeRegion*> rmap;
358     vector<SymtabAPI::Region *> regs;
359     vector<SymtabAPI::Region *> dregs;
360     vector<SymtabAPI::Region *>::iterator rit;
361
362     if ( ! allLoadedRegions ) {
363         _symtab->getCodeRegions(regs);
364         _symtab->getDataRegions(dregs);
365         regs.insert(regs.end(),dregs.begin(),dregs.end());
366     }
367     else {
368         _symtab->getMappedRegions(regs);
369     }
370
371     parsing_printf("[%s:%d] processing %d symtab regions in %s\n",
372         FILE__,__LINE__,regs.size(),_symtab->name().c_str());
373     for(rit = regs.begin(); rit != regs.end(); ++rit) {
374         parsing_printf("   %lx %s",(*rit)->getMemOffset(),
375             (*rit)->getRegionName().c_str());
376     
377         // XXX only TEXT, DATA, TEXTDATA?
378         SymtabAPI::Region::RegionType rt = (*rit)->getRegionType();
379         if(false == allLoadedRegions &&
380            rt != SymtabAPI::Region::RT_TEXT &&
381            rt != SymtabAPI::Region::RT_DATA &&
382            rt != SymtabAPI::Region::RT_TEXTDATA)
383         {
384             parsing_printf(" [skipped]\n");
385             continue;
386         }
387
388         //#if defined(os_vxworks)
389         if(0 == (*rit)->getMemSize()) {
390             parsing_printf(" [skipped null region]\n");
391             continue;
392         }
393         //#endif
394         parsing_printf("\n");
395
396         if(HASHDEF(rmap,*rit)) {
397             parsing_printf("[%s:%d] duplicate region at address %lx\n",
398                 FILE__,__LINE__,(*rit)->getMemOffset());
399         }
400         CodeRegion * cr = new SymtabCodeRegion(_symtab,*rit);
401         rmap[*rit] = cr;
402         addRegion(cr);
403     }
404
405     // Hints are initialized at the SCS level rather than the SCR level
406     // because there is currently no per-Region lookup of functions in
407     // SymtabAPI.
408     init_hints(rmap,filt);
409 }
410
411 void
412 SymtabCodeSource::init_hints(dyn_hash_map<void*, CodeRegion*> & rmap,
413     hint_filt * filt)
414 {
415     vector<SymtabAPI::Function *> fsyms;
416     vector<SymtabAPI::Function *>::iterator fsit;
417     dyn_hash_map<Address,bool> seen;
418     int dupes = 0;
419
420     if(!_symtab->getAllFunctions(fsyms))
421         return;
422
423     parsing_printf("[%s:%d] processing %d symtab hints\n",FILE__,__LINE__,
424         fsyms.size());
425     for(fsit = fsyms.begin(); fsit != fsyms.end(); ++fsit) {
426         if(filt && (*filt)(*fsit))
427         {
428             parsing_printf("    == filtered hint %s [%lx] ==\n",
429                 FILE__,__LINE__,(*fsit)->getOffset(),
430                 (*fsit)->getFirstSymbol()->getPrettyName().c_str());
431             continue;
432         }
433
434         if(HASHDEF(seen,(*fsit)->getOffset())) {
435             // XXX it looks as though symtabapi now does de-duplication
436             //     of function symbols automatically, so this code should
437             //     never be reached, except in the case of overlapping
438             //     regions
439            parsing_printf("[%s:%d] duplicate function at address %lx: %s\n",
440                 FILE__,__LINE__,
441                 (*fsit)->getOffset(),
442                 (*fsit)->getFirstSymbol()->getPrettyName().c_str());
443             ++dupes;
444         }
445         seen[(*fsit)->getOffset()] = true;
446
447         SymtabAPI::Region * sr = (*fsit)->getRegion();
448         if(!sr) {
449             parsing_printf("[%s:%d] missing Region in function at %lx\n",
450                 FILE__,__LINE__,(*fsit)->getOffset());
451             continue;
452         }
453         if(!HASHDEF(rmap,sr)) {
454             parsing_printf("[%s:%d] unrecognized Region %lx in function %lx\n",
455                 FILE__,__LINE__,sr->getMemOffset(),(*fsit)->getOffset());
456             continue;
457         }
458         CodeRegion * cr = rmap[sr];
459         if(!cr->isCode((*fsit)->getOffset()))
460         {
461             parsing_printf("\t<%lx> skipped non-code, region [%lx,%lx)\n",
462                 (*fsit)->getOffset(),
463                 sr->getMemOffset(),
464                 sr->getMemOffset()+sr->getDiskSize());
465         } else {
466             _hints.push_back( Hint((*fsit)->getOffset(),
467                                cr,
468                                (*fsit)->getFirstSymbol()->getPrettyName()) );
469             parsing_printf("\t<%lx,%s,[%lx,%lx)>\n",
470                 (*fsit)->getOffset(),
471                 (*fsit)->getFirstSymbol()->getPrettyName().c_str(),
472                 cr->offset(),
473                 cr->offset()+cr->length());
474         }
475     }
476 }
477
478 void
479 SymtabCodeSource::init_linkage()
480 {
481     vector<SymtabAPI::relocationEntry> fbt;
482     vector<SymtabAPI::relocationEntry>::iterator fbtit;
483
484     if(!_symtab->getFuncBindingTable(fbt))
485         return;
486
487     for(fbtit = fbt.begin(); fbtit != fbt.end(); ++fbtit)
488         _linkage[(*fbtit).target_addr()] = (*fbtit).name(); 
489 }
490
491 bool
492 SymtabCodeSource::nonReturning(Address addr)
493 {
494     SymtabAPI::Function * f = NULL;
495    
496     _symtab->findFuncByEntryOffset(f,addr); 
497
498     if(f) {
499       const std::vector<std::string> &names = f->getAllMangledNames();
500       for (unsigned i = 0; i < names.size(); ++i) {
501         if (nonReturning(names[i])) {
502           return true;
503         }
504       }
505     }
506     return false;
507 }
508
509 dyn_hash_map<std::string, bool>
510 SymtabCodeSource::non_returning_funcs =
511     boost::assign::map_list_of
512         ("exit",true)
513         ("abort",true)
514         ("__f90_stop",true)
515         ("fancy_abort",true)
516         ("__stack_chk_fail",true)
517         ("__assert_fail",true)
518         ("ExitProcess",true)
519         ("_ZSt17__throw_bad_allocv",true)
520         ("_ZSt20__throw_length_errorPKc",true)
521         ("_Unwind_Resume",true)
522         ("longjmp",true)
523         ("siglongjmp",true)
524         ("_ZSt16__throw_bad_castv",true)
525         ("_ZSt19__throw_logic_errorPKc",true)
526         ("_ZSt20__throw_out_of_rangePKc",true)
527         ("__cxa_rethrow",true)
528         ("__cxa_throw",true)
529         ("_ZSt21__throw_runtime_errorPKc",true)
530         ("_gfortran_os_error",true)
531         ("_gfortran_runtime_error",true)
532         ("_gfortran_stop_numeric", true)
533    ("for_stop_core", true)
534   ("__sys_exit", true);
535
536 bool
537 SymtabCodeSource::nonReturning(string name)
538 {
539 #if defined(os_windows)
540         // We see MSVCR<N>.exit
541         // Of course, it's often reached via indirect call, but hope never fails.
542         if ((name.compare(0, strlen("MSVCR"), "MSVCR") == 0) &&
543                 (name.find("exit") != name.npos)) return true;
544 #endif
545         parsing_printf("Checking non-returning (Symtab) for %s\n", name.c_str());
546     return non_returning_funcs.find(name) != non_returning_funcs.end();
547 }
548
549 Address
550 SymtabCodeSource::baseAddress() const
551 {
552     return _symtab->getBaseOffset();
553 }
554
555 Address
556 SymtabCodeSource::loadAddress() const
557 {
558     return _symtab->getLoadOffset();
559 }
560
561 Address
562 SymtabCodeSource::getTOC(Address addr) const
563 {
564     SymtabAPI::Function *func;
565
566     if (_symtab->getContainingFunction(addr, func)) {
567         return func->getTOCOffset();
568     }
569     return _table_of_contents;
570 }
571
572 inline CodeRegion *
573 SymtabCodeSource::lookup_region(const Address addr) const
574 {
575     CodeRegion * ret = NULL;
576     if(_lookup_cache && _lookup_cache->contains(addr))
577         ret = _lookup_cache;
578     else {
579         set<CodeRegion *> stab;
580         int rcnt = findRegions(addr,stab);
581     
582         assert(rcnt <= 1 || regionsOverlap());
583
584 #if defined(os_aix)    
585         // XXX AIX objects frequently have overlapping regions.
586         //     Prefer code over data regions, following 
587         //     SymtabAPI::findEnclosingRegion()
588         if(rcnt) {
589             set<CodeRegion*>::iterator sit = stab.begin();
590             for( ; sit != stab.end(); ++sit) {
591                 CodeRegion * tmp = *sit;
592                 if(tmp->isCode(addr)) {
593                     ret = tmp;
594                     break;
595                 } else {
596                     // XXX hold the first non-code region as 
597                     //     the default return. Don't stop looking,
598                     //     however; might find a code region
599                     if(!ret)
600                         ret = tmp;
601                 }
602             } 
603             _lookup_cache = ret; 
604         }
605 #else
606         if(rcnt) {
607             ret = *stab.begin();
608             _lookup_cache = ret;
609         } 
610 #endif
611     }
612     return ret;
613 }
614
615 inline void 
616 SymtabCodeSource::overlapping_warn(const char * file, unsigned line) const
617 {
618     // XXX AIX objects frequently have overlapping regions; just deal.
619 #if !defined(os_aix)
620     if(regionsOverlap()) {
621         fprintf(stderr,"Invocation of routine at %s:%d is ambiguous for "
622                        "binaries with overlapping code regions\n",
623             file,line);
624     }
625 #endif
626 }
627
628 bool
629 SymtabCodeSource::isValidAddress(const Address addr) const
630 {
631     overlapping_warn(FILE__,__LINE__);
632
633     CodeRegion * cr = lookup_region(addr);
634     if(cr)
635         return cr->isValidAddress(addr);
636     else
637         return false;
638 }
639
640 void *
641 SymtabCodeSource::getPtrToInstruction(const Address addr) const
642 {
643     overlapping_warn(FILE__,__LINE__);
644
645     CodeRegion * cr = lookup_region(addr);
646     if(cr)
647         return cr->getPtrToInstruction(addr);
648     else
649         return NULL;
650 }
651
652 void *
653 SymtabCodeSource::getPtrToData(const Address addr) const
654 {
655     overlapping_warn(FILE__,__LINE__);
656
657     CodeRegion * cr = lookup_region(addr);
658     if(cr)
659         return cr->getPtrToData(addr);
660     else
661         return NULL;
662 }
663
664 unsigned int
665 SymtabCodeSource::getAddressWidth() const
666 {
667     return _symtab->getAddressWidth();
668 }
669
670 Architecture
671 SymtabCodeSource::getArch() const
672 {
673 #if defined(arch_power)
674     if(getAddressWidth() == 8)
675         return Arch_ppc64;
676     else
677         return Arch_ppc32;
678 #elif defined(arch_x86) || defined(arch_x86_64)
679     if(getAddressWidth() == 8)
680         return Arch_x86_64;
681     else
682         return Arch_x86;
683 #else
684     return Arch_none;
685 #endif
686 }
687
688 bool
689 SymtabCodeSource::isCode(const Address addr) const
690 {
691     overlapping_warn(FILE__,__LINE__);
692
693     CodeRegion * cr = lookup_region(addr);
694     if(cr)
695         return cr->isCode(addr);
696     else
697         return false;
698 }
699
700 bool
701 SymtabCodeSource::isData(const Address addr) const
702 {
703     overlapping_warn(FILE__,__LINE__);
704
705     CodeRegion * cr = lookup_region(addr);
706     if(cr)
707         return cr->isData(addr);
708     else
709         return false;
710 }
711
712 Address
713 SymtabCodeSource::offset() const
714 {
715     return _symtab->imageOffset();
716 }
717
718 Address
719 SymtabCodeSource::length() const
720 {
721     return _symtab->imageLength();
722 }
723
724
725 void 
726 SymtabCodeSource::removeRegion(CodeRegion &cr)
727 {
728     _region_tree.remove( &cr );
729
730     for (vector<CodeRegion*>::iterator rit = _regions.begin(); 
731          rit != _regions.end(); rit++) 
732     {
733         if ( &cr == *rit ) {
734             _regions.erase( rit );
735             break;
736         }
737     }
738 }
739
740 // fails and returns false if it can't find a CodeRegion
741 // to match the SymtabAPI::region
742 // has to remove the region before modifying the region's size, 
743 // otherwise the region can't be found
744 bool
745 SymtabCodeSource::resizeRegion(SymtabAPI::Region *sr, Address newDiskSize)
746 {
747     // find region
748     std::set<CodeRegion*> regions;
749     findRegions(sr->getMemOffset(), regions);
750     bool found_it = false;
751     set<CodeRegion*>::iterator rit = regions.begin();
752     for (; rit != regions.end(); rit++) {
753         if (sr == ((SymtabCodeRegion*)(*rit))->symRegion()) {
754             found_it = true;
755             break;
756         }
757     }
758
759     if (!found_it) {
760         return false;
761     }
762
763     // remove, resize, reinsert
764     removeRegion( **rit );
765     sr->setDiskSize( newDiskSize );
766     addRegion( *rit );
767     return true;
768 }
769
770 void
771 SymtabCodeSource::addNonReturning(std::string func_name)
772 {
773     non_returning_funcs[func_name] = true;
774 }