Turns off gap parsing for Dyninst's runtime library and removes compiler warnings
[dyninst.git] / dyninstAPI / src / mapped_object.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: mapped_object.C,v 1.39 2008/09/03 06:08:44 jaw Exp $
33
34 #include <string>
35
36 #include "dyninstAPI/src/mapped_object.h"
37 #include "dyninstAPI/src/mapped_module.h"
38 #include "dyninstAPI/src/symtab.h"
39 #include "dyninstAPI/src/function.h"
40 #include "dyninstAPI/src/debug.h"
41 #include "symtabAPI/h/Symtab.h"
42 #include "process.h"
43 #include "InstructionDecoder.h"
44 #include "Parsing.h"
45 #include "instPoint.h"
46
47 using namespace Dyninst;
48 using namespace Dyninst::ParseAPI;
49
50 #define FS_FIELD_SEPERATOR '/'
51
52 // Whee hasher...
53
54 unsigned imgFuncHash(const image_func * const &func) {
55     return addrHash4((Address) func);
56 }
57 unsigned imgVarHash(const image_variable * const &func) 
58 {
59     return addrHash4((Address) func);
60 }
61
62 // triggered when parsing needs to check if the underlying data has changed
63 void codeBytesUpdateCB(void *objCB, SymtabAPI::Region *reg, Address addr)
64 {
65     mapped_object *obj = (mapped_object*) objCB;
66     assert(obj);
67     obj->updateMappedFileIfNeeded(addr,reg);
68 }
69
70 mapped_object::mapped_object(fileDescriptor fileDesc,
71       image *img,
72       AddressSpace *proc,
73       BPatch_hybridMode mode):
74    desc_(fileDesc),
75    fullName_(fileDesc.file()), 
76    everyUniqueFunction(imgFuncHash),
77    everyUniqueVariable(imgVarHash),
78    allFunctionsByMangledName(::Dyninst::stringhash),
79    allFunctionsByPrettyName(::Dyninst::stringhash),
80    allVarsByMangledName(::Dyninst::stringhash),
81    allVarsByPrettyName(::Dyninst::stringhash),
82    dirty_(false),
83    dirtyCalled_(false),
84    image_(img),
85    dlopenUsed(false),
86    proc_(proc),
87    analyzed_(false),
88    analysisMode_(mode)
89
90    // Set occupied range (needs to be ranges)
91    codeBase_ = fileDesc.code();
92    dataBase_ = fileDesc.data();
93 #if defined(os_windows)
94    codeBase_ = fileDesc.loadAddr();
95    dataBase_ = fileDesc.loadAddr();
96 #endif
97 #if defined(os_aix)
98    // AIX defines "virtual" addresses for an a.out inside the file as
99    // well as when the system loads the object. As far as I can tell,
100    // this only happens for the a.out (for shobjs the file-addresses
101    // are 0).  The file-provided addresses are correct, but the
102    // OS-provided addresses are not. So if the file includes
103    // addresses, use those.  If it doesn't, all of the offsets are
104    // from a "section start" that isn't our start. Getting a headache
105    // yet? So _that_ needs to be adjusted. We've stored these values
106    // in the Object file. We could also adjust all addresses of
107    // symbols, but...
108    if (image_->imageOffset() >= codeBase_) {
109       codeBase_ = 0;
110    }
111    else if (image_->imageOffset() <= 0x1fffffff) {
112       // GCC-ism. This is a shared library with a a.out-like codeOffset.
113       // We need to make our base the difference between the two...
114       codeBase_ -= image_->imageOffset();
115       SymtabAPI::Region *sec;
116       image_->getObject()->findRegion(sec, ".text");
117       //fprintf(stderr, "codeBase 0x%x, rawPtr 0x%x, BaseOffset 0x%x, size %d\n",
118       //        codeBase_, (Address)sec->getPtrToRawData() , image_->getObject()->getBaseAddress());
119       codeBase_ += ((Address)sec->getPtrToRawData() - image_->getObject()->getBaseOffset());    
120       //      codeBase_ += image_->getObject()->text_reloc();
121    }
122    else {
123       // codeBase_ is the address that the chunk was loaded at; the actual interesting
124       // bits start within the chunk. So add in text_reloc (actually, "offset from start
125       // of file to interesting bits"). 
126       // Non-GCC shared libraries.
127       //codeBase_ += image_->getObject()->text_reloc();
128       SymtabAPI::Region *sec;
129       image_->getObject()->findRegion(sec, ".text");
130       //fprintf(stderr, "codeBase 0x%x, rawPtr 0x%x, BaseOffset 0x%x, size %d\n",
131       //        codeBase_, (Address)sec->getPtrToRawData() , image_->getObject()->getBaseOffset());
132       codeBase_ += ((Address)sec->getPtrToRawData()-image_->getObject()->getBaseOffset());
133    }
134    if (image_->dataOffset() >= dataBase_) {
135       dataBase_ = 0;
136    }
137    else if (image_->dataOffset() <= 0x2fffffff) {
138       // More GCC-isms. 
139       dataBase_ -= image_->dataOffset();
140    }
141    else {
142       // *laughs* You'd think this was the same way, right?
143       // Well, you're WRONG!
144       // For some reason we don't need to add in the data_reloc_...
145       //dataBase_ += image_->getObject()->data_reloc();
146    }
147 #endif
148
149 #if 0
150    fprintf(stderr, "Creating new mapped_object %s/%s\n",
151          fullName_.c_str(), getFileDesc().member().c_str());
152    fprintf(stderr, "codeBase 0x%x, codeOffset 0x%x, size %d\n",
153          codeBase_, image_->imageOffset(), image_->imageLength());
154    fprintf(stderr, "dataBase 0x%x, dataOffset 0x%x, size %d\n",
155          dataBase_, image_->dataOffset(), image_->dataLength());
156    fprintf(stderr, "fileDescriptor: code at 0x%x, data 0x%x\n",
157          fileDesc.code(), fileDesc.data());
158    fprintf(stderr, "Code: 0x%lx to 0x%lx\n",
159          codeAbs(), codeAbs() + imageSize());
160    fprintf(stderr, "Data: 0x%lx to 0x%lx\n",
161          dataAbs(), dataAbs() + dataSize());
162 #endif
163
164
165    // Sets "fileName_"
166    set_short_name();
167 }
168
169 mapped_object *mapped_object::createMappedObject(fileDescriptor &desc,
170       AddressSpace *p,
171       BPatch_hybridMode analysisMode, 
172       bool parseGaps) 
173 {
174
175    if (!p) return NULL;
176
177    startup_printf("%s[%d]:  about to parseImage\n", FILE__, __LINE__);
178    startup_printf("%s[%d]: name %s, codeBase 0x%lx, dataBase 0x%lx\n",
179                   FILE__, __LINE__, desc.file().c_str(), desc.code(), desc.data());
180    image *img = image::parseImage( desc, analysisMode, parseGaps );
181    if (!img)  {
182       startup_printf("%s[%d]:  failed to parseImage\n", FILE__, __LINE__);
183       return NULL;
184    }
185    if (img->isDyninstRTLib()) {
186        parseGaps = false;
187    }
188
189 #if defined(os_linux) && defined(arch_x86_64)
190    //Our x86_64 is actually reporting negative load addresses.  Go fig.
191    // On Linux/x86_64 with 32-bit mutatees this causes problems because we
192    // treat the load address as a unsigned 64 bit integer, and things don't
193    // correctly wrap.
194    //
195    // We'll detect this by noticing that the dynamic entry doesn't match up
196    // and then correct.
197    if (desc.dynamic() &&
198        p->getAddressWidth() == 4 && 
199        img->getObject()->getElfDynamicOffset() + desc.code() != desc.dynamic())
200    {
201       Address new_load_addr;
202       new_load_addr = desc.dynamic() - img->getObject()->getElfDynamicOffset();
203       startup_printf("[%s:%u] - Incorrect binary load address %lx, changing " 
204               "to %lx\n", FILE__, __LINE__, (unsigned long) desc.code(), 
205               (unsigned long) new_load_addr);
206       desc.setCode(new_load_addr);
207       desc.setData(new_load_addr);
208    }
209 #endif
210    if (!desc.isSharedObject()) {
211       //We've seen a case where the a.out is a shared object (RHEL4's
212       // version of ssh).  Check if the shared object flag is set in the
213       // binary (which is different from the isSharedObject()) call above.
214       // If so, we need to update the load address.
215       if (p->proc() &&
216             (img->getObject()->getObjectType() == SymtabAPI::obj_SharedLib)) {
217          //Executable is a shared lib
218          p->proc()->setAOutLoadAddress(desc);
219       }
220       // Search for main, if we can't find it, and we're creating the process, 
221       // and not attaching to it, we can find it by instrumenting libc.so
222       // Currently this has only been implemented for linux 
223 #if defined(os_linux)
224       // More specifically, x86 and x86_64 linux
225 #if defined(arch_x86) || defined(arch_x86_64)
226
227       vector <SymtabAPI::Function *> main;
228       if (p->proc() && 
229           (p->proc()->getTraceState() == noTracing_ts) &&
230           !p->proc()->wasCreatedViaAttach() &&
231           (!img->getObject()->findFunctionsByName(main,"main") &&
232            !img->getObject()->findFunctionsByName(main,"_main"))) {
233           fprintf(stderr, "[%s][%d] Module: %s in process %d:\n"
234                "\t  is not a shared object so it should contain a symbol for \n"
235                "\t  function main. Initial attempt to locate main failed,\n"
236                "\t  possibly due to the lack of a .text section\n",
237                __FILE__,__LINE__,desc.file().c_str(), p->proc()->getPid());
238          p->proc()->setTraceSysCalls(true);
239          p->proc()->setTraceState(libcOpenCall_ts);
240       }
241
242 #endif // arch_x86 || arch_x86_64
243 #endif // os_linux
244    }
245
246    // Adds exported functions and variables..
247    startup_printf("%s[%d]:  creating mapped object\n", FILE__, __LINE__);
248    mapped_object *obj = new mapped_object(desc, img, p);
249    startup_printf("%s[%d]:  leaving createMappedObject(%s)\n", FILE__, __LINE__, desc.file().c_str());
250
251    return obj;
252 }
253
254 mapped_object::mapped_object(const mapped_object *s, process *child) :
255    codeRange(),
256    desc_(s->desc_),
257    fullName_(s->fullName_),
258    fileName_(s->fileName_),
259    codeBase_(s->codeBase_),
260    dataBase_(s->dataBase_),
261    everyUniqueFunction(imgFuncHash),
262    everyUniqueVariable(imgVarHash),
263    allFunctionsByMangledName(::Dyninst::stringhash),
264    allFunctionsByPrettyName(::Dyninst::stringhash),
265    allVarsByMangledName(::Dyninst::stringhash),
266    allVarsByPrettyName(::Dyninst::stringhash),
267    dirty_(s->dirty_),
268    dirtyCalled_(s->dirtyCalled_),
269    image_(s->image_),
270    dlopenUsed(s->dlopenUsed),
271    proc_(child),
272    analyzed_(s->analyzed_),
273    analysisMode_(s->analysisMode_)
274 {
275    // Let's do modules
276    for (unsigned k = 0; k < s->everyModule.size(); k++) {
277       // Doesn't copy things like line info. Ah, well.
278       mapped_module *parMod = s->everyModule[k];
279       mapped_module *mod = mapped_module::createMappedModule(this, parMod->pmod());
280       assert(mod);
281       everyModule.push_back(mod);
282    }
283
284    const pdvector<int_function *> parFuncs = s->everyUniqueFunction.values();
285    for (unsigned i = 0; i < parFuncs.size(); i++) {
286       int_function *parFunc = parFuncs[i];
287       assert(parFunc->mod());
288       mapped_module *mod = getOrCreateForkedModule(parFunc->mod());
289       int_function *newFunc = new int_function(parFunc,
290             mod,
291             child);
292       addFunction(newFunc);
293    }
294
295    const pdvector<int_variable *> parVars = s->everyUniqueVariable.values();
296    for (unsigned j = 0; j < parVars.size(); j++) {
297       int_variable *parVar = parVars[j];
298       assert(parVar->mod());
299       mapped_module *mod = getOrCreateForkedModule(parVar->mod());
300       int_variable *newVar = new int_variable(parVar,
301             mod);
302       addVariable(newVar);
303    }
304
305    image_ = s->image_->clone();
306 }
307
308
309 mapped_object::~mapped_object() 
310 {
311    // desc_ is static
312    // fullName_ is static
313    // fileName_ is static
314    // codeBase_ is static
315    // dataBase_ is static
316
317    for (unsigned i = 0; i < everyModule.size(); i++)
318       delete everyModule[i];
319    everyModule.clear();    
320
321    pdvector<int_function *> funcs = everyUniqueFunction.values();
322    for (unsigned j = 0; j < funcs.size(); j++) {
323       delete funcs[j];
324    }
325    everyUniqueFunction.clear();
326
327    pdvector<int_variable *> vars = everyUniqueVariable.values();
328    for (unsigned k = 0; k < vars.size(); k++) {
329       delete vars[k];
330    }
331    everyUniqueVariable.clear();
332
333    pdvector<pdvector<int_function *> * > mangledFuncs = allFunctionsByMangledName.values();
334    for (unsigned i = 0; i < mangledFuncs.size(); i++) {
335       delete mangledFuncs[i];
336    }
337    allFunctionsByMangledName.clear();
338
339    pdvector<pdvector<int_function *> * > prettyFuncs = allFunctionsByPrettyName.values();
340    for (unsigned i = 0; i < prettyFuncs.size(); i++) {
341       delete prettyFuncs[i];
342    }
343    allFunctionsByPrettyName.clear();
344
345    pdvector<pdvector<int_variable *> * > mV = allVarsByMangledName.values();
346    for (unsigned i = 0; i < mV.size(); i++) {
347       delete mV[i];
348    }
349    allVarsByMangledName.clear();
350
351    pdvector<pdvector<int_variable *> * > pV = allVarsByPrettyName.values();
352    for (unsigned i = 0; i < pV.size(); i++) {
353       delete pV[i];
354    }
355    allVarsByPrettyName.clear();
356
357    // codeRangesByAddr_ is static
358     // Remainder are static
359    image::removeImage(image_);
360 }
361
362 bool mapped_object::analyze() 
363 {
364     if (analyzed_) return true;
365   // Create a process-specific version of the image; all functions and
366   // variables at an absolute address (and modifiable).
367   
368   // At some point, we should do better handling of base
369   // addresses. Right now we assume we have one per mapped object; AIX
370   // is a special case with two (one for functions, one for
371   // variables).
372   
373   if (!image_) return false;
374
375   image_->analyzeIfNeeded();
376
377   analyzed_ = true;
378
379   // We already have exported ones. Force analysis (if needed) and get
380   // the functions we created via analysis.
381   CodeObject::funclist & allFuncs = parse_img()->getAllFunctions();
382   CodeObject::funclist::iterator fit = allFuncs.begin();
383   for( ; fit != allFuncs.end(); ++fit) {
384   // For each function, we want to add our base address
385       if((*fit)->src() != HINT)
386         findFunction((image_func*)*fit);
387   }
388   
389   // Remember: variables don't.
390   pdvector<image_variable *> unmappedVars = image_->getCreatedVariables();
391   for (unsigned vi = 0; vi < unmappedVars.size(); vi++) {
392       findVariable(unmappedVars[vi]);
393   }
394   return true;
395 }
396
397 /* In the event that new functions are discovered after the analysis
398  * phase, we need to trigger analysis and enter it into the
399  * appropriate datastructures.
400  */
401
402 // FIXME has not been updated for ParseAPI
403 bool mapped_object::analyzeNewFunctions(vector<image_func *> *funcs)
404 {
405     if (!funcs || !funcs->size()) {
406         return false;
407     }
408
409     vector<image_func *>::iterator curfunc = funcs->begin();
410     while (curfunc != funcs->end()) {
411         if (everyUniqueFunction.defines(*curfunc)) {
412             curfunc = funcs->erase(curfunc);
413         } else {
414
415
416
417             // do control-flow traversal parsing starting from this function
418             /* FIXME IMPLEMENT for parseapi
419             if((*curfunc)->parse()) {
420                 parse_img()->recordFunction(*curfunc);
421             } // FIXME else?
422             */
423
424             curfunc++;
425         }
426     }
427     if (! funcs->size()) {
428         return true;
429     }
430
431     // add the functions we created (non-HINT source) to our datastructures
432     CodeObject::funclist & allFuncs = parse_img()->getAllFunctions();
433     CodeObject::funclist::iterator fit = allFuncs.begin();
434     for( ; fit != allFuncs.end(); ++fit) {
435         image_func *curFunc = (image_func*)*fit;
436         if(curFunc->src() == HINT)
437             continue;
438         if ( ! everyUniqueFunction.defines(curFunc) ) { 
439             // add function to datastructures
440             findFunction(curFunc);
441         }
442     }
443     return true;
444 }
445
446 // TODO: this should probably not be a mapped_object method, but since
447 // for now it is only used by mapped_objects it is
448 // from a string that is a complete path name to a function in a module
449 // (ie. "/usr/lib/libc.so.1/write") return a string with the function
450 // part removed.  return 0 on error
451 char *mapped_object::getModulePart(std::string &full_path_name) {
452     
453     char *whole_name = P_strdup(full_path_name.c_str());
454     char *next=0;
455     char *last=next;
456     if((last = P_strrchr(whole_name, '/'))){
457         next = whole_name;
458         for(u_int i=0;(next!=last)&&(i<full_path_name.length()); i++){
459             next++;
460             if(next == last){
461                 u_int size = i+2;
462                 char *temp_str = new char[size];
463                 if(P_strncpy(temp_str,whole_name,size-1)){
464                     temp_str[size-1] = '\0';
465                     delete whole_name;
466                     return temp_str;
467                     temp_str = 0;
468                 } 
469             }
470         }
471     }
472     delete whole_name;
473     return 0;
474 }
475
476 mapped_module *mapped_object::findModule(string m_name, bool wildcard)
477 {
478    parsing_printf("findModule for %s (substr match %d)\n",
479          m_name.c_str(), wildcard);
480    std::string tmp = m_name.c_str();      
481    for (unsigned i = 0; i < everyModule.size(); i++) {
482       if (everyModule[i]->fileName() == m_name ||
483             everyModule[i]->fullName() == m_name ||
484             (wildcard &&
485              (wildcardEquiv(tmp, everyModule[i]->fileName()) ||
486               wildcardEquiv(tmp, everyModule[i]->fullName())))) {
487          //parsing_printf("... found!\n");
488          return everyModule[i];
489       }
490    }
491    // Create a new one IF there's one in the child pd_module
492
493    pdmodule *pdmod = image_->findModule(m_name, wildcard);
494    if (pdmod) {
495       mapped_module *mod = mapped_module::createMappedModule(this,
496             pdmod);
497       everyModule.push_back(mod);
498       //parsing_printf("... made new module!\n");
499       return mod;
500    }
501    else {
502       //parsing_printf("... error, no module found...\n");
503       return NULL;
504    }
505 }
506
507
508 mapped_module *mapped_object::findModule(pdmodule *pdmod) 
509 {
510    if (!pdmod) {
511       fprintf(stderr, "%s[%d]:  please call this findModule with nonNULL parameter\n", FILE__, __LINE__);
512       return NULL;
513    }
514
515    assert(pdmod);
516
517    if (pdmod->imExec() != parse_img()) {
518       fprintf(stderr, "%s[%d]: WARNING: lookup for module in wrong mapped object! %p != %p\n", FILE__, __LINE__, pdmod->imExec(), parse_img()); 
519       fprintf(stderr, "%s[%d]:  \t\t %s \n", FILE__, __LINE__, parse_img()->name().c_str());
520       fprintf(stderr, "%s[%d]:  \t %s != \n", FILE__, __LINE__, pdmod->imExec()->name().c_str());
521       return NULL;
522    }
523
524    //parsing_printf("findModule for pdmod %s\n",
525    //pdmod->fullName().c_str());
526
527    for (unsigned i = 0; i < everyModule.size(); i++) {
528       if (everyModule[i]->pmod() == pdmod) {
529          //parsing_printf("... found at index %d\n", i);
530          return everyModule[i];
531       }
532    }
533
534    mapped_module *mod = mapped_module::createMappedModule(this,
535          pdmod);
536    if (mod) {
537       //parsing_printf("... created new module\n");
538       everyModule.push_back(mod);
539       return mod;
540    }
541    else
542       return NULL;
543 }
544
545 // fill in "short_name" data member.  Use last component of "name" data
546 // member with FS_FIELD_SEPERATOR ("/") as field seperator....
547 void mapped_object::set_short_name() {
548    const char *name_string = fullName_.c_str();
549    const char *ptr = strrchr(name_string, FS_FIELD_SEPERATOR);
550    if (ptr != NULL) {
551       fileName_ = ptr+1;
552    } else {
553       fileName_ = fullName_;
554    }
555 }
556
557 const pdvector<int_function *> *mapped_object::findFuncVectorByPretty(const std::string &funcname)
558 {
559    if (funcname.c_str() == 0) return NULL;
560    // First, check the underlying image.
561    const pdvector<image_func *> *img_funcs = parse_img()->findFuncVectorByPretty(funcname);
562    if (img_funcs == NULL) {
563       return NULL;
564    }
565
566    assert(img_funcs->size());
567    // Fast path:
568    if (allFunctionsByPrettyName.defines(funcname)) {
569       // Okay, we've pulled in some of the functions before (this can happen as a
570       // side effect of adding functions). But did we get them all?
571        pdvector<int_function *> *map_funcs = allFunctionsByPrettyName[funcname];
572        if (map_funcs->size() == img_funcs->size()) {
573            // We're allocating at the lower level....
574            delete img_funcs;
575            return map_funcs;
576        }
577    }
578    
579    // Slow path: check each img_func, add those we don't already have, and return.
580    for (unsigned i = 0; i < img_funcs->size(); i++) {
581        image_func *func = (*img_funcs)[i];
582        if (!everyUniqueFunction.defines(func)) {
583            findFunction(func);
584        }
585        assert(everyUniqueFunction[func]);
586    }
587    delete img_funcs;
588    return allFunctionsByPrettyName[funcname];
589
590
591 const pdvector <int_function *> *mapped_object::findFuncVectorByMangled(const std::string &funcname)
592 {
593     if (funcname.c_str() == 0) return NULL;
594     
595     // First, check the underlying image.
596     const pdvector<image_func *> *img_funcs = parse_img()->findFuncVectorByMangled(funcname);
597     if (img_funcs == NULL) return NULL;
598
599     assert(img_funcs->size());
600     // Fast path:
601     if (allFunctionsByMangledName.defines(funcname)) {
602         // Okay, we've pulled in some of the functions before (this can happen as a
603         // side effect of adding functions). But did we get them all?
604         pdvector<int_function *> *map_funcs = allFunctionsByMangledName[funcname];
605         if (map_funcs->size() == img_funcs->size())
606             // We're allocating at the lower level...
607             delete img_funcs;
608             return map_funcs;
609     }
610     
611     // Slow path: check each img_func, add those we don't already have, and return.
612     for (unsigned i = 0; i < img_funcs->size(); i++) {
613         image_func *func = (*img_funcs)[i];
614         if (!everyUniqueFunction.defines(func)) {
615             findFunction(func);
616         }
617         assert(everyUniqueFunction[func]);
618     }
619     delete img_funcs;
620     return allFunctionsByMangledName[funcname];
621
622
623
624 const pdvector<int_variable *> *mapped_object::findVarVectorByPretty(const std::string &varname)
625 {
626     if (varname.c_str() == 0) return NULL;
627     
628     // First, check the underlying image.
629     const pdvector<image_variable *> *img_vars = parse_img()->findVarVectorByPretty(varname);
630     if (img_vars == NULL) return NULL;
631     
632     assert(img_vars->size());
633     // Fast path:
634     if (allVarsByPrettyName.defines(varname)) {
635         // Okay, we've pulled in some of the variabletions before (this can happen as a
636         // side effect of adding variabletions). But did we get them all?
637         pdvector<int_variable *> *map_variables = allVarsByPrettyName[varname];
638         if (map_variables->size() == img_vars->size()) {
639             delete img_vars;
640             return map_variables;
641         }
642     }
643     
644     // Slow path: check each img_variable, add those we don't already have, and return.
645     for (unsigned i = 0; i < img_vars->size(); i++) {
646         image_variable *var = (*img_vars)[i];
647         if (!everyUniqueVariable.defines(var)) {
648             findVariable(var);
649         }
650         assert(everyUniqueVariable[var]);
651     }
652     delete img_vars;
653     return allVarsByPrettyName[varname];
654
655
656 const pdvector <int_variable *> *mapped_object::findVarVectorByMangled(const std::string &varname)
657 {
658   if (varname.c_str() == 0) return NULL;
659
660   // First, check the underlying image.
661   const pdvector<image_variable *> *img_vars = parse_img()->findVarVectorByMangled(varname);
662   if (img_vars == NULL) return NULL;
663
664   assert(img_vars->size());
665   // Fast path:
666   if (allVarsByMangledName.defines(varname)) {
667       // Okay, we've pulled in some of the variabletions before (this can happen as a
668       // side effect of adding variabletions). But did we get them all?
669       pdvector<int_variable *> *map_variables = allVarsByMangledName[varname];
670       if (map_variables->size() == img_vars->size()) {
671           delete img_vars;
672           return map_variables;
673       }
674   }
675
676   // Slow path: check each img_variable, add those we don't already have, and return.
677   for (unsigned i = 0; i < img_vars->size(); i++) {
678       image_variable *var = (*img_vars)[i];
679       if (!everyUniqueVariable.defines(var)) {
680           findVariable(var);
681       }
682       assert(everyUniqueVariable[var]);
683   }
684   delete img_vars;
685   return allVarsByMangledName[varname];
686
687
688 //Returns one variable, doesn't search other mapped_objects.  Use carefully.
689 const int_variable *mapped_object::getVariable(const std::string &varname) {
690     const pdvector<int_variable *> *vars = NULL; 
691     vars = findVarVectorByPretty(varname);
692     if (!vars) vars = findVarVectorByMangled(varname);
693     if (vars) {
694         assert(vars->size() > 0);
695         return (*vars)[0];
696     }
697     return NULL;
698 }
699
700 codeRange *mapped_object::findCodeRangeByAddress(const Address &addr)  {
701     // Quick bounds check...
702     if (addr < codeAbs()) { 
703         return NULL; 
704     }
705     if (addr >= (codeAbs() + imageSize())) {
706         return NULL;
707     }
708
709     codeRange *range = NULL;
710     if (codeRangesByAddr_.find(addr, range)) {
711         return range;
712     }
713     // reset range, which may have been modified
714     // by codeRange::find
715     range = NULL;
716
717     // Duck into the image class to see if anything matches
718     set<ParseAPI::Function*> stab;
719     parse_img()->findFuncs(addr - codeBase(),stab);
720     if(!stab.empty()) {
721         // FIXME what if there are multiple functions at this point?
722         image_func * img_func = (image_func*)*stab.begin();
723         int_function *func = findFunction(img_func);
724         assert(func);
725         func->blocks(); // Adds to codeRangesByAddr_...
726         // And repeat...
727         bool res = codeRangesByAddr_.find(addr, range);
728         if (!res) {
729             // Possible: we do a basic-block level search at this point, and a gap (or non-symtab parsing)
730             // may skip an address.
731             return NULL;
732         }
733     }
734     
735     return range;
736 }
737
738 int_function *mapped_object::findFuncByAddr(const Address &addr) {
739     codeRange *range = findCodeRangeByAddress(addr);
740     if (!range) return NULL;
741     return range->is_function();
742 }
743
744 const pdvector<mapped_module *> &mapped_object::getModules() {
745     // everyModule may be out of date...
746     std::vector<pdmodule *> pdmods;
747     parse_img()->getModules(pdmods);
748     if (everyModule.size() == pdmods.size())
749         return everyModule;
750     for (unsigned i = 0; i < pdmods.size(); i++) {
751         findModule(pdmods[i]);
752     }
753     
754     return everyModule;
755 }
756
757 bool mapped_object::getAllFunctions(pdvector<int_function *> &funcs) {
758     unsigned start = funcs.size();
759
760     CodeObject::funclist &img_funcs = parse_img()->getAllFunctions();
761     CodeObject::funclist::iterator fit = img_funcs.begin();
762     for( ; fit != img_funcs.end(); ++fit) {
763         if(!everyUniqueFunction.defines((image_func*)*fit)) {
764             findFunction((image_func*)*fit);
765         }
766         funcs.push_back(everyUniqueFunction[(image_func*)*fit]);
767     }
768     return funcs.size() > start;
769 }
770
771 bool mapped_object::getAllVariables(pdvector<int_variable *> &vars) {
772     unsigned start = vars.size();
773
774     const pdvector<image_variable *> &img_vars = parse_img()->getAllVariables();
775     
776     for (unsigned i = 0; i < img_vars.size(); i++) {
777         if (!everyUniqueVariable.defines(img_vars[i])) {
778             findVariable(img_vars[i]);
779         }
780         vars.push_back(everyUniqueVariable[img_vars[i]]);
781     }
782     return vars.size() > start;
783 }
784
785 // Enter a function in all the appropriate tables
786 int_function *mapped_object::findFunction(image_func *img_func) {
787     if (!img_func) {
788         fprintf(stderr, "Warning: findFunction with null img_func\n");
789         return NULL;
790     }
791     assert(img_func->getSymtabFunction());
792
793     mapped_module *mod = findModule(img_func->pdmod());
794     if (!mod) {
795         fprintf(stderr, "%s[%d]: ERROR: cannot find module %p\n", FILE__, __LINE__, img_func->pdmod());
796         fprintf(stderr, "%s[%d]:  ERROR:  Cannot find module %s\n", FILE__, __LINE__, img_func->pdmod()->fileName().c_str());
797     }
798     assert(mod);
799     
800
801     if (everyUniqueFunction.defines(img_func)) {
802         return everyUniqueFunction[img_func];
803     }
804
805     int_function *func = new int_function(img_func, 
806                                           codeBase_,
807                                           mod);
808     addFunction(func);
809     return func;
810 }
811
812 void mapped_object::addFunctionName(int_function *func,
813                                     const std::string newName,
814                                     nameType_t nameType) {
815     // DEBUG
816     pdvector<int_function *> *funcsByName = NULL;
817     
818     if (nameType & mangledName) {
819         if (!allFunctionsByMangledName.find(newName,
820                                             funcsByName)) {
821             funcsByName = new pdvector<int_function *>;
822             allFunctionsByMangledName[newName] = funcsByName;
823         }
824     }
825     if (nameType & prettyName) {
826         if (!allFunctionsByPrettyName.find(newName,
827                                            funcsByName)) {
828             funcsByName = new pdvector<int_function *>;
829             allFunctionsByPrettyName[newName] = funcsByName;
830         }
831     }
832     if (nameType & typedName) {
833         return; 
834         /*
835           // TODO add?
836         if (!allFunctionsByPrettyName.find(newName,
837                                            funcsByName)) {
838             funcsByName = new pdvector<int_function *>;
839             allFunctionsByPrettyName[newName] = funcsByName;
840         }
841         */
842     }
843
844     assert(funcsByName != NULL);
845     funcsByName->push_back(func);
846 }
847     
848
849 void mapped_object::addFunction(int_function *func) {
850     /*
851     fprintf(stderr, "Adding function %s/%p: %d mangled, %d pretty, %d typed names\n",
852             func->symTabName().c_str(),
853             func,
854             func->symTabNameVector().size(),
855             func->prettyNameVector().size(),
856             func->typedNameVector().size());
857     */
858
859     // Possibly multiple demangled (pretty) names...
860     // And multiple functions (different addr) with the same pretty
861     // name. So we have a many::many mapping...
862     for (unsigned pretty_iter = 0; 
863          pretty_iter < func->prettyNameVector().size();
864          pretty_iter++) {
865         string pretty_name = func->prettyNameVector()[pretty_iter];
866         addFunctionName(func, pretty_name.c_str(), prettyName);
867     }
868
869     for (unsigned typed_iter = 0; 
870          typed_iter < func->typedNameVector().size();
871          typed_iter++) {
872         string typed_name = func->typedNameVector()[typed_iter];
873         addFunctionName(func, typed_name.c_str(), typedName);
874     }
875     
876     // And multiple symtab names...
877     for (unsigned symtab_iter = 0; 
878          symtab_iter < func->symTabNameVector().size();
879          symtab_iter++) {
880         string symtab_name = func->symTabNameVector()[symtab_iter];
881         addFunctionName(func, symtab_name.c_str(), mangledName);
882     }  
883     everyUniqueFunction[func->ifunc()] = func;
884     func->mod()->addFunction(func);
885 }  
886
887 // Enter a function in all the appropriate tables
888 int_variable *mapped_object::findVariable(image_variable *img_var) {
889     if (!img_var) return NULL;
890     
891     if (everyUniqueVariable.defines(img_var))
892         return everyUniqueVariable[img_var];
893     
894     mapped_module *mod = findModule(img_var->pdmod());
895     assert(mod);
896
897     int_variable *var = new int_variable(img_var, dataBase_, mod);
898     addVariable(var);
899     return var;
900 }
901
902 void mapped_object::addVariable(int_variable *var) { 
903     
904     // Possibly multiple demangled (pretty) names...
905     // And multiple functions (different addr) with the same pretty
906     // name. So we have a many::many mapping...
907     for (unsigned pretty_iter = 0; 
908          pretty_iter < var->prettyNameVector().size();
909          pretty_iter++) {
910         string pretty_name = var->prettyNameVector()[pretty_iter];
911         pdvector<int_variable *> *varsByPrettyEntry = NULL;
912         
913         // Ensure a vector exists
914         if (!allVarsByPrettyName.find(pretty_name.c_str(),  
915                                       varsByPrettyEntry)) {
916             varsByPrettyEntry = new pdvector<int_variable *>;
917             allVarsByPrettyName[pretty_name.c_str()] = varsByPrettyEntry;
918         }
919         
920         (*varsByPrettyEntry).push_back(var);
921     }
922     
923     // And multiple symtab names...
924     for (unsigned symtab_iter = 0; 
925          symtab_iter < var->symTabNameVector().size();
926          symtab_iter++) {
927         string symtab_name = var->symTabNameVector()[symtab_iter];
928         pdvector<int_variable *> *varsBySymTabEntry = NULL;
929         
930         // Ensure a vector exists
931         if (!allVarsByMangledName.find(symtab_name.c_str(),  
932                                        varsBySymTabEntry)) {
933             varsBySymTabEntry = new pdvector<int_variable *>;
934             allVarsByMangledName[symtab_name.c_str()] = varsBySymTabEntry;
935         }
936         
937         (*varsBySymTabEntry).push_back(var);
938     }  
939     
940     everyUniqueVariable[var->ivar()] = var;
941     
942     var->mod()->addVariable(var);
943 }  
944
945 /////////// Dinky functions
946
947 // This way we don't have to cross-include every header file in the
948 // world.
949
950 AddressSpace *mapped_object::proc() const { return proc_; }
951
952 bool mapped_object::isSharedLib() const 
953 {
954     return parse_img()->isSharedObj();
955     // HELL NO
956     //return desc_.isSharedObject();
957 }
958
959 bool mapped_object::isStaticExec() const
960 {
961     return parse_img()->getObject()->isStaticBinary();
962 }
963
964 const std::string mapped_object::debugString() const 
965 {
966     std::string debug;
967     debug = std::string(fileName_.c_str()) + ":" 
968        + utos(codeBase_) 
969        + "/" + utos(imageSize()); 
970     return debug;
971 }
972
973 // This gets called once per image. Poke through to the internals;
974 // all we care about, amusingly, is symbol table information. 
975
976 void mapped_object::getInferiorHeaps(vector<pair<string, Address> > &foundHeaps)
977 {
978     vector<pair<string, Address> > code_heaps;
979     vector<pair<string, Address> > data_heaps;
980
981     if (!parse_img()->getInferiorHeaps(code_heaps, data_heaps)) {
982 #if !defined(os_aix)
983         // AIX: see auxiliary lookup, below.
984         return;
985 #endif
986     }
987
988
989     // We have a bunch of offsets, now add in the base addresses
990     for (unsigned i = 0; i < code_heaps.size(); i++) {
991         foundHeaps.push_back(pair<string,Address>(code_heaps[i].first,
992                                                   code_heaps[i].second + codeBase()));
993     }
994     for (unsigned i = 0; i < data_heaps.size(); i++) {
995         foundHeaps.push_back(pair<string,Address>(data_heaps[i].first,
996                                                   data_heaps[i].second + dataBase()));
997     }
998     
999     // AIX: we scavenge space. Do that here.
1000     
1001 #if defined(os_aix)
1002     // ...
1003     
1004     // a.out: from the end of the loader to 0x20000000
1005     // Anything in 0x2....: skip
1006     // Anything in 0xd....: to the next page
1007     
1008     Address start = 0;
1009     unsigned size = 0;
1010     
1011 #if 0
1012     fprintf(stderr, "Looking for inferior heap in %s/%s, codeAbs 0x%x (0x%x/0x%x)\n",
1013             getFileDesc().file().c_str(),
1014             getFileDesc().member().c_str(),
1015             codeAbs(),
1016             codeBase(),
1017             codeOffset());
1018 #endif
1019     
1020     if (codeAbs() >= 0xd0000000) {
1021         // This caused problems on sp3-01.cs.wisc.edu; apparently we were overwriting
1022         // necessary library information. For now I'm disabling it (10FEB06) until
1023         // we can get a better idea of what was going on.
1024 #if 0
1025         start = codeAbs() + imageSize();
1026         start += instruction::size() - (start % (Address)instruction::size());
1027         size = PAGESIZE - (start % PAGESIZE);
1028 #endif
1029     }
1030     else if (codeAbs() > 0x20000000) {
1031         // ...
1032     }
1033     else if (codeAbs() > 0x10000000) {
1034         // We also have the loader; there is no information on where
1035         // it goes (ARGH) so we pad the end of the code segment to
1036         // try and avoid it.
1037         
1038         SymtabAPI::Region *sec;
1039         image_->getObject()->findRegion(sec, ".loader");
1040         Address loader_end = codeAbs() + 
1041             //sec.getSecAddr() +
1042             image_->getObject()->getLoadOffset() +
1043             sec->getDiskSize();
1044         //Address loader_end = codeAbs() + 
1045         //    image_->getObject()->loader_off() +
1046         //    image_->getObject()->loader_len();
1047         // If we loaded it up in the data segment, don't use...
1048         if (loader_end > 0x20000000)
1049             loader_end = 0;
1050         Address code_end = codeAbs() + imageSize();
1051         
1052         start = (loader_end > code_end) ? loader_end : code_end;
1053         
1054         start += instruction::size() - (start % (Address)instruction::size());
1055         size = (0x20000000 - start);
1056     }
1057     
1058     
1059     if (start) {
1060         char name_scratch[1024];
1061         snprintf(name_scratch, 1023,
1062                  "DYNINSTstaticHeap_%i_uncopiedHeap_0x%lx_scratchpage_%s",
1063                  (unsigned) size,
1064                  start,
1065                  fileName().c_str());
1066
1067         foundHeaps.push_back(pair<string,Address>(string(name_scratch),start)); 
1068     }
1069 #endif
1070 }
1071     
1072
1073 void *mapped_object::getPtrToInstruction(Address addr) const 
1074 {
1075    if (addr < codeAbs()) {
1076        return NULL;
1077    }
1078    if (addr >= (codeAbs() + imageSize())) {
1079        return NULL;
1080    }
1081
1082    // Only subtract off the codeBase, not the codeBase plus
1083    // codeOffset -- the image class includes the codeOffset.
1084    Address offset = addr - codeBase();
1085    return image_->codeObject()->cs()->getPtrToInstruction(offset);
1086 }
1087
1088 void *mapped_object::getPtrToData(Address addr) const 
1089 {
1090    assert(addr >= dataAbs());
1091    assert(addr < (dataAbs() + dataSize()));
1092
1093    // Don't go from the code base... the image adds back in the code
1094    // offset.
1095    Address offset = addr - dataBase();
1096    return image_->codeObject()->cs()->getPtrToData(offset);
1097 }
1098
1099 // mapped objects may contain multiple Symtab::Regions, this function
1100 // should not be used, but must be included in the class because this
1101 // function is a subclass of codeRange
1102 void *mapped_object::get_local_ptr() const 
1103 {
1104     assert(0);// if you crash here, blame me. -kevin
1105     return NULL; 
1106     //   return image_->getObject()->image_ptr();
1107 }
1108
1109
1110 bool mapped_object::getSymbolInfo(const std::string &n, int_symbol &info) 
1111 {
1112     using SymtabAPI::Symbol;
1113
1114     assert(image_);
1115
1116     Symbol *lowlevel_sym = image_->symbol_info(n);
1117     if (!lowlevel_sym) {
1118         lowlevel_sym = image_->symbol_info(std::string("_") + n);
1119     }
1120     
1121     if (!lowlevel_sym) return false;
1122     
1123     if (lowlevel_sym->getType() == Symbol::ST_OBJECT)
1124         info = int_symbol(lowlevel_sym, dataBase_);
1125     else
1126         info = int_symbol(lowlevel_sym, codeBase_);
1127     
1128     return true;
1129 }
1130
1131 mapped_module *mapped_object::getOrCreateForkedModule(mapped_module *parMod) 
1132 {
1133    // Okay. We're forking, and this is the child mapped_object.
1134    // And now, given a parent module, we need to find the right one
1135    // in our little baby modules.
1136
1137    // Since we've already copied modules, we can just do a name lookup.
1138    mapped_module *childModule = findModule(parMod->fileName(), false);
1139    assert(childModule);
1140    return childModule;
1141
1142 }
1143
1144 mapped_module* mapped_object::getDefaultModule()
1145 {
1146   mapped_module* ret = findModule("DEFAULT_MODULE");
1147   if(ret) return ret;
1148
1149   // Make sure the everyModule vector is initialized
1150   getModules();
1151   
1152   assert(everyModule.size() > 0);
1153   return everyModule[0];
1154   
1155 }
1156
1157
1158 // splits int-layer blocks in response to block-splitting at the image-layer,
1159 // adds the split image-layer blocks that are newly created, 
1160 // and adjusts point->block pointers accordingly 
1161 bool mapped_object::splitIntLayer()
1162 {
1163
1164 #if ! defined (cap_instruction_api)
1165     // not implemented (or needed, for now) on non-instruction API platforms
1166     return false;
1167 #else
1168
1169     using namespace InstructionAPI;
1170     // iterates through the blocks that were created during block splitting
1171     std::set< image_basicBlock* > splits = parse_img()->getSplitBlocks();
1172     set<image_basicBlock*>::iterator bIter;
1173     std::set<image_func*> splitfuncs;
1174     for (bIter = splits.begin(); bIter != splits.end(); bIter++) 
1175     {
1176         // foreach function corresponding to the block
1177         image_basicBlock *imgBlock = (*bIter);
1178
1179         vector<Function *> funcs;
1180         imgBlock->getFuncs(funcs);
1181         for (std::vector<Function*>::iterator fIter = funcs.begin();
1182              fIter != funcs.end(); 
1183              fIter++) 
1184         {
1185             image_func *imgFunc = dynamic_cast<image_func*>(*fIter);
1186             splitfuncs.insert(imgFunc);
1187             int_function   * intFunc  = findFunction(imgFunc);
1188             int_basicBlock * intBlock = intFunc->findBlockByOffset
1189                 ( imgBlock->firstInsnOffset() - imgFunc->getOffset() );
1190
1191             // add block to new int_function if necessary
1192             if (!intBlock || intBlock->llb() != imgBlock) {
1193                 // this will adjust the previous block's length if necessary
1194                 intFunc->addMissingBlock(*imgBlock);
1195             }
1196
1197             //warning: intBlock might still be null if we deemed this
1198             // function uninstrumentable (probably because it is very
1199             // short), keep that in mind
1200             if (intBlock) {
1201
1202                 // make point fixes
1203                 instPoint *point = NULL;
1204                 Address current = intBlock->origInstance()->firstInsnAddr();
1205                 InstructionDecoder dec
1206                     (getPtrToInstruction(current),
1207                      intBlock->origInstance()->get_size(),
1208                      proc()->getArch());
1209                 Instruction::Ptr insn;
1210                 while(insn = dec.decode()) 
1211                 {
1212                     point = intFunc->findInstPByAddr( current );
1213                     if ( point && point->block() != intBlock ) {
1214                         point->setBlock( intBlock );
1215                     } 
1216                     current += insn->size();
1217                 }
1218                 // we're at the last instruction, create a point if needed
1219                 if ( !point ) {
1220                     if ( parse_img()->getInstPoint
1221                          (intBlock->origInstance()->lastInsnAddr()) ) 
1222                     {
1223                         intFunc->addMissingPoints();
1224                         point = intFunc->findInstPByAddr
1225                             ( intBlock->origInstance()->lastInsnAddr() );
1226                         if (!point) {
1227                             fprintf(stderr,"WARNING: failed to find point for "
1228                                     "block [%lx %lx] at the"
1229                                     " block's lastInsnAddr = %lx %s[%d]\n", 
1230                                     intBlock->origInstance()->firstInsnAddr(), 
1231                                     intBlock->origInstance()->endAddr(),
1232                                     intBlock->origInstance()->lastInsnAddr(),
1233                                     FILE__,__LINE__);
1234                         }
1235                     }
1236                 }
1237             }
1238         }
1239     }
1240
1241     // check arbitrary points in functions whose block boundaries may have changed 
1242     Address baseAddress = parse_img()->desc().loadAddr();
1243     for (std::set<image_func*>::iterator fIter = splitfuncs.begin();
1244             fIter != splitfuncs.end(); 
1245             fIter++) 
1246     {
1247         int_function *f = findFuncByAddr(baseAddress + (*fIter)->getOffset());
1248         pdvector<instPoint*> points = f->funcArbitraryPoints();
1249         for (pdvector<instPoint*>::iterator pIter = points.begin(); 
1250              pIter != points.end(); pIter++) 
1251         {
1252             Address pointAddr = (*pIter)->addr();
1253             bblInstance *bbi = (*pIter)->block()->origInstance();
1254             // fix block boundaries if necessary
1255             while (pointAddr <  bbi->firstInsnAddr()) 
1256             {
1257                 bbi = bbi->block()->func()->findBlockInstanceByAddr(
1258                     bbi->firstInsnAddr() -1 );
1259                 assert(bbi);
1260             } 
1261             while (pointAddr >= bbi->endAddr()) 
1262             {
1263                 bbi = bbi->block()->func()->findBlockInstanceByAddr(
1264                     bbi->endAddr() );
1265                 assert(bbi);
1266             }
1267             if (bbi != (*pIter)->block()->origInstance()) {
1268                 mal_printf("updating block (which was split) for arbitrary"
1269                         " point %lx with %d instances %s[%d]\n",(*pIter)->addr(),
1270                         (int)(*pIter)->instances.size(), FILE__,__LINE__);
1271                 (*pIter)->setBlock(bbi->block());
1272             }
1273         }
1274     }
1275
1276     return true;
1277
1278 #endif
1279 }
1280
1281
1282 void mapped_object::findBBIsByRange(Address startAddr,
1283                                     Address endAddr,
1284                                     std::vector<bblInstance*> &pageBlocks)
1285 {
1286     codeRange *range=NULL;
1287     if ( ! codeRangesByAddr_.find(startAddr,range) &&
1288          ! codeRangesByAddr_.successor(startAddr,range) ) 
1289     {
1290         range = NULL;
1291     }
1292     while (range != NULL && 
1293            range->get_address() < endAddr)
1294     {
1295         bblInstance* bbi = range->is_basicBlockInstance();
1296         assert(bbi);
1297         pageBlocks.push_back(bbi);
1298         // advance to the next region
1299         if ( ! codeRangesByAddr_.successor(
1300                     range->get_address() + range->get_size(), 
1301                     range) ) 
1302         {
1303            range = NULL;
1304         }
1305     }
1306 }
1307
1308 void mapped_object::findFuncsByRange(Address startAddr,
1309                                       Address endAddr,
1310                                       std::set<int_function*> &pageFuncs)
1311 {
1312     codeRange *range=NULL;
1313     if ( ! codeRangesByAddr_.find(startAddr,range) &&
1314          ! codeRangesByAddr_.successor(startAddr,range) ) 
1315     {
1316         range = NULL;
1317     }
1318     while (range != NULL && 
1319            range->get_address() < endAddr)
1320     {
1321         bblInstance* bbi = range->is_basicBlockInstance();
1322         assert(bbi);
1323         pageFuncs.insert(bbi->func());
1324         // advance to the next region
1325         if ( ! codeRangesByAddr_.successor(
1326                     range->get_address() + range->get_size(), 
1327                     range) ) 
1328         {
1329            range = NULL;
1330         }
1331     }
1332 }
1333
1334
1335 /* Re-trigger parsing in the object.  This function should
1336  * only be invoked if all funcEntryAddrs lie within the boundaries of
1337  * the object.  
1338  * 
1339  * Copies over the raw data if a funcEntryAddr lies in between
1340  * the region's disk size and memory size, also copies raw data 
1341  * if the memory around the entry point has changed
1342  * 
1343  * A true return value means that new functions were parsed
1344 */
1345 bool mapped_object::parseNewFunctions(vector<Address> &funcEntryAddrs)
1346 {
1347
1348     bool reparsedObject = false;
1349     Address baseAddress = parse_img()->desc().loadAddr();
1350     SymtabAPI::Region *reg;
1351     std::set<SymtabAPI::Region*> visitedRegions;
1352
1353     if (parse_img()->codeObject()->defensiveMode()) {
1354         clearUpdatedRegions();
1355     }
1356
1357     assert( !parse_img()->hasSplitBlocks() && !parse_img()->hasNewBlocks());
1358
1359     // update regions if necessary, check that functions not parsed already
1360     vector<Address>::iterator curEntry = funcEntryAddrs.begin();
1361     while (curEntry != funcEntryAddrs.end()) {
1362         Address entryOffset = (*curEntry)-baseAddress;
1363         reg = parse_img()->getObject()->findEnclosingRegion(entryOffset);
1364         if (reg != NULL) {
1365
1366             if (parse_img()->codeObject()->defensiveMode() && 
1367                 visitedRegions.end() == visitedRegions.find(reg))
1368             {
1369                 updateMappedFileIfNeeded(*curEntry,reg);
1370                 visitedRegions.insert(reg);
1371             }
1372
1373             if (parse_img()->findFuncByEntry(entryOffset)) {
1374                 fprintf(stderr,"WARNING: tried to parse at %lx, where a "
1375                         "function entry exists already %s[%d]\n",
1376                         *curEntry, FILE__,__LINE__);
1377                 curEntry = funcEntryAddrs.erase(curEntry);
1378             } 
1379             else {
1380                 curEntry++;
1381             }
1382
1383         } 
1384         else {
1385             fprintf(stderr,"ERROR: passed invalid address %lx to "
1386                     "parseNewFunctions %s[%d]\n", *curEntry,FILE__,__LINE__);
1387             assert(0);
1388             curEntry++;
1389         }
1390     }
1391
1392     // parse at funcEntryAddrs
1393     curEntry = funcEntryAddrs.begin();
1394     set<ParseAPI::Function*> tmpfuncs;
1395     while (curEntry != funcEntryAddrs.end()) {
1396         Address entryOffset = (*curEntry)  - baseAddress;
1397         parse_img()->codeObject()->parse( entryOffset, true );
1398         
1399         if ( ! parse_img()->findFuncs(entryOffset, tmpfuncs) ) {
1400             // parse failed, this can happen when the function is just a 
1401             // jump or return instruction, but it doesn't mean that we 
1402             // didn't do any parsing
1403             fprintf(stderr,"WARNING, failed to parse function at %lx, "
1404                     "%s[%d]\n", *curEntry, FILE__, __LINE__);
1405         }
1406         else {
1407             reparsedObject = true;
1408             tmpfuncs.clear();
1409         }
1410         curEntry++;
1411     }
1412
1413
1414
1415     // add the functions we created to mapped_object datastructures
1416     CodeObject::funclist newFuncs = parse_img()->getAllFunctions();
1417     CodeObject::funclist::iterator fit = newFuncs.begin();
1418     for( ; fit != newFuncs.end(); ++fit) {
1419         image_func *curFunc = (image_func*) *fit;
1420         if ( ! everyUniqueFunction.defines(curFunc) ) { 
1421             findFunction(curFunc); // does all the work
1422         }
1423     }
1424
1425     // split int layer
1426     if (parse_img()->hasSplitBlocks()) {
1427         splitIntLayer();
1428         parse_img()->clearSplitBlocks();
1429     }
1430
1431     return reparsedObject;
1432 }
1433
1434
1435 void mapped_object::expandMappedFile(SymtabAPI::Region *reg)
1436 {
1437     assert(reg);
1438     Address baseAddress = parse_img()->desc().loadAddr();
1439     void *mappedPtr = reg->getPtrToRawData();
1440     Address regionStart = baseAddress + reg->getRegionAddr();
1441     codeRange *range=NULL;
1442
1443     void* regBuf = NULL;
1444     Address copySize = reg->getMemSize();
1445
1446     regBuf = malloc(copySize);
1447     if (!proc()->readDataSpace((void*)regionStart, copySize, regBuf, true)) 
1448     {
1449         fprintf(stderr, "%s[%d] Failed to read from region [%lX %lX]\n",
1450                 __FILE__, __LINE__, (long)regionStart, copySize);
1451         assert(0);
1452     }
1453
1454     // find the first code range in the region
1455     if ( ! codeRangesByAddr_.find(regionStart,range) &&
1456             ! codeRangesByAddr_.successor(regionStart,range) ) 
1457     {
1458         range = NULL;
1459     }
1460     while (range != NULL && 
1461             range->get_address() < regionStart + copySize)
1462     {
1463         // copy code ranges from mapped data into regBuf
1464         if ( ! memcpy((void*)((Address)regBuf 
1465                         + range->get_address()
1466                         - regionStart),
1467                         (void*)((Address)mappedPtr
1468                         + range->get_address() 
1469                         - regionStart),
1470                         range->get_size()) )
1471         {
1472             assert(0);
1473         }
1474         // advance to the next region
1475         if ( ! codeRangesByAddr_.successor(
1476                     range->get_address() + range->get_size(), 
1477                     range) ) 
1478         {
1479             range = NULL;
1480         }
1481     }
1482
1483     if (reg->isDirty()) {
1484         // if isDirty is true, the pointer was created via malloc 
1485         // and we can free it.  If not, isDirty is part of a mapped
1486         // file and we can't free it
1487         free( mappedPtr );
1488     }
1489
1490     // KEVINTODO: This sets diskSize = memSize, but that's 
1491     // disgusting, think of a cleaner solution than taking over 
1492     // the mapped files, which won't work anyway for 
1493     // VirtualAlloc'd and mmapped regions
1494     reg->setPtrToRawData( regBuf , copySize );
1495 }
1496
1497 // 1. use other update functions to update non-code areas of mapped files, 
1498 //    expanding them if we overwrote into unmapped areas
1499 // 2. copy overwritten regions into the mapped objects
1500 void mapped_object::updateMappedFile( std::map<Address,Address> owRanges )
1501 {
1502 // 1. use other update functions to update non-code areas of mapped files, 
1503 //    expanding them if we overwrote into unmapped areas
1504
1505     using namespace SymtabAPI;
1506     std::set<Region *> updateregions;// so we don't update regions more than once
1507     std::set<Region *> expansionregions;// so we don't update regions more than once
1508     Address baseAddress = parse_img()->desc().loadAddr();
1509     // figure out which regions need expansion and which need updating
1510     std::map<Address,Address>::iterator rIter = owRanges.begin();
1511     for(; rIter != owRanges.end(); rIter++) {
1512         Address lastChangeOffset = (*rIter).second -1 -baseAddress;
1513         Region *curReg = parse_img()->getObject()->findEnclosingRegion
1514                                                     ( lastChangeOffset );
1515         if ( lastChangeOffset - curReg->getRegionAddr() >= curReg->getDiskSize() ) {
1516             expansionregions.insert(curReg);
1517         } else {
1518             updateregions.insert(curReg);
1519         }        
1520         updatedRegions.insert(curReg);
1521     }
1522     // expand and update regions
1523     set<Region*>::iterator regIter;
1524     for (regIter = expansionregions.begin(); 
1525          regIter != expansionregions.end(); regIter++) 
1526     {
1527         updateregions.erase(*regIter);//won't be necessary to update after expansion
1528         expandMappedFile(*regIter);
1529     }
1530     for (regIter = updateregions.begin(); 
1531          regIter != updateregions.end(); regIter++) 
1532     {
1533         updateMappedFile(*regIter);
1534     }
1535
1536 // 2. copy overwritten regions into the mapped objects
1537     for(rIter = owRanges.begin(); rIter != owRanges.end(); rIter++) 
1538     {
1539         Region *reg = parse_img()->getObject()->findEnclosingRegion
1540             ( (*rIter).first - baseAddress );
1541         unsigned char* regPtr = (unsigned char*)reg->getPtrToRawData() 
1542             + (*rIter).first - baseAddress - reg->getRegionAddr();
1543
1544         assert ( proc()->readDataSpace((void*)(*rIter).first, 
1545                                      (*rIter).second - (*rIter).first, 
1546                                      regPtr, 
1547                                      true) );
1548     }
1549 }
1550
1551 // this is a helper function
1552 // 
1553 // update mapped data, if reg=NULL, update mapped data for whole object, otherwise just for the region
1554 //
1555 //    Read non-code memory values into the mapped version
1556 //    (not code regions so we don't get instrumentation in our parse)
1557 void mapped_object::updateMappedFile(SymtabAPI::Region *reg=NULL)
1558 {
1559     using namespace SymtabAPI;
1560     Address baseAddress = parse_img()->desc().loadAddr();
1561
1562     std::vector<Region *> regions;
1563     if ( reg ) {
1564         regions.push_back(reg);
1565     } else {
1566         parse_img()->getObject()->getCodeRegions(regions);
1567     }
1568
1569     codeRange *range=NULL;
1570     for(unsigned rIdx=0; rIdx < regions.size(); rIdx++) {
1571         Region *curReg = regions[rIdx];
1572         void *mappedPtr = curReg->getPtrToRawData();
1573         Address regionStart = baseAddress + curReg->getRegionAddr();
1574
1575         // find the first code range in the region
1576         if ( ! codeRangesByAddr_.find(regionStart,range) &&
1577              ! codeRangesByAddr_.successor(regionStart,range) ) 
1578         {
1579             range = NULL;
1580         }
1581         Address prevEndAddr = regionStart;
1582         while ( range != NULL && 
1583                 range->get_address() < regionStart + curReg->getDiskSize() )
1584         {
1585             // if there's a gap between previous and current range
1586             if (prevEndAddr < range->get_address()) {
1587                 // update the mapped file
1588                 if (!proc()->readDataSpace(
1589                         (void*)(prevEndAddr), 
1590                         range->get_address() - prevEndAddr, 
1591                         (void*)((Address)mappedPtr 
1592                             + prevEndAddr 
1593                             - regionStart), 
1594                         true)) 
1595                 {
1596                     assert(0);//read failed
1597                 }
1598             }
1599             // set prevEndOffset
1600             prevEndAddr = range->get_address() + range->get_size();
1601             // advance to the next region
1602             if ( ! codeRangesByAddr_.successor(prevEndAddr, 
1603                                                range) ) 
1604             {
1605                range = NULL;
1606             }
1607         }
1608         // read in from prevEndAddr to the end of the region
1609                 // (will read in whole region if there are no ranges in the region)
1610         if (prevEndAddr < regionStart + curReg->getDiskSize() &&
1611             !proc()->readDataSpace(
1612                 (void*)prevEndAddr, 
1613                 regionStart + curReg->getDiskSize() - prevEndAddr, 
1614                 (void*)((Address)mappedPtr 
1615                     + prevEndAddr 
1616                     - regionStart), 
1617                 true)) 
1618         {
1619             assert(0);// read failed
1620         }
1621     }
1622 }
1623
1624 // not only checks if update is needed, but update gaps in-between 
1625 // code ranges for the code region that has an entry point into it, if necessary
1626 // Assumes that an expansion is not needed.
1627 // 
1628 // see if entry point has mapped data value or not, 
1629 // case 1: do nothing yet. 
1630 // case 2: see if memory needs to be updated by comparing non-code bytes, 
1631 //    if no change needed, return.
1632 // case 3:
1633 //    Uninitialized code in the region has been written to
1634 // 
1635 // case 1:  isCode(entryAddr) is false:
1636 //    We need to read the 
1637 //    [regStart+diskEnd, regStart+memEnd] from memory and
1638 //    expand the mapped rawData for the region to reach the
1639 //    end of memory.  This can only trigger once per region. 
1640 //    Copy code ranges from original mapped data into the region
1641 //    so that we don't have instrumentation in our parse
1642 // case 2:
1643 //    Read non-code memory values into the mapped version
1644 //    (not code regions so we don't get instrumentation in our parse)
1645 // case 3:
1646 //    Uninitialized code in the region has been written to
1647 bool mapped_object::isUpdateNeeded(Address entryAddr, SymtabAPI::Region* reg)
1648 {
1649     void* regBuf = NULL;
1650     Address baseAddress = parse_img()->desc().loadAddr();
1651     bool updateNeeded = false;
1652     assert( parse_img()->codeObject()->defensiveMode() );
1653
1654     if (!reg) {
1655         reg = parse_img()->getObject()->findEnclosingRegion(entryAddr-baseAddress);
1656         assert ( reg );
1657     }
1658
1659     // see if the underlying bytes have changed
1660
1661     // read until the next basic block or until the end of the region
1662     // to make sure nothing has changed, otherwise we'll want to read 
1663     // the section in again
1664     codeRange *range = NULL;
1665     unsigned COMPARE_BYTES; 
1666     //KEVINTODO: fix this, it's sometimes comparing the content of basic blocks, which is not the intent
1667     if (codeRangesByAddr_.successor(entryAddr,range)) {
1668         COMPARE_BYTES = range->get_address() - entryAddr;
1669     } else {
1670         COMPARE_BYTES = reg->getDiskSize() - 
1671             ((entryAddr - baseAddress) - reg->getRegionAddr());
1672     }
1673     regBuf = malloc(COMPARE_BYTES);
1674     mal_printf("%s[%d] Comparing %lx bytes starting at %lx\n",
1675             FILE__,__LINE__,COMPARE_BYTES,entryAddr);
1676     if (!proc()->readDataSpace((void*)entryAddr, COMPARE_BYTES, regBuf, true)) {
1677         assert(0); 
1678     }
1679     // read until first difference, then see if the difference is to known
1680     // in which case the difference is due to instrumentation, as we would 
1681     // have otherwise detected the overwrite
1682     void *mappedPtr = (void*)
1683                       ((Address)reg->getPtrToRawData() +
1684                         entryAddr - 
1685                         reg->getRegionAddr() -
1686                         baseAddress);
1687     if (0 != memcmp(mappedPtr,regBuf,COMPARE_BYTES) ) {
1688         updateNeeded = true;
1689     }
1690     free(regBuf);
1691     regBuf = NULL;
1692
1693     return updateNeeded;
1694 }
1695
1696 // checks to see if expansion is needed 
1697 bool mapped_object::isExpansionNeeded(Address entryAddr, 
1698                                       SymtabAPI::Region *reg) 
1699 {
1700
1701     assert(reg);
1702
1703     if (reg->getMemSize() <= reg->getDiskSize()) {
1704         return false;
1705     }
1706
1707     Address baseAddress = parse_img()->desc().loadAddr();
1708     if ( ! parse_img()->getObject()->isCode(entryAddr - baseAddress) ) {
1709         return true;
1710     } 
1711
1712     // if there is uninitialized space in the region, 
1713     // see if the first few bytes have been updated
1714     // KEVINTODO: make compareSize the maximum length of an instruction 
1715     // on the current platform
1716     Address compareStart = 
1717         baseAddress + reg->getRegionAddr() + reg->getDiskSize();
1718     unsigned compareSize = 2 * proc()->getAddressWidth(); 
1719     Address uninitSize = reg->getMemSize() - reg->getDiskSize();
1720     if (compareSize > uninitSize) {
1721         compareSize = uninitSize;
1722     }
1723     unsigned char* regBuf = (unsigned char*) malloc(compareSize);
1724     if (!proc()->readDataSpace((void*)compareStart,compareSize,regBuf,true)) {
1725         fprintf(stderr, "%s[%d] Failed to read from region [%lX %lX]\n",
1726                 __FILE__, __LINE__, compareStart, compareStart+compareSize);
1727         assert(0);
1728     }
1729     // compare to zero if the region has not been expanded yet
1730     bool allZeros = true;
1731     for (unsigned idx=0; allZeros && idx < compareSize; idx++) {
1732         if (0 != regBuf[idx]) {
1733             allZeros = false;
1734         }
1735     }
1736     if (allZeros) {
1737         return false;
1738     } else {
1739         return true;
1740     }
1741 }
1742
1743 void mapped_object::updateMappedFileIfNeeded(Address entryAddr,
1744                                              SymtabAPI::Region* reg)
1745 {
1746     // only update if this is an obfuscated object, AND the region has not 
1747     // already been updated
1748     if ( ! parse_img()->codeObject()->defensiveMode() ||
1749          (reg && updatedRegions.end() != updatedRegions.find(reg)))
1750     {
1751         return;
1752     }
1753
1754     bool expandReg = isExpansionNeeded(entryAddr,reg);
1755     if ( ! expandReg &&
1756          ! isUpdateNeeded(entryAddr,reg) ) 
1757     {
1758         return;
1759     }
1760
1761     // only mark the region updated if we update the region, the update 
1762     // checks are not thorough, but region updates are
1763     updatedRegions.insert(reg); 
1764
1765     Address baseAddress = parse_img()->desc().loadAddr();
1766
1767     if (!reg) {
1768         reg = parse_img()->getObject()->findEnclosingRegion(entryAddr-baseAddress);
1769     }
1770
1771     mal_printf("%s[%d] updating region [%lx %lx] for entry point %lx\n", 
1772             FILE__,__LINE__,
1773             reg->getRegionAddr(), 
1774             reg->getRegionAddr()+reg->getDiskSize(),
1775             entryAddr);
1776
1777     if ( expandReg ) {
1778         expandMappedFile(reg);
1779     } 
1780     else {
1781         updateMappedFile(reg);
1782     }
1783 }
1784
1785 void mapped_object::clearUpdatedRegions()
1786
1787     updatedRegions.clear(); 
1788 }
1789
1790 void mapped_object::removeFunction(int_function *func) {
1791     // remove from int_function vectore
1792     everyUniqueFunction.undef(func->ifunc());
1793     // remove pretty names
1794     pdvector<int_function *> *funcsByName = NULL;
1795     for (unsigned pretty_iter = 0; 
1796          pretty_iter < func->prettyNameVector().size();
1797          pretty_iter++) {
1798         allFunctionsByPrettyName.find
1799             (func->prettyNameVector()[pretty_iter], funcsByName);
1800         if (funcsByName) {
1801             for (unsigned fIdx=0; fIdx < funcsByName->size(); fIdx++) {
1802                 if (func == (*funcsByName)[fIdx]) {
1803                     unsigned lastIdx = funcsByName->size() -1;
1804                     if (fIdx != lastIdx) {
1805                         (*funcsByName)[fIdx] = (*funcsByName)[lastIdx];
1806                     }
1807                     funcsByName->pop_back();
1808                     if (funcsByName->size() == 0) {
1809                         allFunctionsByPrettyName.undef
1810                             (func->symTabNameVector()[pretty_iter]);
1811                     }
1812                 }
1813             }
1814         }
1815     }
1816     // remove typed names
1817     for (unsigned typed_iter = 0; 
1818          typed_iter < func->typedNameVector().size();
1819          typed_iter++) {
1820         allFunctionsByPrettyName.find
1821             (func->typedNameVector()[typed_iter], funcsByName);
1822         if (funcsByName) {
1823             for (unsigned fIdx=0; fIdx < funcsByName->size(); fIdx++) {
1824                 if (func == (*funcsByName)[fIdx]) {
1825                     unsigned lastIdx = funcsByName->size() -1;
1826                     if (fIdx != lastIdx) {
1827                         (*funcsByName)[fIdx] = (*funcsByName)[lastIdx];
1828                     }
1829                     funcsByName->pop_back();
1830                     if (funcsByName->size() == 0) {
1831                         allFunctionsByPrettyName.undef
1832                             (func->symTabNameVector()[typed_iter]);
1833                     }
1834                 }
1835             }
1836         }
1837     }
1838     // remove symtab names
1839     for (unsigned symtab_iter = 0; 
1840          symtab_iter < func->symTabNameVector().size();
1841          symtab_iter++) {
1842         allFunctionsByMangledName.find
1843             (func->symTabNameVector()[symtab_iter], funcsByName);
1844         if (funcsByName) {
1845             for (unsigned fIdx=0; fIdx < funcsByName->size(); fIdx++) {
1846                 if (func == (*funcsByName)[fIdx]) {
1847                     unsigned lastIdx = funcsByName->size() -1;
1848                     if (fIdx != lastIdx) {
1849                         (*funcsByName)[fIdx] = (*funcsByName)[lastIdx];
1850                     }
1851                     funcsByName->pop_back();
1852                     if (funcsByName->size() == 0) {
1853                         allFunctionsByMangledName.undef
1854                             (func->symTabNameVector()[symtab_iter]);
1855                     }
1856                 }
1857             }
1858         }
1859     }  
1860 }
1861
1862 // remove an element from range, these are always original bblInstance's
1863 void mapped_object::removeRange(codeRange *range) {
1864     codeRange *foundrange = NULL;
1865     codeRangesByAddr_.find(range->get_address(), foundrange);
1866     if (range == foundrange) {
1867         codeRangesByAddr_.remove(range->get_address());
1868     }
1869 }
1870
1871 bool mapped_object::isSystemLib(const std::string &objname)
1872 {
1873    const char * fname = objname.c_str();
1874    if (strstr(fname, "libdyninstAPI_RT"))
1875       return true;
1876
1877 #if defined(os_solaris)
1878    // Solaris 2.8... we don't grab the initial func always,
1879    // so fix up this code as well...
1880    if (strstr(fname, "libthread"))
1881       return true;
1882 #endif
1883
1884 #if defined(os_linux)
1885    if (strstr(fname, "libc.so"))
1886       return true;
1887    if (strstr(fname, "libpthread"))
1888       return true;
1889 #endif
1890
1891 #if defined(os_windows)
1892    if (strstr(fname, "kernel32.dll"))
1893       return true;
1894    if (strstr(fname, "user32.dll"))
1895       return true;
1896    if (strstr(fname, "ntdll.dll"))
1897       return true;
1898    if (strstr(fname, "msvcrt") && strstr(fname, ".dll"))
1899       return true;
1900 #endif
1901
1902    return false;
1903 }
1904
1905 bool mapped_object::isExploratoryModeOn()
1906 {
1907     return BPatch_exploratoryMode == analysisMode_ ||
1908            BPatch_defensiveMode == analysisMode_;
1909 }
1910
1911 #if !( (defined(os_linux) || defined(os_freebsd)) && \
1912        (defined(arch_x86) || defined(arch_x86_64)) )
1913 int_function *mapped_object::findGlobalConstructorFunc(const std::string &) {
1914     assert(!"Not implemented");
1915     return NULL;
1916 }
1917
1918 int_function *mapped_object::findGlobalDestructorFunc(const std::string &) {
1919     assert(!"Not implemented");
1920     return NULL;
1921 }
1922 #endif