Compile fix after removing deprecated SymtabAPI methods.
[dyninst.git] / dyninstAPI / src / image.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
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <string>
36 #include <fstream>
37
38 #include "image.h"
39 #include "common/h/arch.h"
40 #include "parRegion.h"
41 #include "util.h"
42 #include "inst.h"
43 #include "debug.h"
44 #include "function.h"
45 #include "Parsing.h"
46
47 #include "common/h/Timer.h"
48 #include "common/h/debugOstream.h"
49 #include "common/h/pathName.h"
50 #include "common/h/MappedFile.h"
51
52 #include "dyninstAPI/h/BPatch_flowGraph.h"
53 #include "dynutil/h/util.h"
54
55 #include "symtabAPI/h/Function.h"
56
57 #include "parseAPI/h/InstructionSource.h"
58 #include "parseAPI/h/CodeObject.h"
59 #include "parseAPI/h/CFG.h"
60
61 #if defined(TIMED_PARSE)
62 #include <sys/time.h>
63 #endif
64
65 #if defined( USES_DWARF_DEBUG )
66 #include "dwarf.h"
67 #include "libdwarf.h"
68 #endif
69
70 #if defined(i386_unknown_nt4_0)
71 #include <dbghelp.h>
72 //#include <cvconst.h>
73 #endif
74
75 #if defined(os_vxworks)
76 #include "dyninstAPI/src/vxworks.h"
77 #endif
78
79 // For callbacks
80 #include "dyninstAPI/src/mapped_object.h" 
81
82 AnnotationClass<image_variable> ImageVariableUpPtrAnno("ImageVariableUpPtrAnno");
83 AnnotationClass<parse_func> ImageFuncUpPtrAnno("ImageFuncUpPtrAnno");
84 pdvector<image*> allImages;
85
86 using namespace std;
87 using namespace Dyninst;
88 using namespace Dyninst::ParseAPI;
89
90 using Dyninst::SymtabAPI::Symtab;
91 using Dyninst::SymtabAPI::Symbol;
92 using Dyninst::SymtabAPI::Region;
93 using Dyninst::SymtabAPI::Variable;
94 using Dyninst::SymtabAPI::Module;
95
96 char main_function_names[NUMBER_OF_MAIN_POSSIBILITIES][20] = {
97     "main",
98     "DYNINST_pltMain",
99     "_main",
100     "WinMain",
101     "_WinMain",
102     "wWinMain",
103     "_wWinMain",
104     "tls_cb_0"};
105
106 string fileDescriptor::emptyString(string(""));
107 fileDescriptor::fileDescriptor() {
108     // This shouldn't be called... must be public for pdvector, though
109 }
110
111 bool fileDescriptor::IsEqual(const fileDescriptor &fd) const {
112     // Don't test isShared, only file name and addresses
113     bool file_match_ = false;
114
115     // Annoying... we often get "foo vs ./foo" or such. So consider it a match
116     // if either file name is prefixed by the other; we don't get trailing crud.
117     string::size_type len1 = file_.length();
118     string::size_type len2 = fd.file_.length();
119   
120     if(((len1>=len2) && (file_.substr(len1-len2,len2) == fd.file_))
121        || ((len2>len1) && (fd.file_.substr(len2-len1,len1) == file_)))
122         file_match_ = true;   
123 #if defined(os_linux)
124     struct stat buf1;
125     struct stat buf2;
126     if (!stat(file_.c_str(),&buf1)
127         && !stat(fd.file_.c_str(),&buf2)
128         && buf1.st_ino == buf2.st_ino) {
129         file_match_ = true;
130     }
131 #endif  
132
133 #if defined(os_windows)
134     if(extract_pathname_tail(file_) == extract_pathname_tail(fd.file_)) file_match_ = true;
135 #endif
136 #if 0
137     cerr << hex << "Addr comparison: " << code_ << " ? " << fd.code_
138          << ", " << data_ << " ? " << fd.data_ 
139          << ", " << dynamic_ << " ? " << fd.dynamic_ << dec << endl;
140 #endif
141     bool addr_match = ((code_ == fd.code_ && data_ == fd.data_) ||
142                        (dynamic_ && dynamic_ == fd.dynamic_));
143 #if 0
144     cerr << "file " << file_match_ 
145          << ", addr " << addr_match
146          << ", member_ " << (member_ == fd.member_)
147          << ", pid_ " << (pid_ == fd.pid_) << endl;
148 #endif
149     if (file_match_ &&
150         (addr_match) &&
151         (member_ == fd.member_) &&
152         (pid_ == fd.pid_))
153         return true;
154     else
155         return false;
156 }
157
158 // only for non-files
159 unsigned char* fileDescriptor::rawPtr()
160 {
161
162 #if defined(os_windows)
163
164     return rawPtr_;
165
166 #else
167
168     return NULL;
169
170 #endif
171
172 }
173
174
175 // All debug_ostream vrbles are defined in process.C (for no particular reason)
176 extern unsigned enable_pd_sharedobj_debug;
177
178 int codeBytesSeen = 0;
179
180 #if defined(ppc32_linux) || defined(ppc32_bgp) || defined(ppc64_linux) || defined(ppc64_bgq)
181
182 #include <dataflowAPI/h/slicing.h>
183 #include <dataflowAPI/h/SymEval.h>
184 #include <dataflowAPI/h/AbslocInterface.h>
185 #include <dataflowAPI/h/Absloc.h>
186 #include <dynutil/h/DynAST.h>
187
188 namespace {
189     /* On PPC GLIBC (32 & 64 bit) the address of main is in a structure
190        located in either .data or .rodata, depending on whether the 
191        binary is PIC. The structure has the following format:
192
193         struct 
194         {
195             void * // "small data area base"
196             main   // pointer to main
197             init   // pointer to init
198             fini   // pointer to fini
199         }
200
201         This structure is passed in GR8 as an argument to libc_start_main.
202
203         Annoyingly, the value in GR8 is computed in several different ways,
204         depending on how GLIBC was compiled.
205
206         This code follows the i386 linux version closely otherwise.
207     */
208
209     class Default_Predicates : public Slicer::Predicates {};
210
211     /* This visitor is capable of simplifying constant value computations
212        that involve additions and concatenations (lis instruction). This
213        is sufficient to handle the startup struct address calculation in
214        GLIBC that we have seen; if additional variants are introduced
215        (refer to start.S in glibc or equivalently to the compiled library)
216        this visitor should be expanded to handle any new operations */
217         
218     class SimpleArithVisitor : public ASTVisitor {
219
220         using ASTVisitor::visit;
221
222         virtual ASTPtr visit(AST * a) {return a->ptr();};
223         virtual ASTPtr visit(DataflowAPI::BottomAST *a) {return a->ptr(); };
224         virtual ASTPtr visit(DataflowAPI::ConstantAST *c) {return c->ptr();};
225         virtual ASTPtr visit(DataflowAPI::VariableAST *v) {return v->ptr();};
226
227         virtual AST::Ptr visit(DataflowAPI::RoseAST * r) {
228             using namespace DataflowAPI;
229
230             AST::Children newKids;
231             for(unsigned i=0;i<r->numChildren();++i) {
232                 newKids.push_back(r->child(i)->accept(this));
233             }
234
235             switch(r->val().op) {
236                 case ROSEOperation::addOp:
237                     assert(newKids.size() == 2);
238                     if(newKids[0]->getID() == AST::V_ConstantAST &&
239                        newKids[1]->getID() == AST::V_ConstantAST)
240                     {
241                         ConstantAST::Ptr c1 = ConstantAST::convert(newKids[0]);
242                         ConstantAST::Ptr c2 = ConstantAST::convert(newKids[1]);
243                         return ConstantAST::create(
244                             Constant(c1->val().val+c2->val().val));
245                     }
246                     break;
247                 case ROSEOperation::concatOp:
248                     assert(newKids.size() == 2);
249                     if(newKids[0]->getID() == AST::V_ConstantAST &&
250                        newKids[1]->getID() == AST::V_ConstantAST)
251                     {
252                         ConstantAST::Ptr c1 = ConstantAST::convert(newKids[0]);
253                         ConstantAST::Ptr c2 = ConstantAST::convert(newKids[1]);
254                         unsigned long result = c1->val().val;
255                         result |= (c2->val().val << c2->val().size);
256                         return ConstantAST::create(result);
257                     }
258                     break;
259                 default:
260                     startup_printf("%s[%d] unhandled operation in simplification\n",FILE__,__LINE__);
261             }
262         
263             return RoseAST::create(r->val(), newKids);
264         }
265     };
266
267     struct libc_startup_info {
268         void * sda;
269         void * main_addr;
270         void * init_addr;
271         void * fini_addr;
272     };
273
274     /*
275      * b ends with a call to libc_start_main. We are looking for the
276      * value in GR8, which is the address of a structure that contains
277      * the address to main
278      */
279     Address evaluate_main_address(Symtab * linkedFile, Function * f, Block *b)
280     {
281         using namespace DataflowAPI;
282         using namespace InstructionAPI;
283         // looking for the *last* instruction in the block
284         // that defines GR8
285     
286         Instruction::Ptr r8_def;
287         Address r8_def_addr;
288     
289         InstructionDecoder dec(
290             b->region()->getPtrToInstruction(b->start()),
291             b->end()-b->start(),
292             b->region()->getArch());
293
294         RegisterAST::Ptr r8( new RegisterAST(ppc32::r8) );
295
296         Address cur_addr = b->start();
297         while(Instruction::Ptr cur = dec.decode()) {
298             if(cur->isWritten(r8)) {
299                 r8_def = cur;
300                 r8_def_addr = cur_addr;  
301             }
302             cur_addr += cur->size();
303         }
304         if(!r8_def)
305             return 0;
306
307         // Get all of the assignments that happen in this instruction
308         AssignmentConverter conv(true);
309         vector<Assignment::Ptr> assigns;
310         conv.convert(r8_def,r8_def_addr,f,b,assigns);
311
312         // find the one we care about (r8)
313         vector<Assignment::Ptr>::iterator ait = assigns.begin();
314         for( ; ait != assigns.end(); ++ait) {
315             AbsRegion & outReg = (*ait)->out();
316             Absloc const& loc = outReg.absloc();
317             if(loc.reg() == r8->getID())
318                 break;
319         }
320         if(ait == assigns.end()) {
321             return 0;
322         }
323
324         // Slice back to the definition of R8, and, if possible, simplify
325         // to a constant
326         Slicer slc(*ait,b,f);
327         Default_Predicates preds;
328         Graph::Ptr slg = slc.backwardSlice(preds);
329         DataflowAPI::Result_t sl_res;
330         DataflowAPI::SymEval::expand(slg,sl_res);
331         AST::Ptr calculation = sl_res[*ait];
332         SimpleArithVisitor visit; 
333         AST::Ptr simplified = calculation->accept(&visit);
334         //printf("after simplification:\n%s\n",simplified->format().c_str());
335         if(simplified->getID() == AST::V_ConstantAST) { 
336             ConstantAST::Ptr cp = ConstantAST::convert(simplified);
337             Address ss_addr = cp->val().val;
338
339             // need a pointer to the image data
340             SymtabAPI::Region * dreg = linkedFile->findEnclosingRegion(ss_addr);
341         
342             if(dreg) {
343                 struct libc_startup_info * si =
344                     (struct libc_startup_info *)(
345                         ((Address)dreg->getPtrToRawData()) + 
346                         ss_addr - (Address)dreg->getMemOffset())
347                 return (Address)si->main_addr;
348             }
349         }
350
351         return 0;
352     }
353 }
354 #endif
355
356 /* 
357  * Search for the Main Symbols in the list of symbols, Only in case
358  * if the file is a shared object. If not present add them to the
359  * list
360  */
361 void image::findMain()
362 {
363 #if defined(ppc32_linux) || defined(ppc32_bgp)
364     using namespace Dyninst::InstructionAPI;
365
366     if(!desc_.isSharedObject())
367     {
368         bool foundMain = false;
369         bool foundStart = false;
370         bool foundFini = false;
371         //check if 'main' is in allsymbols
372         vector <SymtabAPI::Function *> funcs;
373         if (linkedFile->findFunctionsByName(funcs, "main") ||
374             linkedFile->findFunctionsByName(funcs, "_main"))
375             foundMain = true;
376         else if (linkedFile->findFunctionsByName(funcs, "_start"))
377             foundStart = true;
378         else if (linkedFile->findFunctionsByName(funcs, "_fini"))
379             foundFini = true;
380     
381         Region *eReg = NULL;
382         bool foundText = linkedFile->findRegion(eReg, ".text");
383         if (foundText == false) {
384             return;
385         }
386         
387         if( !foundMain )
388         {
389             logLine("No main symbol found: attempting to create symbol for main\n");
390             const unsigned char* p;
391             p = (( const unsigned char * ) eReg->getPtrToRawData());
392
393             Address mainAddress = 0;
394
395                 bool parseInAllLoadableRegions = (BPatch_normalMode != mode_);
396                 SymtabCodeSource scs(linkedFile, filt, parseInAllLoadableRegions);
397             CodeObject tco(&scs,NULL,NULL,false);
398
399             tco.parse(eReg->getMemOffset(),false);
400             set<CodeRegion *> regions;
401             scs.findRegions(eReg->getMemOffset(),regions);
402             if(regions.empty()) {
403                 // express puzzlement
404                 return;
405             }
406             SymtabCodeRegion * reg = 
407                 static_cast<SymtabCodeRegion*>(*regions.begin());
408             Function * func = 
409                 tco.findFuncByEntry(reg,eReg->getMemOffset());
410             if(!func) {
411                 // again, puzzlement
412                 return;
413             }
414
415             const Function::edgelist & calls = func->callEdges();
416             if(calls.size() != 1) {
417                 startup_printf("%s[%d] _start has unexpected number (%d) of"
418                                " call edges, bailing on findMain()\n",
419                     FILE__,__LINE__,calls.size());
420                 return; 
421             }
422             Function::edgelist::iterator cit = calls.begin();
423             Block * b = (*cit)->src();
424
425             mainAddress = evaluate_main_address(linkedFile,func,b);
426             if(0 == mainAddress || !scs.isValidAddress(mainAddress)) {
427                 startup_printf("%s[%d] failed to find main\n",FILE__,__LINE__);
428                 return;
429             } else {
430                 startup_printf("%s[%d] found main at %lx\n",
431                     FILE__,__LINE__,mainAddress);
432             }
433                 Symbol *newSym= new Symbol( "main", 
434                                             Symbol::ST_FUNCTION,
435                                             Symbol::SL_GLOBAL, 
436                                             Symbol::SV_DEFAULT, 
437                                             mainAddress,
438                                             linkedFile->getDefaultModule(),
439                                             eReg, 
440                                             0 );
441                 linkedFile->addSymbol(newSym);          
442         }
443     }
444 #elif defined(i386_unknown_linux2_0) \
445 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
446 || defined(i386_unknown_solaris2_5) \
447 || (defined(os_freebsd) \
448     && (defined(arch_x86) || defined(arch_x86_64)))
449     if(!desc_.isSharedObject())
450     {
451         bool foundMain = false;
452         bool foundStart = false;
453         bool foundFini = false;
454
455         //check if 'main' is in allsymbols
456         vector <SymtabAPI::Function *> funcs;
457         if (linkedFile->findFunctionsByName(funcs, "main") ||
458             linkedFile->findFunctionsByName(funcs, "_main")) {
459            foundMain = true;
460         }
461
462         if (linkedFile->findFunctionsByName(funcs, "_start")) {
463             foundStart = true;
464         }
465
466         if (linkedFile->findFunctionsByName(funcs, "_fini")) {
467             foundFini = true;
468         }
469
470         Address eAddr = linkedFile->getEntryOffset();
471         Region *eReg = linkedFile->findEnclosingRegion(eAddr);
472         if (!eReg) {
473            return;
474         }
475         Address eStart = eReg->getMemOffset();
476
477         if( !foundMain )
478         {
479             logLine( "No main symbol found: creating symbol for main\n" );
480
481             //find and add main to allsymbols
482             const unsigned char* p;
483                                    
484             p = (( const unsigned char * ) eReg->getPtrToRawData());
485
486             if (eAddr > eStart) {
487                p += (eAddr - eStart);
488             }
489
490             switch(linkedFile->getAddressWidth()) {
491                 case 4:
492                     // 32-bit...
493                     startup_printf("%s[%u]:  setting 32-bit mode\n",
494                         FILE__,__LINE__);
495                     ia32_set_mode_64(false);
496                     break;
497                 case 8:
498                     startup_printf("%s[%u]:  setting 64-bit mode\n",
499                         FILE__,__LINE__);
500                     ia32_set_mode_64(true);
501                     break;
502                 default:
503                     assert(0 && "Illegal address width");
504                     break;
505             }
506
507             instruction insn;
508             insn.setInstruction( p );
509             Address mainAddress = 0;
510
511             // Create a temporary SymtabCodeSource that we can use for parsing. 
512             // We're going to throw it away when we're done so that we can re-sync
513             // with the new symbols we're going to add shortly. 
514             bool parseInAllLoadableRegions = (BPatch_normalMode != mode_);
515             SymtabCodeSource scs(linkedFile, filt, parseInAllLoadableRegions);
516
517 #if !defined(os_freebsd)
518             const unsigned char *lastP = 0;
519             while( !insn.isCall() )
520             {
521                 lastP = p;
522                 p += insn.size();
523                 insn.setInstruction( p );
524             }
525
526             // We _really_ can't handle a call with nothing before it....
527             assert(lastP);
528
529             // FIXME: this assumes that the instruction immediately before the call sets
530             // the main address - this may not be true.
531             instruction preCall;
532             preCall.setInstruction(lastP);
533
534             mainAddress = get_immediate_operand(&preCall);
535 #else
536             // Heuristic: main is the target of the 4th call in the text section
537             using namespace Dyninst::InstructionAPI;
538
539             unsigned bytesSeen = 0, numCalls = 0;
540             InstructionDecoder decoder(p, eReg->getMemSize(), scs.getArch());
541
542             Instruction::Ptr curInsn = decoder.decode();
543             while( numCalls < 4 && curInsn && curInsn->isValid() &&
544                    bytesSeen < eReg->getMemSize())
545             {
546                 InsnCategory category = curInsn->getCategory();
547                 if( category == c_CallInsn ) {
548                     numCalls++;
549                 }
550
551                 if( numCalls < 4 ) {
552                     bytesSeen += curInsn->size();
553                     curInsn = decoder.decode();
554                 }
555             }
556
557             if( numCalls != 4 ) {
558                 logLine("heuristic for finding global constructor function failed\n");
559             }else{
560                 Address callAddress = eReg->getMemOffset() + bytesSeen;
561                 RegisterAST thePC = RegisterAST(Dyninst::MachRegister::getPC(scs.getArch()));
562
563                 Expression::Ptr callTarget = curInsn->getControlFlowTarget();
564
565                 if( callTarget.get() ) {
566                     callTarget->bind(&thePC, Result(s64, callAddress));
567                     Result actualTarget = callTarget->eval();
568                     if( actualTarget.defined ) {
569                         mainAddress = actualTarget.convert<Address>();
570                     }
571                 }
572             }
573 #endif
574
575             if(!mainAddress || !scs.isValidAddress(mainAddress)) {
576                 startup_printf("%s[%u]:  invalid main address 0x%lx\n",
577                     FILE__, __LINE__, mainAddress);   
578             } else {
579                 startup_printf("%s[%u]:  set main address to 0x%lx\n",
580                     FILE__,__LINE__,mainAddress);
581             }
582
583             /* Note: creating a symbol for main at the invalid address 
584                anyway, because there is guard code for this later in the
585                process and otherwise we end up in a weird "this is not an
586                a.out" path.
587
588                findMain, like all important utility functions, should have
589                a way of gracefully indicating that it has failed. It should
590                not return void. NR
591             */
592
593             Region *pltsec;
594             if((linkedFile->findRegion(pltsec, ".plt")) && pltsec->isOffsetInRegion(mainAddress))
595             {
596                 //logLine( "No static symbol for function main\n" );
597                 Symbol *newSym = new Symbol("DYNINST_pltMain", 
598                                             Symbol::ST_FUNCTION, 
599                                             Symbol::SL_GLOBAL,
600                                             Symbol::SV_DEFAULT,
601                                             mainAddress,
602                                             linkedFile->getDefaultModule(),
603                                             eReg, 
604                                             0 );
605                 linkedFile->addSymbol( newSym );
606            }
607            else
608            {
609                 Symbol *newSym= new Symbol( "main", 
610                                             Symbol::ST_FUNCTION,
611                                             Symbol::SL_GLOBAL, 
612                                             Symbol::SV_DEFAULT, 
613                                             mainAddress,
614                                             linkedFile->getDefaultModule(),
615                                             eReg, 
616                                             0 );
617                 linkedFile->addSymbol(newSym);          
618             }
619         }
620         if( !foundStart )
621         {
622             Symbol *startSym = new Symbol( "_start",
623                                            Symbol::ST_FUNCTION,
624                                            Symbol::SL_GLOBAL,
625                                            Symbol::SV_DEFAULT, 
626                                            eReg->getMemOffset(),
627                                            linkedFile->getDefaultModule(),
628                                            eReg,
629                                            0 );
630             //cout << "sim for start!" << endl;
631         
632             linkedFile->addSymbol(startSym);            
633         }
634         if( !foundFini )
635         {
636           Region *finisec = NULL;
637           if (linkedFile->findRegion(finisec,".fini")) {
638             Symbol *finiSym = new Symbol( "_fini",
639                                           Symbol::ST_FUNCTION,
640                                           Symbol::SL_GLOBAL, 
641                                           Symbol::SV_DEFAULT, 
642                                           finisec->getMemOffset(),
643                                           linkedFile->getDefaultModule(),
644                                           finisec, 
645                                           0 );
646             linkedFile->addSymbol(finiSym);     
647           }     
648         }
649     }
650
651     Region *dynamicsec;
652     vector < Symbol *>syms;
653     if(linkedFile->findRegion(dynamicsec, ".dynamic")==true)
654     {
655         if(linkedFile->findSymbol(syms,
656                                   "_DYNAMIC",
657                                   Symbol::ST_UNKNOWN,
658                                   SymtabAPI::mangledName)==false)
659         {
660             Symbol *newSym = new Symbol( "_DYNAMIC", 
661                                         Symbol::ST_OBJECT, 
662                                          Symbol::SL_GLOBAL, 
663                                          Symbol::SV_DEFAULT,
664                                          dynamicsec->getMemOffset(), 
665                                          linkedFile->getDefaultModule(),
666                                          dynamicsec, 
667                                          0 );
668             linkedFile->addSymbol(newSym);
669         }
670     }
671     
672 #elif defined(rs6000_ibm_aix4_1) || defined(rs6000_ibm_aix5_1)
673    
674    bool foundMain = false;
675    vector <SymtabAPI::Function *> funcs;
676    if (linkedFile->findFunctionsByName(funcs, "main") ||
677        linkedFile->findFunctionsByName(funcs, "usla_main"))
678        foundMain = true;
679
680    Region *sec = NULL;
681    bool found = linkedFile->findRegion(sec, ".text");   
682
683    if( !foundMain && linkedFile->isExec() && found )
684    {
685        //we havent found a symbol for main therefore we have to parse _start
686        //to find the address of main
687
688        //last two calls in _start are to main and exit
689        //find the end of _start then back up to find the target addresses
690        //for exit and main
691       
692        int c;
693        int calls = 0;
694        Word *code_ptr_ = (Word *) sec->getPtrToRawData();
695        
696        for( c = 0; code_ptr_[ c ] != 0; c++ );
697
698        instruction i;
699        while( c > 0 )
700        {
701            i.setInstruction((codeBuf_t*)(&code_ptr_[ c ]));
702
703            if(IFORM_LK(i) && 
704               ((IFORM_OP(i) == Bop) || (BFORM_OP(i) == BCop) ||
705                ((XLFORM_OP(i) == BCLRop) && 
706                 ((XLFORM_XO(i) == 16) || (XLFORM_XO(i) == 528)))))
707            {
708                calls++;
709                if( calls == 2 )
710                    break;
711            }
712            c--;
713        }
714        
715        Offset currAddr = sec->getMemOffset() + c * instruction::size();
716        Offset mainAddr = 0;
717        
718        if( ( IFORM_OP(i) == Bop ) || ( BFORM_OP(i) == BCop ) )
719        {
720            int disp = 0;
721            if(IFORM_OP(i) == Bop)
722            {
723                disp = IFORM_LI(i);
724            }
725            else if(BFORM_OP(i) == BCop)
726            {
727                disp = BFORM_BD(i);
728            }
729
730            disp <<= 2;
731
732            if(IFORM_AA(i))
733            {
734                mainAddr = (Offset)disp;
735            }
736            else
737                mainAddr = (Offset)( currAddr + disp );      
738        }  
739        
740        Symbol *sym = new Symbol( "main", 
741                                  Symbol::ST_FUNCTION,
742                                  Symbol::SL_GLOBAL,
743                                  Symbol::SV_DEFAULT, 
744                                  mainAddr,
745                                  linkedFile->getDefaultModule(),
746                                  sec);
747        linkedFile->addSymbol(sym);
748       
749    
750        //since we are here make up a sym for _start as well
751
752        Symbol *sym1 = new Symbol( "__start", 
753                                   Symbol::ST_FUNCTION,
754                                   Symbol::SL_GLOBAL, 
755                                   Symbol::SV_DEFAULT, 
756                                   sec->getMemOffset(), 
757                                   linkedFile->getDefaultModule(),
758                                   sec);
759        linkedFile->addSymbol(sym1);
760    }
761
762 #elif defined(i386_unknown_nt4_0)
763
764    if(linkedFile->isExec()) {
765        vector <Symbol *>syms;
766        vector<SymtabAPI::Function *> funcs;
767        Address eAddr = linkedFile->getEntryOffset();
768        Region *eReg = linkedFile->findEnclosingRegion(eAddr);
769        
770        bool found_main = false;
771        for (unsigned i=0; i<NUMBER_OF_MAIN_POSSIBILITIES; i++) {
772            if(linkedFile->findFunctionsByName(funcs, main_function_names[i])) {
773                found_main = true;
774                break;
775            }
776        }
777        if (found_main) {
778            if(!linkedFile->findSymbol(syms,"start",Symbol::ST_UNKNOWN, SymtabAPI::mangledName)) {
779                //use 'start' for mainCRTStartup.
780                Symbol *startSym = new Symbol( "start", 
781                                               Symbol::ST_FUNCTION,
782                                               Symbol::SL_GLOBAL, 
783                                               Symbol::SV_DEFAULT, 
784                                               eAddr ,
785                                               linkedFile->getDefaultModule(),
786                                               eReg,
787                                               UINT_MAX );
788                linkedFile->addSymbol(startSym);
789            }
790            syms.clear();
791        } 
792        else {
793            // add entry point as main given that nothing else was found
794            startup_printf("[%s:%u] - findmain could not find symbol "
795                           "for main, using binary entry point %x\n",
796                           __FILE__, __LINE__, eAddr);
797            linkedFile->addSymbol(new Symbol("main",
798                                             Symbol::ST_FUNCTION, 
799                                             Symbol::SL_GLOBAL, 
800                                             Symbol::SV_DEFAULT,
801                                             eAddr,
802                                             linkedFile->getDefaultModule(),
803                                             eReg));
804        }
805    }
806 #endif
807 }
808
809 /*
810  * We do a search for a "main" symbol (a couple of variants), and
811  * if found we flag this image as the executable (a.out). 
812  */
813 bool image::determineImageType()
814 {
815 #if defined(TIMED_PARSE)
816   struct timeval starttime;
817   gettimeofday(&starttime, NULL);
818 #endif
819
820   //Checking "main" function names in same order as in the inst-*.C files
821   vector <SymtabAPI::Function *>funcs;
822   if (linkedFile->findFunctionsByName(funcs,"main")       ||
823       linkedFile->findFunctionsByName(funcs,"_main")     
824 #if defined(os_windows)
825       || linkedFile->findFunctionsByName(funcs,"WinMain")   ||
826       linkedFile->findFunctionsByName(funcs,"_WinMain")  ||
827       linkedFile->findFunctionsByName(funcs,"wWinMain")  ||
828       linkedFile->findFunctionsByName(funcs,"_wWinMain") 
829 #endif
830       ) {
831       is_a_out = true;
832   }
833   else
834       is_a_out = false;
835   
836   // Checking for libdyninstRT (DYNINSTinit())
837   if (linkedFile->findFunctionsByName(funcs, "DYNINSTinit") ||
838       linkedFile->findFunctionsByName(funcs, "_DYNINSTinit"))
839       is_libdyninstRT = true;
840   else
841       is_libdyninstRT = false;
842    
843 #if defined(TIMED_PARSE)
844   struct timeval endtime;
845   gettimeofday(&endtime, NULL);
846   unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
847   unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
848   unsigned long difftime = lendtime - lstarttime;
849   double dursecs = difftime/(1000 );
850   cout << __FILE__ << ":" << __LINE__ <<": determineImageType took "<<dursecs <<" msecs" << endl;
851 #endif
852   return true;
853 }
854
855 bool image::getInferiorHeaps(vector<pair<string,Address> > &codeHeaps,
856                              vector<pair<string,Address> > &dataHeaps) {
857     if ((codeHeaps_.size() == 0) &&
858         (dataHeaps_.size() == 0)) return false;
859
860     for (unsigned i = 0; i < codeHeaps_.size(); i++) {
861         codeHeaps.push_back(codeHeaps_[i]);
862     }
863
864     for (unsigned i = 0; i < dataHeaps_.size(); i++) {
865         dataHeaps.push_back(dataHeaps_[i]);
866     }
867     return true;
868 }
869
870 bool image::addSymtabVariables()
871 {
872    /* Eventually we'll have to do this on all platforms (because we'll retrieve
873     * the type information here).
874     */
875    
876 #if defined(TIMED_PARSE)
877    struct timeval starttime;
878    gettimeofday(&starttime, NULL);
879 #endif
880
881    std::string mangledName; 
882
883    vector<Variable *> allVars;
884
885    linkedFile->getAllVariables(allVars); 
886
887    for (vector<Variable *>::iterator varIter = allVars.begin();
888         varIter != allVars.end(); 
889         varIter++) {
890        Variable *symVar = *varIter;
891
892        parsing_printf("New variable, mangled %s, module %s...\n",
893                       symVar->getAllMangledNames()[0].c_str(),
894                       symVar->getFirstSymbol()->getModule()->fileName().c_str());
895        pdmodule *use = getOrCreateModule(symVar->getModule());
896
897        assert(use);
898        image_variable *var = new image_variable(symVar, use);
899        if (!var->svar()->addAnnotation(var, ImageVariableUpPtrAnno)) {
900            fprintf(stderr, "%s[%d]: failed to add annotation here\n", FILE__, __LINE__);
901            return false;
902        }
903
904        // If this is a Dyninst dynamic heap placeholder, add it to the
905        // list of inferior heaps...
906        string compString = "DYNINSTstaticHeap";
907        if (!var->symTabName().compare(0, compString.size(), compString)) {
908            dataHeaps_.push_back(pair<string,Address>(var->symTabName(), var->getOffset()));
909        }
910
911        exportedVariables.push_back(var);
912        everyUniqueVariable.push_back(var);
913        varsByAddr[var->getOffset()] = var;
914    }
915
916 #if defined(TIMED_PARSE)
917    struct timeval endtime;
918    gettimeofday(&endtime, NULL);
919    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
920    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
921    unsigned long difftime = lendtime - lstarttime;
922    double dursecs = difftime/(1000 );
923    cout << __FILE__ << ":" << __LINE__ <<": addSymtabVariables took "<<dursecs <<" msecs" << endl;
924 #endif
925
926    return true;
927 }
928
929 pdmodule *image::findModule(const string &name, bool wildcard)
930 {
931    pdmodule *found = NULL;
932    //cerr << "image::findModule " << name << " , " << find_if_excluded
933    //     << " called" << endl;
934
935    if (!wildcard) {
936       if (modsByFileName.find(name) != modsByFileName.end()) {
937          //cerr << " (image::findModule) found module in modsByFileName" << endl;
938          found = modsByFileName[name];
939       }
940       else if (modsByFullName.find(name) != modsByFullName.end()) {
941          //cerr << " (image::findModule) found module in modsByFullName" << endl;
942          found = modsByFullName[name];
943       }
944    }
945    else {
946       //  if we want a substring, have to iterate over all module names
947       //  this is ok b/c there are not usually more than a handful or so
948       //
949       dyn_hash_map <string, pdmodule *>::iterator mi;
950       string str; pdmodule *mod;
951       std::string pds = name.c_str();
952
953       for(mi = modsByFileName.begin(); mi != modsByFileName.end() ; mi++)
954       {
955          str = mi->first;
956          mod = mi->second;
957          if (wildcardEquiv(pds, mod->fileName()) ||
958                wildcardEquiv(pds, mod->fullName())) {
959             found = mod; 
960             break;
961          }
962       }
963    }
964
965    //cerr << " (image::findModule) did not find module, returning NULL" << endl;
966    if (found) {
967       // Just-in-time...
968       //if (parseState_ == symtab)
969       //analyzeImage();
970       return found;
971    }
972
973    return NULL;
974 }
975
976 const CodeObject::funclist &
977 image::getAllFunctions()
978 {
979     analyzeIfNeeded();
980     return codeObject()->funcs();
981 }
982
983 const pdvector<image_variable*> &image::getAllVariables()
984 {
985     analyzeIfNeeded();
986     return everyUniqueVariable;
987 }
988
989 const pdvector<image_variable*> &image::getExportedVariables() const { return exportedVariables; }
990
991 const pdvector<image_variable*> &image::getCreatedVariables()
992 {
993   analyzeIfNeeded();
994   return createdVariables;
995 }
996
997 bool image::getModules(vector<pdmodule *> &mods) 
998 {
999     bool ret = false;
1000    pdvector<pdmodule *> toReturn;
1001     for (map<Module *, pdmodule *>::const_iterator iter = mods_.begin();
1002          iter != mods_.end(); iter++) {
1003         ret = true;
1004         mods.push_back(iter->second);
1005     }
1006     return ret;
1007 }
1008
1009 // identify module name from symbol address (binary search)
1010 // based on module tags found in file format (ELF/COFF)
1011 void image::findModByAddr (const Symbol *lookUp, vector<Symbol *> &mods,
1012                            string &modName, Address &modAddr, 
1013                            const string &defName)
1014 {
1015   if (mods.size() == 0) {
1016     modAddr = 0;
1017     modName = defName;
1018     return;
1019   }
1020
1021   Address symAddr = lookUp->getOffset();
1022   int index;
1023   int start = 0;
1024   int end = mods.size() - 1;
1025   int last = end;
1026   bool found = false;
1027   while ((start <= end) && !found) {
1028     index = (start+end)/2;
1029     if ((index == last) ||
1030         ((mods[index]->getOffset() <= symAddr) && 
1031          (mods[index+1]->getOffset() > symAddr))) {
1032       modName = mods[index]->getMangledName().c_str();
1033       modAddr = mods[index]->getOffset();      
1034       found = true;
1035     } else if (symAddr < mods[index]->getOffset()) {
1036       end = index - 1;
1037     } else {
1038       start = index + 1;
1039     }
1040   }
1041   if (!found) { 
1042     // must be (start > end)
1043     modAddr = 0;
1044     modName = defName;
1045   }
1046 }
1047
1048 unsigned int int_addrHash(const Address& addr) {
1049   return (unsigned int)addr;
1050 }
1051
1052 /*
1053  * load an executable:
1054  *   1.) parse symbol table and identify rotuines.
1055  *   2.) scan executable to identify inst points.
1056  *
1057  *  offset is normally zero except on CM-5 where we have two images in one
1058  *    file.  The offset passed to parseImage is the logical offset (0/1), not
1059  *    the physical point in the file.  This makes it faster to "parse" multiple
1060  *    copies of the same image since we don't have to stat and read to find the
1061  *    physical offset. 
1062  */
1063
1064 image *image::parseImage(fileDescriptor &desc, 
1065                          BPatch_hybridMode mode, 
1066                          bool parseGaps)
1067 {
1068   /*
1069    * Check to see if we have parsed this image before. We will
1070    * consider it a match if the filename matches (Our code is now able
1071    * to cache the parsing results even if a library is loaded at a
1072    * different address for the second time).
1073    */
1074   unsigned numImages = allImages.size();
1075   
1076   // AIX: it's possible that we're reparsing a file with better information
1077   // about it. If so, yank the old one out of the images vector -- replace
1078   // it, basically.
1079   for (unsigned u=0; u<numImages; u++) {
1080       if (desc.isSameFile(allImages[u]->desc())) {
1081          if (allImages[u]->getObject()->canBeShared()) {
1082             // We reference count...
1083             startup_printf("%s[%d]: returning pre-parsed image\n", FILE__, __LINE__);
1084             return allImages[u]->clone();
1085          }
1086       }
1087   }
1088
1089   stats_parse.startTimer(PARSE_SYMTAB_TIMER);
1090
1091   /*
1092    * load the symbol table. (This is the a.out format specific routine).
1093    */
1094   
1095   bool err=false;
1096
1097 #if defined(TIMED_PARSE)
1098   struct timeval starttime;
1099   gettimeofday(&starttime, NULL);
1100 #endif
1101
1102   startup_printf("%s[%d]:  about to create image\n", FILE__, __LINE__);
1103   image *ret = new image(desc, err, mode, parseGaps); 
1104   startup_printf("%s[%d]:  created image\n", FILE__, __LINE__);
1105
1106   if(desc.isSharedObject()) 
1107       startup_printf("%s[%d]: processing shared object\n", FILE__, __LINE__);
1108   else  
1109       startup_printf("%s[%d]: processing executable object\n", FILE__, __LINE__);
1110       
1111
1112 #if defined(TIMED_PARSE)
1113   struct timeval endtime;
1114   gettimeofday(&endtime, NULL);
1115   unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
1116   unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
1117   unsigned long difftime = lendtime - lstarttime;
1118   double dursecs = difftime/(1000 );
1119   cout << __FILE__ << ":" << __LINE__ <<": parsing image "<< desc.file().c_str() <<" took "<<dursecs <<" msecs" << endl;
1120 #endif
1121
1122   if (err || !ret) {
1123      if (ret) {
1124          startup_printf("%s[%d]: error in processing, deleting image and returning\n",
1125                         FILE__, __LINE__);
1126          delete ret;
1127      }
1128      else {
1129         fprintf(stderr, "Failed to allocate memory for parsing %s!\n", 
1130                 desc.file().c_str());
1131      }
1132      stats_parse.stopTimer(PARSE_SYMTAB_TIMER);
1133      return NULL;
1134   }
1135
1136   allImages.push_back(ret);
1137
1138   // start tracking new blocks after initial parse
1139   if ( BPatch_exploratoryMode == mode ||
1140        BPatch_defensiveMode == mode ) 
1141   {
1142       ret->trackNewBlocks_ = true;
1143   }
1144
1145   // define all modules.
1146
1147   statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
1148   stats_parse.stopTimer(PARSE_SYMTAB_TIMER);
1149
1150   return ret;
1151 }
1152
1153 /*
1154  * Remove a parsed executable from the global list. Used if the old handle
1155  * is no longer valid.
1156  */
1157 void image::removeImage(image *img)
1158 {
1159
1160   // Here's a question... do we want to actually delete images?
1161   // Pro: free up memory. Con: we'd just have to parse them again...
1162   // I guess the question is "how often do we serially open files".
1163   /* int refCount = */ img->destroy();
1164   
1165
1166   /*
1167     // We're not deleting when the refcount hits 0, so we may as well
1168     // keep the vector. It's a time/memory problem. 
1169   if (refCount == 0) {
1170     pdvector<image*> newImages;
1171     // It's gone... remove from image vector
1172     for (unsigned i = 0; i < allImages.size(); i++) {
1173       if (allImages[i] != img)
1174         newImages.push_back(allImages[i]);
1175     }
1176     allImages = newImages;
1177   }
1178   */
1179 }
1180
1181 int image::destroy() {
1182     refCount--;
1183     if (refCount == 0) {
1184         if (!desc().isSharedObject()) {
1185             // a.out... destroy it
1186             //delete this;
1187             return 0;
1188         }
1189     }
1190     if (refCount < 0)
1191         assert(0 && "NEGATIVE REFERENCE COUNT FOR IMAGE!");
1192     return refCount; 
1193 }
1194
1195 void image::analyzeIfNeeded() {
1196   if (parseState_ == symtab) {
1197       parsing_printf("ANALYZING IMAGE %s\n",
1198               file().c_str());
1199       analyzeImage();
1200           // For defensive mode: we only care about incremental splitting and block
1201           // creation, not ones noted during parsing (as we haven't created the int
1202           // layer yet, so no harm no foul)
1203           clearNewBlocks();
1204   }
1205 }
1206
1207 void image::analyzeImage() {
1208 #if defined(TIMED_PARSE)
1209     struct timeval starttime;
1210     gettimeofday(&starttime, NULL);
1211 #endif
1212     stats_parse.startTimer(PARSE_ANALYZE_TIMER);
1213
1214 // FIXME necessary?
1215 #if defined(arch_x86_64)
1216     ia32_set_mode_64(getObject()->getAddressWidth() == 8);
1217 #endif
1218
1219     assert(parseState_ < analyzed);
1220     if(parseState_ < symtab){
1221         fprintf(stderr, "Error: attempt to analyze incomplete image\n");
1222         goto done;
1223     }
1224     parseState_ = analyzing;
1225
1226     obj_->parse();
1227
1228 #if defined(os_aix)
1229   {
1230   image_parRegion *parReg;
1231   int currentSectionNum = 0;
1232
1233   // Most of the time there will be no parallel regions in an image, so nothing will happen.
1234   // If there is a parallel region we examine it individually 
1235   for (unsigned i = 0; i < parallelRegions.size(); i++)
1236     {
1237       parReg = parallelRegions[i];
1238       if (parReg == NULL)
1239     continue;
1240       else
1241     {
1242       // Every parallel region has the parse_func that contains the
1243       //   region associated with it 
1244             parse_func * imf = const_cast<parse_func*>(parReg->getAssociatedFunc());
1245       
1246       // Returns pointers to all potential parse_funcs that correspond
1247       //   to what could be the parent OpenMP function for the region 
1248       const pdvector<parse_func *> *prettyNames =
1249         findFuncVectorByPretty(imf->calcParentFunc(imf, parallelRegions));
1250       
1251       //There may be more than one (or none) functions with that name, we take the first 
1252       // This function gives us all the information about the parallel region by getting
1253       // information for the parallel region parent function  
1254       if (prettyNames->size() > 0)
1255         imf->parseOMP(parReg, (*prettyNames)[0], currentSectionNum);
1256       else
1257         continue;
1258     }
1259     }
1260   }
1261   /**************************/
1262   /* END OpenMP Parsing Code */
1263   /**************************/
1264
1265 #endif
1266
1267 #if defined(cap_stripped_binaries)
1268    {
1269        vector<CodeRegion *>::const_iterator rit = cs_->regions().begin();
1270        for( ; rit != cs_->regions().end(); ++rit)
1271        {
1272         SymtabCodeRegion * scr = static_cast<SymtabCodeRegion*>(*rit);
1273         if(parseGaps_ && scr->symRegion()->isText()) {
1274             obj_->parseGaps(scr);
1275         }
1276        } 
1277    }
1278 #endif // cap_stripped_binaries
1279     
1280     parseState_ = analyzed;
1281   done:
1282     stats_parse.stopTimer(PARSE_ANALYZE_TIMER); 
1283
1284 #if defined(TIMED_PARSE)
1285     struct timeval endtime;
1286     gettimeofday(&endtime, NULL);
1287     unsigned long lstarttime = starttime.tv_sec * 1000*1000+starttime.tv_usec;
1288     unsigned long lendtime = endtime.tv_sec * 1000*1000+endtime.tv_usec;
1289     unsigned long difftime = lendtime - lstarttime;
1290     double dursecs = difftime/(1000 );
1291     cout << __FILE__ << ":" << __LINE__ <<": analyzeImage of " << name_ << " took "<<dursecs <<" msecs" << endl;
1292 #endif
1293 }
1294
1295 // Constructor for the image object. The fileDescriptor simply
1296 // wraps (in the normal case) the object name and a relocation
1297 // address (0 for a.out file). On the following platforms, we
1298 // are handling a special case:
1299 //   AIX: objects can possibly have a name like /lib/libc.so:shr.o
1300 //          since libraries are archives
1301 //        Both text and data sections have a relocation address
1302
1303
1304 image::image(fileDescriptor &desc, 
1305              bool &err, 
1306              BPatch_hybridMode mode, 
1307              bool parseGaps) :
1308    desc_(desc),
1309    activelyParsing(addrHash4),
1310    is_libdyninstRT(false),
1311    is_a_out(false),
1312    main_call_addr_(0),
1313    nativeCompiler(false),    
1314    obj_(NULL),
1315    cs_(NULL),
1316    filt(NULL),
1317    img_fact_(NULL),
1318    parse_cb_(NULL),
1319    nextBlockID_(0),
1320    pltFuncs(NULL),
1321    varsByAddr(addrHash4),
1322    trackNewBlocks_(false),
1323    refCount(1),
1324    parseState_(unparsed),
1325    parseGaps_(parseGaps),
1326    mode_(mode),
1327    arch(Dyninst::Arch_none)
1328 {
1329 #if defined(os_aix)
1330    archive = NULL;
1331    string file = desc_.file().c_str();
1332    SymtabAPI::SymtabError serr = SymtabAPI::Not_An_Archive;
1333
1334    startup_printf("%s[%d]:  opening file %s (or archive)\n", FILE__, __LINE__, file.c_str());
1335    if (!SymtabAPI::Archive::openArchive(archive, file))
1336    {
1337       err = true;
1338       if (archive->getLastError() != serr) {
1339          startup_printf("%s[%d]:  opened archive\n", FILE__, __LINE__);
1340          return;
1341       }
1342       else
1343       {
1344          startup_printf("%s[%d]:  opening file (not archive)\n", FILE__, __LINE__);
1345          if (!SymtabAPI::Symtab::openFile(linkedFile, file, BPatch_defensiveMode == mode)) 
1346          {
1347             startup_printf("%s[%d]:  opening file (not archive) failed\n", FILE__, __LINE__);
1348             err = true;
1349             return;
1350          }
1351          startup_printf("%s[%d]:  opened file\n", FILE__, __LINE__);
1352       }
1353    }
1354    else
1355    {
1356       assert (archive);
1357       startup_printf("%s[%d]:  getting member\n", FILE__, __LINE__);
1358       string member = std::string(desc_.member());
1359       if (member == fileDescriptor::emptyString) {
1360          fprintf(stderr, "%s[%d]:  WARNING:  not asking for unnamed member\n", FILE__, __LINE__);
1361       }
1362       else {
1363          if (!archive->getMember(linkedFile, member))
1364          {
1365             startup_printf("%s[%d]:  getting member failed\n", FILE__, __LINE__);
1366             err = true;
1367             return;
1368          }
1369          startup_printf("%s[%d]:  got member\n", FILE__, __LINE__);
1370       }
1371    }
1372    startup_printf("%s[%d]:  opened file %s (or archive)\n", FILE__, __LINE__, file.c_str());
1373 #elif defined(os_linux) || defined(os_freebsd)
1374    string file = desc_.file().c_str();
1375    if( desc_.member().empty() ) {
1376        startup_printf("%s[%d]:  opening file %s\n", FILE__, __LINE__, file.c_str());
1377        if( !SymtabAPI::Symtab::openFile(linkedFile, file, (BPatch_defensiveMode == mode ? Symtab::Defensive : Symtab::NotDefensive)) ) {
1378            err = true;
1379            return;
1380        }
1381    }else{
1382        startup_printf("%s[%d]: opening archive member: %s(%s)\n", FILE__, __LINE__, file.c_str(),
1383                desc_.member().c_str());
1384
1385        if( SymtabAPI::Archive::openArchive(archive, file) ) {
1386            if( !archive->getMember(linkedFile, const_cast<std::string&>(desc_.member())) ) {
1387                err = true;
1388                return;
1389            }
1390        }else{
1391            err = true;
1392            return;
1393        }
1394    }
1395 #elif defined(os_vxworks)
1396    string file = desc_.file();
1397    startup_printf("%s[%d]: opening file %s\n", FILE__, __LINE__, file.c_str());
1398    if( !Symtab::openFile(linkedFile, file) ) {
1399        startup_printf("%s[%d]: %s unavailable. Building info from target.\n",
1400                       FILE__, __LINE__, file.c_str());
1401        MappedFile *mf = MappedFile::createMappedFile(file);
1402        linkedFile = new Symtab::Symtab(mf);
1403    }
1404
1405    // Fill in remaining unknown information from remote target.
1406    fixup_offsets(file, linkedFile);
1407
1408 #else
1409         std::string file = desc_.file();
1410    startup_printf("%s[%d]: opening file %s\n", FILE__, __LINE__, file.c_str());
1411    Symtab::def_t symMode = (BPatch_defensiveMode == mode) ? 
1412        Symtab::Defensive : Symtab::NotDefensive;
1413    if(desc.rawPtr()) {
1414        linkedFile = new Symtab((unsigned char*)desc.rawPtr(), 
1415                                           desc.length(), 
1416                                           desc.file(), 
1417                                           symMode,
1418                                           err);
1419    } 
1420    else if(!Symtab::openFile(linkedFile, file, symMode)) 
1421    {
1422       err = true;
1423       return;
1424    }
1425 #endif
1426
1427    err = false;
1428
1429    // fix isSharedObject flag in file descriptor
1430    desc.setIsShared(!linkedFile->isExec());
1431    desc_.setIsShared(!linkedFile->isExec());
1432
1433    name_ = extract_pathname_tail(string(desc.file().c_str()));
1434
1435    //   fprintf(stderr,"img name %s\n",name_.c_str());
1436    pathname_ = desc.file().c_str();
1437
1438    // initialize (data members) codeOffset_, dataOffset_,
1439    //  codeLen_, dataLen_.
1440
1441    imageOffset_ = linkedFile->imageOffset();
1442    dataOffset_ = linkedFile->dataOffset();
1443
1444    imageLen_ = linkedFile->imageLength();
1445    dataLen_ = linkedFile->dataLength();
1446
1447    /*
1448     * When working with ELF .o's, it is a possibility that the region
1449     * which is referred to by imageOffset(), imageLength() could have a zero
1450     * length. This is okay for .o's
1451     */
1452
1453    // if unable to parse object file (somehow??), try to
1454    //  notify user/calling process + return....    
1455    if (!imageLen_ && 
1456        linkedFile->getObjectType() != SymtabAPI::obj_RelocatableFile)
1457     {
1458       string msg = string("Parsing problem with executable file: ") + desc.file();
1459       statusLine(msg.c_str());
1460       msg += "\n";
1461       logLine(msg.c_str());
1462       err = true;
1463       return;
1464    }
1465
1466    //Now add Main and Dynamic Symbols if they are not present
1467    startup_printf("%s[%d]:  before findMain\n", FILE__, __LINE__);
1468    findMain();
1469
1470    // Initialize ParseAPI 
1471    filt = NULL;
1472
1473    /** Optionally eliminate some hints in which Dyninst is not
1474        interested **/
1475    struct filt_heap : SymtabCodeSource::hint_filt {
1476         bool operator()(SymtabAPI::Function * f) {
1477             return f->getModule()->fullName() == "DYNINSTheap";
1478         }
1479     } nuke_heap;
1480     filt = &nuke_heap;
1481
1482    bool parseInAllLoadableRegions = (BPatch_normalMode != mode_);
1483    cs_ = new SymtabCodeSource(linkedFile,filt,parseInAllLoadableRegions);
1484
1485    // Continue ParseAPI init
1486    img_fact_ = new DynCFGFactory(this);
1487    parse_cb_ = new DynParseCallback(this);
1488    obj_ = new CodeObject(cs_,img_fact_,parse_cb_,BPatch_defensiveMode == mode);
1489
1490    string msg;
1491    // give user some feedback....
1492    msg = string("Parsing object file: ") + desc.file();
1493
1494    statusLine(msg.c_str());
1495
1496
1497    // look for `main' or something similar to recognize a.outs
1498    startup_printf("%s[%d]:  before determineImageType\n", FILE__, __LINE__);
1499    determineImageType();
1500    if (isDyninstRTLib()) { // don't parse gaps in the runtime library
1501        parseGaps_ = false;
1502    }
1503             
1504    // And symtab variables
1505    addSymtabVariables();
1506
1507    parseState_ = symtab;
1508 }
1509
1510 image::~image() 
1511 {
1512     unsigned i;
1513
1514     for (map<Module *, pdmodule *>::iterator iter = mods_.begin();
1515          iter != mods_.end(); iter++) {
1516         delete (iter->second);
1517     }
1518
1519     for (i = 0; i < everyUniqueVariable.size(); i++) {
1520         delete everyUniqueVariable[i];
1521     }
1522     everyUniqueVariable.clear();
1523     createdVariables.clear();
1524     exportedVariables.clear();
1525
1526    
1527     for (i = 0; i < parallelRegions.size(); i++)
1528       delete parallelRegions[i];
1529     parallelRegions.clear();
1530
1531     // Finally, remove us from the image list.
1532     for (i = 0; i < allImages.size(); i++) {
1533         if (allImages[i] == this)
1534             VECTOR_ERASE(allImages,i,i);
1535     }
1536
1537     if (pltFuncs) {
1538        delete pltFuncs;
1539        pltFuncs = NULL;
1540     }
1541
1542     if(obj_) delete obj_;
1543     if(cs_) delete cs_;
1544     if(img_fact_) delete img_fact_;
1545     if(parse_cb_) delete parse_cb_;
1546
1547     if (linkedFile) { SymtabAPI::Symtab::closeSymtab(linkedFile); }
1548 #if defined (os_aix)
1549     //fprintf(stderr, "%s[%d]:  IMAGE DTOR:  archive = %p\n", FILE__, __LINE__, archive);
1550     if (archive) delete archive;
1551 #endif
1552 }
1553
1554 bool pdmodule::findFunction( const std::string &name, pdvector<parse_func *> &found ) {
1555     if (findFunctionByMangled(name, found))
1556         return true;
1557     return findFunctionByPretty(name, found);
1558 }
1559
1560 bool pdmodule::findFunctionByMangled( const std::string &name,
1561                                       pdvector<parse_func *> &found)
1562 {
1563     // For efficiency sake, we grab the image vector and strip out the
1564     // functions we want.
1565     // We could also keep them all in modules and ditch the image-wide search; 
1566     // the problem is that BPatch goes by module and internal goes by image. 
1567     unsigned orig_size = found.size();
1568     
1569     const pdvector<parse_func *> *obj_funcs = imExec()->findFuncVectorByMangled(name.c_str());
1570     if (!obj_funcs) {
1571         return false;
1572     }
1573     for (unsigned i = 0; i < obj_funcs->size(); i++) {
1574         if ((*obj_funcs)[i]->pdmod() == this)
1575             found.push_back((*obj_funcs)[i]);
1576     }
1577     if (found.size() > orig_size) {
1578         //exec()->analyzeIfNeeded();
1579         return true;
1580     }
1581     
1582     return false;
1583 }
1584
1585
1586 bool pdmodule::findFunctionByPretty( const std::string &name,
1587                                      pdvector<parse_func *> &found)
1588 {
1589     // For efficiency sake, we grab the image vector and strip out the
1590     // functions we want.
1591     // We could also keep them all in modules and ditch the image-wide search; 
1592     // the problem is that BPatch goes by module and internal goes by image. 
1593     unsigned orig_size = found.size();
1594     
1595     const pdvector<parse_func *> *obj_funcs = imExec()->findFuncVectorByPretty(name);
1596     if (!obj_funcs) {
1597         return false;
1598     }
1599     for (unsigned i = 0; i < obj_funcs->size(); i++) {
1600         if ((*obj_funcs)[i]->pdmod() == this)
1601             found.push_back((*obj_funcs)[i]);
1602     }
1603     if (found.size() > orig_size) {
1604         //exec()->analyzeIfNeeded();
1605         return true;
1606     }
1607     
1608     return false;
1609 }
1610
1611 void pdmodule::dumpMangled(std::string &prefix) const
1612 {
1613   cerr << fileName() << "::dumpMangled("<< prefix << "): " << endl;
1614
1615   const CodeObject::funclist & allFuncs = imExec()->getAllFunctions();
1616   CodeObject::funclist::const_iterator fit = allFuncs.begin();
1617   for( ; fit != allFuncs.end(); ++fit) {
1618       parse_func * pdf = (parse_func*)*fit;
1619       if (pdf->pdmod() != this) continue;
1620
1621       if( ! strncmp( pdf->symTabName().c_str(), prefix.c_str(), strlen( prefix.c_str() ) ) ) {
1622           cerr << pdf->symTabName() << " ";
1623       }
1624       else {
1625           // bperr( "%s is not a prefix of %s\n", prefix, pdf->symTabName().c_str() );
1626       }
1627   }
1628   cerr << endl;
1629 }
1630
1631 parse_func *image::addFunction(Address functionEntryAddr, const char *fName)
1632  {
1633      set<CodeRegion *> regions;
1634      CodeRegion * region;
1635      codeObject()->cs()->findRegions(functionEntryAddr,regions);
1636      if(regions.empty()) {
1637         parsing_printf("[%s:%d] refusing to create function in nonexistent "
1638                        "region at %lx\n",
1639             FILE__,__LINE__,functionEntryAddr);
1640         return NULL;
1641      }
1642      region = *(regions.begin()); // XXX pick one, throwing up hands. 
1643
1644      pdmodule *mod = getOrCreateModule(linkedFile->getDefaultModule());
1645
1646      // copy or create function name
1647      char funcName[32];
1648      if (fName) {
1649          snprintf( funcName, 32, "%s", fName);
1650      } else {
1651          snprintf( funcName, 32, "entry_%lx", functionEntryAddr);       
1652      }
1653      Symbol *funcSym = new Symbol(funcName,
1654                                   Symbol::ST_FUNCTION,
1655                                   Symbol::SL_GLOBAL, 
1656                                   Symbol::SV_DEFAULT,
1657                                   functionEntryAddr, 
1658                                   mod->mod(),
1659                                   NULL,
1660                                   UINT_MAX);
1661      // create function stub, update datastructures
1662      if (!linkedFile->addSymbol( funcSym )) {
1663          return NULL;
1664      }
1665      
1666      // Adding the symbol finds or creates a Function object...
1667      assert(funcSym->getFunction());
1668
1669      // Parse, but not recursively
1670      codeObject()->parse(functionEntryAddr, false); 
1671
1672      parse_func * func = static_cast<parse_func*>(
1673             codeObject()->findFuncByEntry(region,functionEntryAddr));
1674
1675      if(NULL == func) {
1676         parsing_printf("[%s:%d] failed to create function at %lx\n",
1677             FILE__,__LINE__,functionEntryAddr);
1678         return NULL;
1679      }
1680
1681      if (!func->getSymtabFunction()->addAnnotation(func, ImageFuncUpPtrAnno))
1682      {
1683         fprintf(stderr, "%s[%d]: failed to add annotation here\n", FILE__, __LINE__);
1684         return NULL;
1685      }
1686
1687      // If this is a Dyninst dynamic heap placeholder, add it to the
1688      // list of inferior heaps...
1689      string compString = "DYNINSTstaticHeap";
1690      if (!func->symTabName().compare(0, compString.size(), compString)) {
1691          codeHeaps_.push_back(pair<string, Address>(func->symTabName(), func->getOffset()));
1692      }
1693
1694      func->addSymTabName( funcName ); 
1695      func->addPrettyName( funcName );
1696      // funcsByEntryAddr[func->getOffset()] = func;
1697      //createdFunctions.push_back(func);
1698
1699      return func;
1700 }
1701
1702 const string &pdmodule::fileName() const
1703 {
1704     return mod_->fileName();
1705 }
1706
1707 const string &pdmodule::fullName() const
1708 {
1709     return mod_->fullName();
1710 }
1711
1712 SymtabAPI::supportedLanguages 
1713 pdmodule::language() const
1714 {
1715     return mod_->language();
1716 }
1717
1718 Address pdmodule::addr() const
1719 {
1720     return mod_->addr();
1721 }
1722
1723 bool pdmodule::isShared() const
1724 {
1725     return mod_->isShared();
1726 }
1727
1728 Module *pdmodule::mod()
1729 {
1730     return mod_;
1731 }
1732
1733 pdmodule *image::getOrCreateModule(Module *mod) {
1734     if (mods_.find(mod) != mods_.end())
1735         return mods_[mod];
1736
1737     pdmodule *pdmod = new pdmodule(mod, this);
1738
1739     mods_[mod] = pdmod;
1740     modsByFileName[pdmod->fileName()] = pdmod;
1741     modsByFullName[pdmod->fullName()] = pdmod;
1742     
1743     return pdmod;
1744 }
1745
1746 namespace {
1747     /* 
1748      * See ParseAPI::SymtabCodeSource::lookup_region for 
1749      * details about this
1750      */  
1751     CodeRegion * aix_region_hack(set<CodeRegion *> regs,Address addr)
1752     {
1753         set<CodeRegion*>::iterator rit = regs.begin();
1754         for( ; rit != regs.end(); ++rit) {
1755             CodeRegion * tmp = *rit;
1756             if(tmp->isCode(addr))
1757                 return tmp;
1758         }
1759         return *regs.begin();
1760     }
1761 };
1762
1763
1764 /*********************************************************************/
1765 /**** Function lookup (by name or address) routines               ****/
1766 /****                                                             ****/
1767 /**** Overlapping region objects MUST NOT use these routines(+)   ****/
1768 /*********************************************************************/
1769 /*
1770  * (+) that is, except on AIX which is just /different/
1771  */
1772
1773 int
1774 image::findFuncs(const Address offset, set<Function *> & funcs) {
1775     analyzeIfNeeded();
1776
1777     set<CodeRegion *> match;
1778     int cnt = cs_->findRegions(offset,match);
1779     if(cnt == 0)
1780         return 0;
1781     else if(cnt == 1)
1782         return obj_->findFuncs(*match.begin(),offset,funcs);
1783
1784 #if !defined(os_aix)
1785         fprintf(stderr,"[%s:%d] image::findFuncs(offset) called on "
1786                        "overlapping-region object\n",
1787             FILE__,__LINE__);
1788         assert(0);
1789         return 0;
1790 #else
1791     CodeRegion * single = aix_region_hack(match,offset);
1792     return obj_->findFuncs(single,offset,funcs);
1793 #endif 
1794 }
1795
1796 parse_func *image::findFuncByEntry(const Address &entry) {
1797     analyzeIfNeeded();
1798
1799     set<CodeRegion *> match;
1800     int cnt = cs_->findRegions(entry,match);
1801     if(cnt == 0)
1802         return 0;
1803     else if(cnt == 1)
1804         return (parse_func*)obj_->findFuncByEntry(*match.begin(),entry);
1805
1806 #if !defined(os_aix)
1807     fprintf(stderr,"[%s:%d] image::findFuncByEntry(entry) called on "
1808                    "overlapping-region object\n",
1809         FILE__,__LINE__);
1810     assert(0);
1811     return 0;
1812 #else
1813     CodeRegion * single = aix_region_hack(match,entry);
1814     return (parse_func*)obj_->findFuncByEntry(single,entry);
1815 #endif 
1816 }
1817
1818 int 
1819 image::findBlocksByAddr(const Address addr, set<ParseAPI::Block *> & blocks ) 
1820 {
1821     analyzeIfNeeded();
1822
1823     set<CodeRegion *> match;
1824     int cnt = cs_->findRegions(addr,match);
1825     if(cnt == 0)
1826         return 0;
1827     else if(cnt == 1)
1828         return obj_->findBlocks(*match.begin(),addr,blocks);
1829
1830 #if !defined(os_aix)
1831         fprintf(stderr,"[%s:%d] image::findBlocks(offset) called on "
1832                        "overlapping-region object\n",
1833             FILE__,__LINE__);
1834         assert(0);
1835         return 0;
1836 #else
1837     CodeRegion * single = aix_region_hack(match,addr);
1838     return obj_->findBlocks(single,addr,blocks);
1839 #endif
1840 }
1841
1842 // Return the vector of functions associated with a pretty (demangled) name
1843 // Very well might be more than one!
1844
1845 const pdvector<parse_func *> *image::findFuncVectorByPretty(const std::string &name) {
1846     //Have to change here
1847     pdvector<parse_func *>* res = new pdvector<parse_func *>;
1848     vector<SymtabAPI::Function *> funcs;
1849     linkedFile->findFunctionsByName(funcs, name.c_str(), SymtabAPI::prettyName);
1850
1851     for(unsigned index=0; index < funcs.size(); index++)
1852     {
1853         SymtabAPI::Function *symFunc = funcs[index];
1854         parse_func *imf = NULL;
1855         
1856         if (!symFunc->getAnnotation(imf, ImageFuncUpPtrAnno)) {
1857           // TODO: just create the function here...
1858
1859            return NULL;
1860         }
1861         
1862         if (imf) {
1863             res->push_back(imf);
1864         }
1865
1866
1867     }           
1868     if(res->size())     
1869         return res;         
1870     else {
1871         delete res;
1872         return NULL;
1873     }
1874 }
1875
1876 // Return the vector of functions associated with a mangled name
1877 // Very well might be more than one! -- multiple static functions in different .o files
1878
1879 const pdvector <parse_func *> *image::findFuncVectorByMangled(const std::string &name)
1880 {
1881     pdvector<parse_func *>* res = new pdvector<parse_func *>;
1882
1883     vector<SymtabAPI::Function *> funcs;
1884     linkedFile->findFunctionsByName(funcs, name.c_str(), SymtabAPI::mangledName);
1885
1886     for(unsigned index=0; index < funcs.size(); index++) {
1887         SymtabAPI::Function *symFunc = funcs[index];
1888         parse_func *imf = NULL;
1889         
1890         if (!symFunc->getAnnotation(imf, ImageFuncUpPtrAnno)) {
1891             return NULL;
1892         }
1893         
1894         if (imf) {
1895             res->push_back(imf);
1896         }
1897
1898     }       
1899     if(res->size()) 
1900         return res;         
1901     else {
1902         delete res;
1903         return NULL;
1904     }   
1905 }
1906
1907 const pdvector <image_variable *> *image::findVarVectorByPretty(const std::string &name)
1908 {
1909     pdvector<image_variable *>* res = new pdvector<image_variable *>;
1910
1911     vector<Variable *> vars;
1912     linkedFile->findVariablesByName(vars, name.c_str(), SymtabAPI::prettyName);
1913     
1914     for (unsigned index=0; index < vars.size(); index++) {
1915         Variable *symVar = vars[index];
1916         image_variable *imv = NULL;
1917         
1918         if (!symVar->getAnnotation(imv, ImageVariableUpPtrAnno)) {
1919             fprintf(stderr, "%s[%d]:  failed to getAnnotations here\n", FILE__, __LINE__);
1920             return NULL;
1921         }
1922
1923        if (imv) {
1924            res->push_back(imv);
1925        }
1926     }       
1927     if(res->size())     
1928         return res;         
1929     else {
1930         delete res;
1931         return NULL;
1932     }
1933 }
1934
1935 const pdvector <image_variable *> *image::findVarVectorByMangled(const std::string &name)
1936 {
1937     //    fprintf(stderr,"findVariableVectorByPretty %s\n",name.c_str());
1938 #ifdef IBM_BPATCH_COMPAT_STAB_DEBUG
1939     bperr( "%s[%d]:  inside findVariableVectorByPretty\n", FILE__, __LINE__);
1940 #endif
1941     pdvector<image_variable *>* res = new pdvector<image_variable *>;
1942
1943     vector<Variable *> vars;
1944     linkedFile->findVariablesByName(vars, name.c_str(), SymtabAPI::mangledName);
1945     
1946     for (unsigned index=0; index < vars.size(); index++) {
1947         Variable *symVar = vars[index];
1948         image_variable *imv = NULL;
1949         
1950         if (!symVar->getAnnotation(imv, ImageVariableUpPtrAnno)) {
1951             fprintf(stderr, "%s[%d]:  failed to getAnnotations here\n", FILE__, __LINE__);
1952             return NULL;
1953         }
1954
1955         if (imv) {
1956             res->push_back(imv);
1957         }
1958     }       
1959     if(res->size())     
1960         return res;         
1961     else {
1962         delete res;
1963         return NULL;
1964     }
1965   /*
1966   if (varsByMangled.defines(name)) {
1967       //analyzeIfNeeded();
1968       return varsByMangled[name];
1969   }
1970   return NULL;*/
1971 }
1972
1973 bool pdmodule::getFunctions(pdvector<parse_func *> &funcs)  {
1974     unsigned curFuncSize = funcs.size();
1975     const CodeObject::funclist & allFuncs = imExec()->getAllFunctions();
1976     
1977     CodeObject::funclist::const_iterator fit = allFuncs.begin();
1978     for( ; fit != allFuncs.end(); ++fit) {
1979         parse_func *f = (parse_func*)*fit;
1980         if (f->pdmod() == this) 
1981         {
1982             funcs.push_back(f);
1983         }
1984     }
1985   
1986     return (funcs.size() > curFuncSize);
1987 } /* end getFunctions() */
1988
1989 /* Instrumentable-only, by the last version's source. */
1990 bool pdmodule::getVariables(pdvector<image_variable *> &vars)  {
1991     pdvector<image_variable *> allVars = imExec()->getAllVariables();
1992     unsigned curVarSize = vars.size();
1993
1994     for (unsigned i = 0; i < allVars.size(); i++) {
1995         if (allVars[i]->pdmod() == this)
1996             vars.push_back(allVars[i]);
1997     }
1998   
1999     return (vars.size() > curVarSize);
2000 } /* end getFunctions() */
2001
2002 /*
2003 void *image::getPtrToDataInText( Address offset ) const {
2004     if( isData(offset) ) { return NULL; }
2005     if( ! isCode(offset) ) { return NULL; }
2006         
2007     Region *reg = linkedFile->findEnclosingRegion(offset);
2008     if(reg != NULL) {
2009         return (void*) ((Address)reg->getPtrToRawData() + offset 
2010                         - reg->getMemOffset());
2011     }
2012     return NULL;
2013 } *//* end getPtrToDataInText() */
2014     
2015 bool image::getExecCodeRanges(std::vector<std::pair<Address, Address> > &ranges)
2016 {
2017    std::vector<Region *> regions;
2018    bool result = linkedFile->getCodeRegions(regions);
2019    if (!result)
2020       return false;
2021    Address cur_start = 0, cur_end = (Address)(-1);
2022    bool found_something = false;
2023    fprintf(stderr, "\n");
2024    for (std::vector<Region *>::iterator i = regions.begin(); i != regions.end(); i++)
2025    {
2026       Region *r = *i;
2027       if (!r->isStandardCode() && !codeObject()->defensiveMode())
2028          continue;
2029       if (!found_something) {
2030          cur_start = r->getDiskOffset();
2031          cur_end = cur_start + r->getDiskSize();
2032          found_something = true;
2033          continue;
2034       }
2035
2036       if (r->getDiskOffset() <= cur_end) {
2037          cur_end = r->getDiskOffset() + r->getDiskSize();
2038       }
2039       else {
2040          ranges.push_back(std::pair<Address, Address>(cur_start, cur_end));
2041          cur_start = r->getDiskOffset();
2042          cur_end = cur_start + r->getDiskSize();
2043       }
2044    }
2045    if (!found_something) {
2046       return false;
2047    }
2048    ranges.push_back(std::pair<Address, Address>(cur_start, cur_end));
2049    return true;
2050 }
2051
2052 Symbol *image::symbol_info(const std::string& symbol_name) {
2053    vector< Symbol *> symbols;
2054    if(!(linkedFile->findSymbol(symbols,symbol_name.c_str(),Symbol::ST_UNKNOWN, SymtabAPI::anyName))) 
2055        return false;
2056
2057    return symbols[0];
2058 }
2059
2060 bool image::findSymByPrefix(const std::string &prefix, pdvector<Symbol *> &ret) {
2061     unsigned start;
2062     vector <Symbol *>found;     
2063     std::string reg = prefix+std::string("*");
2064     if(!linkedFile->findSymbol(found, reg.c_str(), Symbol::ST_UNKNOWN, SymtabAPI::anyName, true))
2065         return false;
2066     for(start=0;start< found.size();start++)
2067                 ret.push_back(found[start]);
2068         return true;    
2069 }
2070
2071 dictionary_hash<Address, std::string> *image::getPltFuncs()
2072 {
2073    bool result;
2074    if (pltFuncs)
2075       return pltFuncs;
2076
2077
2078    vector<SymtabAPI::relocationEntry> fbt;
2079    result = getObject()->getFuncBindingTable(fbt);
2080    if (!result)
2081       return NULL;
2082
2083    pltFuncs = new dictionary_hash<Address, std::string>(addrHash);
2084    assert(pltFuncs);
2085    for(unsigned k = 0; k < fbt.size(); k++) {
2086 #if defined(os_vxworks)
2087        if (fbt[k].target_addr() == 0) {
2088            (*pltFuncs)[fbt[k].rel_addr()] = fbt[k].name().c_str();
2089        }
2090 #else
2091       (*pltFuncs)[fbt[k].target_addr()] = fbt[k].name().c_str();
2092 #endif
2093    }
2094    return pltFuncs;
2095 }
2096
2097 void image::getPltFuncs(std::map<Address, std::string> &out)
2098 {
2099    out.clear();
2100    vector<SymtabAPI::relocationEntry> fbt;
2101    bool result = getObject()->getFuncBindingTable(fbt);
2102    if (!result)
2103       return;
2104
2105    for(unsigned k = 0; k < fbt.size(); k++) {
2106       out[fbt[k].target_addr()] = fbt[k].name();
2107    }
2108 }
2109
2110 image_variable* image::createImageVariable(Offset offset, std::string name, int size, pdmodule *mod)
2111 {
2112     // What to do here?
2113     if (varsByAddr.defines(offset))
2114         return varsByAddr[offset];
2115
2116     Variable *sVar = getObject()->createVariable(name, offset, size, mod->mod());
2117
2118     image_variable *ret = new image_variable(sVar, mod);
2119
2120     extern AnnotationClass<image_variable> ImageVariableUpPtrAnno;
2121     if (!sVar->addAnnotation(ret, ImageVariableUpPtrAnno)) {
2122         fprintf(stderr, "%s[%d]:  failed to add annotation here\n", FILE__, __LINE__);
2123     }
2124
2125     createdVariables.push_back(ret);
2126     everyUniqueVariable.push_back(ret);
2127     varsByAddr[offset] = ret;
2128     return ret;
2129 }
2130
2131
2132 const vector<parse_block*> & image::getNewBlocks() const
2133 {
2134     return newBlocks_;
2135 }
2136 void image::clearNewBlocks()
2137 {
2138     newBlocks_.clear();
2139 }
2140
2141 void image::setImageLength(Address newlen)
2142 {
2143     imageLen_ = newlen; 
2144 }
2145
2146 void image::destroy(ParseAPI::Block *) {}
2147 void image::destroy(ParseAPI::Edge *) {}
2148 void image::destroy(ParseAPI::Function *) {}