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