Compile fix after removing deprecated SymtabAPI methods.
[dyninst.git] / dyninstAPI / src / mapped_object.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 // $Id: mapped_object.C,v 1.39 2008/09/03 06:08:44 jaw Exp $
32
33 #include <string>
34 #include <cctype>
35 #include <algorithm>
36
37 #include "dyninstAPI/src/mapped_object.h"
38 #include "dyninstAPI/src/mapped_module.h"
39 #include "dyninstAPI/src/image.h"
40 #include "dyninstAPI/src/function.h"
41 #include "dyninstAPI/h/BPatch_function.h"
42 #include "dyninstAPI/src/debug.h"
43 #include "dyninstAPI/src/addressSpace.h"
44 #include "dyninstAPI/src/dynProcess.h"
45 #include "symtabAPI/h/Symtab.h"
46 #include "InstructionDecoder.h"
47 #include "Parsing.h"
48 #include "instPoint.h"
49 #include "MemoryEmulator/memEmulator.h"
50 #include <boost/tuple/tuple.hpp>
51
52 #include "PatchCFG.h"
53 #include "PCProcess.h"
54
55 using namespace Dyninst;
56 using namespace Dyninst::ParseAPI;
57 using namespace Dyninst::ProcControlAPI;
58 #if defined(os_windows)
59 #define FS_FIELD_SEPERATOR '\\'
60 #else
61 #define FS_FIELD_SEPERATOR '/'
62 #endif
63 // Whee hasher...
64
65 unsigned imgFuncHash(const parse_func * const &func) {
66     return addrHash4((Address) func);
67 }
68 unsigned imgVarHash(const image_variable * const &func)
69 {
70     return addrHash4((Address) func);
71 }
72
73 // triggered when parsing needs to check if the underlying data has changed
74 bool codeBytesUpdateCB(void *objCB, Address targ)
75 {
76     mapped_object *obj = (mapped_object*) objCB;
77     return obj->updateCodeBytesIfNeeded(targ);
78 }
79
80 mapped_object::mapped_object(fileDescriptor fileDesc,
81       image *img,
82       AddressSpace *proc,
83       BPatch_hybridMode mode):
84   DynObject(img->codeObject(), proc, fileDesc.code()),
85   desc_(fileDesc),
86   fullName_(img->getObject()->file()),
87   everyUniqueVariable(imgVarHash),
88   allFunctionsByMangledName(::Dyninst::stringhash),
89   allFunctionsByPrettyName(::Dyninst::stringhash),
90   allVarsByMangledName(::Dyninst::stringhash),
91   allVarsByPrettyName(::Dyninst::stringhash),
92   dirty_(false),
93   dirtyCalled_(false),
94   image_(img),
95   dlopenUsed(false),
96   proc_(proc),
97   analyzed_(false),
98   analysisMode_(mode),
99   pagesUpdated_(true),
100   codeByteUpdates_(0),
101   memEnd_(-1),
102   memoryImg_(false)
103 {
104 // Set occupied range (needs to be ranges)
105    dataBase_ = fileDesc.data();
106
107 #if defined(os_linux)
108    // Handling for non-fPIE
109    if (codeBase_ == image_->imageOffset()) {
110       // Normal, non-PIE executable, so set the codeBase to 0. 
111       codeBase_ = 0;
112       dataBase_ = 0;
113    }
114 #endif
115    
116    startup_printf("[%s:%d] Creating new mapped_object %s/%s\n",
117                   FILE__, __LINE__, fullName_.c_str(), getFileDesc().member().c_str());
118    startup_printf("[%s:%d] \tcodeBase 0x%lx, codeOffset 0x%lx, size %d\n",
119                   FILE__, __LINE__, codeBase_, image_->imageOffset(), image_->imageLength());
120    startup_printf("[%s:%d] \tdataBase 0x%lx, dataOffset 0x%lx, size %d\n",
121                   FILE__, __LINE__, dataBase_, image_->dataOffset(), image_->dataLength());
122    startup_printf("[%s:%d] \tfileDescriptor: code at 0x%lx, data 0x%lx\n",
123                   FILE__, __LINE__, fileDesc.code(), fileDesc.data());
124    startup_printf("[%s:%d] \tCode: 0x%lx to 0x%lx\n",
125                   FILE__, __LINE__, codeAbs(), codeAbs() + imageSize());
126    startup_printf("[%s:%d] \tData: 0x%lx to 0x%lx\n",
127                   FILE__, __LINE__, dataAbs(), dataAbs() + dataSize());
128
129
130    // Sets "fileName_"
131    set_short_name();
132 }
133
134 mapped_object *mapped_object::createMappedObject(Library::const_ptr lib,
135                                                  AddressSpace *p,
136                                                  BPatch_hybridMode analysisMode,
137                                                  bool parseGaps) {
138    fileDescriptor desc(lib->getName(),
139                        lib->getLoadAddress(),
140                        p->usesDataLoadAddress() ? lib->getDataLoadAddress() : lib->getLoadAddress(),
141                        lib->isSharedLib());
142    return createMappedObject(desc, p, analysisMode, parseGaps);
143 }
144    
145
146 mapped_object *mapped_object::createMappedObject(fileDescriptor &desc,
147                                                  AddressSpace *p,
148                                                  BPatch_hybridMode analysisMode,
149                                                  bool parseGaps) {
150    if (!p) return NULL;
151    if ( BPatch_defensiveMode == analysisMode ) {
152        // parsing in the gaps in defensive mode is a bad idea because
153        // we mark all binary regions as possible code-containing areas
154        parseGaps = false;
155    }
156    assert(desc.file() != "");
157    startup_printf("%s[%d]:  about to parseImage\n", FILE__, __LINE__);
158    startup_printf("%s[%d]: name %s, codeBase 0x%lx, dataBase 0x%lx\n",
159                   FILE__, __LINE__, desc.file().c_str(), desc.code(), desc.data());
160    image *img = image::parseImage( desc, analysisMode, parseGaps);
161    if (!img)  {
162       startup_printf("%s[%d]:  failed to parseImage\n", FILE__, __LINE__);
163       return NULL;
164    }
165    if (img->isDyninstRTLib()) {
166        parseGaps = false;
167    }
168 #if defined(os_linux) && defined(arch_x86_64)
169    //Our x86_64 is actually reporting negative load addresses.  Go fig.
170    // On Linux/x86_64 with 32-bit mutatees this causes problems because we
171    // treat the load address as a unsigned 64 bit integer, and things don't
172    // correctly wrap.
173    //
174    // We'll detect this by noticing that the dynamic entry doesn't match up
175    // and then correct.
176    if (desc.dynamic() &&
177        p->getAddressWidth() == 4 &&
178        img->getObject()->getElfDynamicOffset() + desc.code() != desc.dynamic()) {
179       Address new_load_addr;
180       new_load_addr = desc.dynamic() - img->getObject()->getElfDynamicOffset();
181       startup_printf("[%s:%u] - Incorrect binary load address %lx, changing "
182               "to %lx\n", FILE__, __LINE__, (unsigned long) desc.code(),
183               (unsigned long) new_load_addr);
184       desc.setCode(new_load_addr);
185       desc.setData(new_load_addr);
186    }
187 #endif
188    if (!desc.isSharedObject()) {
189       //We've seen a case where the a.out is a shared object (RHEL4's
190       // version of ssh).  Check if the shared object flag is set in the
191       // binary (which is different from the isSharedObject()) call above.
192       // If so, we need to update the load address.
193       if (p->proc() &&
194           (img->getObject()->getObjectType() == SymtabAPI::obj_SharedLib)) {
195          //Executable is a shared lib
196          p->proc()->setAOutLoadAddress(desc);
197       }
198       
199 // Used to search for main here and enable system call tracing to find out 
200 // when libc.so is loaded -- this is unnecessary now that we use ProcControlAPI
201 //
202 // This is now done on-demand when libc is loaded and main has yet to be found
203    }
204
205    // Adds exported functions and variables..
206    startup_printf("%s[%d]:  creating mapped object\n", FILE__, __LINE__);
207    mapped_object *obj = new mapped_object(desc, img, p, analysisMode);
208    if (BPatch_defensiveMode == analysisMode) {
209        img->register_codeBytesUpdateCB(obj);
210    }
211    startup_printf("%s[%d]:  leaving createMappedObject(%s)\n", FILE__, __LINE__, desc.file().c_str());
212
213   return obj;
214 }
215
216 mapped_object::mapped_object(const mapped_object *s, AddressSpace *child) :
217    codeRange(),
218    DynObject(s, child, s->codeBase_),
219    desc_(s->desc_),
220    fullName_(s->fullName_),
221    fileName_(s->fileName_),
222    dataBase_(s->dataBase_),
223    everyUniqueVariable(imgVarHash),
224    allFunctionsByMangledName(::Dyninst::stringhash),
225    allFunctionsByPrettyName(::Dyninst::stringhash),
226    allVarsByMangledName(::Dyninst::stringhash),
227    allVarsByPrettyName(::Dyninst::stringhash),
228    dirty_(s->dirty_),
229    dirtyCalled_(s->dirtyCalled_),
230    image_(s->image_),
231    dlopenUsed(s->dlopenUsed),
232    proc_(child),
233    analyzed_(s->analyzed_),
234    analysisMode_(s->analysisMode_),
235    pagesUpdated_(true),
236    codeByteUpdates_(0),
237    memoryImg_(s->memoryImg_)
238 {
239    // Let's do modules
240    for (unsigned k = 0; k < s->everyModule.size(); k++) {
241       // Doesn't copy things like line info. Ah, well.
242       mapped_module *parMod = s->everyModule[k];
243       mapped_module *mod = mapped_module::createMappedModule(this, parMod->pmod());
244       assert(mod);
245       everyModule.push_back(mod);
246    }
247
248    copyCFG(const_cast<mapped_object*>(s));
249
250    const pdvector<int_variable *> parVars = s->everyUniqueVariable.values();
251    for (unsigned j = 0; j < parVars.size(); j++) {
252       int_variable *parVar = parVars[j];
253       assert(parVar->mod());
254       mapped_module *mod = getOrCreateForkedModule(parVar->mod());
255       int_variable *newVar = new int_variable(parVar,
256             mod);
257       addVariable(newVar);
258    }
259
260    assert(BPatch_defensiveMode != analysisMode_);
261
262    image_ = s->image_->clone();
263 }
264
265
266 mapped_object::~mapped_object()
267 {
268    // desc_ is static
269    // fullName_ is static
270    // fileName_ is static
271    // codeBase_ is static
272    // dataBase_ is static
273
274    for (unsigned i = 0; i < everyModule.size(); i++)
275       delete everyModule[i];
276    everyModule.clear();
277
278    pdvector<int_variable *> vars = everyUniqueVariable.values();
279    for (unsigned k = 0; k < vars.size(); k++) {
280       delete vars[k];
281    }
282    everyUniqueVariable.clear();
283
284    pdvector<pdvector<func_instance *> * > mangledFuncs = allFunctionsByMangledName.values();
285    for (unsigned i = 0; i < mangledFuncs.size(); i++) {
286       delete mangledFuncs[i];
287    }
288    allFunctionsByMangledName.clear();
289
290    pdvector<pdvector<func_instance *> * > prettyFuncs = allFunctionsByPrettyName.values();
291    for (unsigned i = 0; i < prettyFuncs.size(); i++) {
292       delete prettyFuncs[i];
293    }
294    allFunctionsByPrettyName.clear();
295
296    pdvector<pdvector<int_variable *> * > mV = allVarsByMangledName.values();
297    for (unsigned i = 0; i < mV.size(); i++) {
298       delete mV[i];
299    }
300    allVarsByMangledName.clear();
301
302    pdvector<pdvector<int_variable *> * > pV = allVarsByPrettyName.values();
303    for (unsigned i = 0; i < pV.size(); i++) {
304       delete pV[i];
305    }
306    allVarsByPrettyName.clear();
307
308    // codeRangesByAddr_ is static
309     // Remainder are static
310    image::removeImage(image_);
311 }
312
313 Address mapped_object::codeAbs() const {
314   return codeBase_ + imageOffset();
315 }
316
317 Address mapped_object::dataAbs() const {
318   return dataBase_ + dataOffset();
319 }
320
321 bool mapped_object::isCode(Address addr) const {
322    Address offset;
323    offset = addr - codeBase();
324
325    return parse_img()->getObject()->isCode(offset);
326 }
327
328 bool mapped_object::isData(Address addr) const {
329    Address offset;
330    offset = addr - codeBase();
331
332    return parse_img()->getObject()->isData(offset);
333 }
334
335 bool mapped_object::analyze()
336 {
337     if (analyzed_) return true;
338   // Create a process-specific version of the image; all functions and
339   // variables at an absolute address (and modifiable).
340
341   // At some point, we should do better handling of base
342   // addresses. Right now we assume we have one per mapped object; AIX
343   // is a special case with two (one for functions, one for
344   // variables).
345
346   if (!image_) return false;
347
348   image_->analyzeIfNeeded();
349
350   analyzed_ = true;
351
352   // TODO: CLEANUP, shouldn't need this for loop, calling findFunction forces 
353   // PatchAPI to create function objects, destroying lazy function creation
354   // We already have exported ones. Force analysis (if needed) and get
355   // the functions we created via analysis.
356   const CodeObject::funclist & allFuncs = parse_img()->getAllFunctions();
357   CodeObject::funclist::const_iterator fit = allFuncs.begin();
358   for( ; fit != allFuncs.end(); ++fit) {
359   // For each function, we want to add our base address
360       if((*fit)->src() != HINT)
361         findFunction((parse_func*)*fit);
362   }
363
364   // Remember: variables don't.
365   pdvector<image_variable *> unmappedVars = image_->getCreatedVariables();
366   for (unsigned vi = 0; vi < unmappedVars.size(); vi++) {
367       findVariable(unmappedVars[vi]);
368   }
369   return true;
370 }
371
372 // TODO: this should probably not be a mapped_object method, but since
373 // for now it is only used by mapped_objects it is
374 // from a string that is a complete path name to a function in a module
375 // (ie. "/usr/lib/libc.so.1/write") return a string with the function
376 // part removed.  return 0 on error
377 char *mapped_object::getModulePart(std::string &full_path_name) {
378
379     char *whole_name = P_strdup(full_path_name.c_str());
380     char *next=0;
381     char *last=next;
382     if((last = P_strrchr(whole_name, '/'))){
383         next = whole_name;
384         for(u_int i=0;(next!=last)&&(i<full_path_name.length()); i++){
385             next++;
386             if(next == last){
387                 u_int size = i+2;
388                 char *temp_str = new char[size];
389                 if(P_strncpy(temp_str,whole_name,size-1)){
390                     temp_str[size-1] = '\0';
391                     delete whole_name;
392                     return temp_str;
393                     temp_str = 0;
394                 }
395             }
396         }
397     }
398     delete whole_name;
399     return 0;
400 }
401
402 mapped_module *mapped_object::findModule(string m_name, bool wildcard)
403 {
404    parsing_printf("findModule for %s (substr match %d)\n",
405          m_name.c_str(), wildcard);
406    std::string tmp = m_name.c_str();
407    for (unsigned i = 0; i < everyModule.size(); i++) {
408       if (everyModule[i]->fileName() == m_name ||
409             everyModule[i]->fullName() == m_name ||
410             (wildcard &&
411              (wildcardEquiv(tmp, everyModule[i]->fileName()) ||
412               wildcardEquiv(tmp, everyModule[i]->fullName())))) {
413          //parsing_printf("... found!\n");
414          return everyModule[i];
415       }
416    }
417    // Create a new one IF there's one in the child pd_module
418
419    pdmodule *pdmod = image_->findModule(m_name, wildcard);
420    if (pdmod) {
421       mapped_module *mod = mapped_module::createMappedModule(this,
422             pdmod);
423       everyModule.push_back(mod);
424       //parsing_printf("... made new module!\n");
425       return mod;
426    }
427    else {
428       //parsing_printf("... error, no module found...\n");
429       return NULL;
430    }
431 }
432
433
434 mapped_module *mapped_object::findModule(pdmodule *pdmod)
435 {
436    if (!pdmod) {
437       fprintf(stderr, "%s[%d]:  please call this findModule with nonNULL parameter\n", FILE__, __LINE__);
438       return NULL;
439    }
440
441    assert(pdmod);
442
443    if (pdmod->imExec() != parse_img()) {
444       fprintf(stderr, "%s[%d]: WARNING: lookup for module in wrong mapped object! %p != %p\n", FILE__, __LINE__, pdmod->imExec(), parse_img());
445       fprintf(stderr, "%s[%d]:  \t\t %s \n", FILE__, __LINE__, parse_img()->name().c_str());
446       fprintf(stderr, "%s[%d]:  \t %s != \n", FILE__, __LINE__, pdmod->imExec()->name().c_str());
447       return NULL;
448    }
449
450    //parsing_printf("findModule for pdmod %s\n",
451    //pdmod->fullName().c_str());
452
453    for (unsigned i = 0; i < everyModule.size(); i++) {
454       if (everyModule[i]->pmod() == pdmod) {
455          //parsing_printf("... found at index %d\n", i);
456          return everyModule[i];
457       }
458    }
459
460    mapped_module *mod = mapped_module::createMappedModule(this,
461          pdmod);
462    if (mod) {
463       //parsing_printf("... created new module\n");
464       everyModule.push_back(mod);
465       return mod;
466    }
467    else
468       return NULL;
469 }
470
471 // fill in "short_name" data member.  Use last component of "name" data
472 // member with FS_FIELD_SEPERATOR ("/") as field seperator....
473 void mapped_object::set_short_name() {
474    const char *name_string = fullName_.c_str();
475    const char *ptr = strrchr(name_string, FS_FIELD_SEPERATOR);
476    if (ptr != NULL) {
477       fileName_ = ptr+1;
478    } else {
479       fileName_ = fullName_;
480    }
481 }
482
483 const pdvector<func_instance *> *mapped_object::findFuncVectorByPretty(const std::string &funcname)
484 {
485    if (funcname.c_str() == 0) return NULL;
486    // First, check the underlying image.
487    const pdvector<parse_func *> *img_funcs = parse_img()->findFuncVectorByPretty(funcname);
488    if (img_funcs == NULL) {
489       return NULL;
490    }
491
492    assert(img_funcs->size());
493    // Fast path:
494    if (allFunctionsByPrettyName.defines(funcname)) {
495       // Okay, we've pulled in some of the functions before (this can happen as a
496       // side effect of adding functions). But did we get them all?
497        pdvector<func_instance *> *map_funcs = allFunctionsByPrettyName[funcname];
498        if (map_funcs->size() == img_funcs->size()) {
499            // We're allocating at the lower level....
500            delete img_funcs;
501            return map_funcs;
502        }
503    }
504
505    // Slow path: check each img_func, add those we don't already have, and return.
506    for (unsigned i = 0; i < img_funcs->size(); i++) {
507        parse_func *func = (*img_funcs)[i];
508        if (funcs_.find(func) == funcs_.end()) {
509            findFunction(func);
510        }
511        assert(funcs_[func]);
512    }
513    delete img_funcs;
514    return allFunctionsByPrettyName[funcname];
515 }
516
517 const pdvector <func_instance *> *mapped_object::findFuncVectorByMangled(const std::string &funcname)
518 {
519     if (funcname.c_str() == 0) return NULL;
520
521     // First, check the underlying image.
522     const pdvector<parse_func *> *img_funcs = parse_img()->findFuncVectorByMangled(funcname);
523     if (img_funcs == NULL) {
524        return NULL;
525     }
526
527     assert(img_funcs->size());
528     // Fast path:
529     if (allFunctionsByMangledName.defines(funcname)) {
530         // Okay, we've pulled in some of the functions before (this can happen as a
531         // side effect of adding functions). But did we get them all?
532         pdvector<func_instance *> *map_funcs = allFunctionsByMangledName[funcname];
533         if (map_funcs->size() == img_funcs->size()) {
534             // We're allocating at the lower level...
535             delete img_funcs;
536             return map_funcs;
537         }
538     }
539
540     // Slow path: check each img_func, add those we don't already have, and return.
541     for (unsigned i = 0; i < img_funcs->size(); i++) {
542         parse_func *func = (*img_funcs)[i];
543         if (funcs_.find(func) == funcs_.end()) {
544             findFunction(func);
545         }
546         assert(funcs_[func]);
547     }
548     delete img_funcs;
549     return allFunctionsByMangledName[funcname];
550 }
551
552
553 const pdvector<int_variable *> *mapped_object::findVarVectorByPretty(const std::string &varname)
554 {
555     if (varname.c_str() == 0) return NULL;
556
557     // First, check the underlying image.
558     const pdvector<image_variable *> *img_vars = parse_img()->findVarVectorByPretty(varname);
559     if (img_vars == NULL) return NULL;
560
561     assert(img_vars->size());
562     // Fast path:
563     if (allVarsByPrettyName.defines(varname)) {
564         // Okay, we've pulled in some of the variabletions before (this can happen as a
565         // side effect of adding variabletions). But did we get them all?
566         pdvector<int_variable *> *map_variables = allVarsByPrettyName[varname];
567         if (map_variables->size() == img_vars->size()) {
568             delete img_vars;
569             return map_variables;
570         }
571     }
572
573     // Slow path: check each img_variable, add those we don't already have, and return.
574     for (unsigned i = 0; i < img_vars->size(); i++) {
575         image_variable *var = (*img_vars)[i];
576         if (!everyUniqueVariable.defines(var)) {
577             findVariable(var);
578         }
579         assert(everyUniqueVariable[var]);
580     }
581     delete img_vars;
582     return allVarsByPrettyName[varname];
583 }
584
585 const pdvector <int_variable *> *mapped_object::findVarVectorByMangled(const std::string &varname)
586 {
587   if (varname.c_str() == 0) return NULL;
588
589   // First, check the underlying image.
590   const pdvector<image_variable *> *img_vars = parse_img()->findVarVectorByMangled(varname);
591   if (img_vars == NULL) return NULL;
592
593   assert(img_vars->size());
594   // Fast path:
595   if (allVarsByMangledName.defines(varname)) {
596       // Okay, we've pulled in some of the variabletions before (this can happen as a
597       // side effect of adding variabletions). But did we get them all?
598       pdvector<int_variable *> *map_variables = allVarsByMangledName[varname];
599       if (map_variables->size() == img_vars->size()) {
600           delete img_vars;
601           return map_variables;
602       }
603   }
604
605   // Slow path: check each img_variable, add those we don't already have, and return.
606   for (unsigned i = 0; i < img_vars->size(); i++) {
607       image_variable *var = (*img_vars)[i];
608       if (!everyUniqueVariable.defines(var)) {
609           findVariable(var);
610       }
611       assert(everyUniqueVariable[var]);
612   }
613   delete img_vars;
614   return allVarsByMangledName[varname];
615 }
616
617 //Returns one variable, doesn't search other mapped_objects.  Use carefully.
618 const int_variable *mapped_object::getVariable(const std::string &varname) {
619     const pdvector<int_variable *> *vars = NULL;
620     vars = findVarVectorByPretty(varname);
621     if (!vars) vars = findVarVectorByMangled(varname);
622     if (vars) {
623         assert(vars->size() > 0);
624         return (*vars)[0];
625     }
626     return NULL;
627 }
628
629 block_instance *mapped_object::findBlockByEntry(Address addr)
630 {
631     std::set<block_instance *> allBlocks;
632     if (!findBlocksByAddr(addr, allBlocks)) return false;
633     for (std::set<block_instance *>::iterator iter = allBlocks.begin();
634         iter != allBlocks.end(); ++iter)
635     {
636         if ((*iter)->start() == addr)
637         {
638            return *iter;
639         }
640     }
641     return NULL;
642 }
643
644
645 bool mapped_object::findBlocksByAddr(const Address addr, std::set<block_instance *> &blocks)
646 {
647     // Quick bounds check...
648     if (addr < codeAbs()) {
649         return false;
650     }
651     if (addr >= (codeAbs() + imageSize())) {
652         return false;
653     }
654
655     // Duck into the image class to see if anything matches
656     set<ParseAPI::Block *> stab;
657     parse_img()->findBlocksByAddr(addr - codeBase(), stab);
658     if (stab.empty()) return false;
659
660     for (set<ParseAPI::Block *>::iterator llb_iter = stab.begin();
661         llb_iter != stab.end(); ++llb_iter)
662     {
663         // For each block b \in stab
664         //   For each func f \in b.funcs()
665         //     Let i_f = up_map(f)
666         //       add up_map(b, i_f)
667         std::vector<ParseAPI::Function *> ll_funcs;
668         (*llb_iter)->getFuncs(ll_funcs);
669         for (std::vector<ParseAPI::Function *>::iterator llf_iter = ll_funcs.begin();
670             llf_iter != ll_funcs.end(); ++llf_iter) {
671            block_instance *block = findBlock(*llb_iter);
672            assert(block);
673            blocks.insert(block);
674         }
675     }
676     return !blocks.empty();
677 }
678
679 bool mapped_object::findFuncsByAddr(const Address addr, std::set<func_instance *> &funcs)
680 {
681     bool ret = false;
682     // Quick and dirty implementation
683     std::set<block_instance *> blocks;
684     if (!findBlocksByAddr(addr, blocks)) return false;
685     for (std::set<block_instance *>::iterator iter = blocks.begin();
686          iter != blocks.end(); ++iter) {
687        (*iter)->getFuncs(std::inserter(funcs, funcs.end()));
688        ret = true;
689     }
690     return ret;
691 }
692
693 func_instance *mapped_object::findFuncByEntry(const Address addr) {
694    std::set<func_instance *> funcs;
695    if (!findFuncsByAddr(addr, funcs)) return NULL;
696    for (std::set<func_instance *>::iterator iter = funcs.begin();
697         iter != funcs.end(); ++iter) {
698       if ((*iter)->entryBlock()->start() == addr) return *iter;
699    }
700    return NULL;
701 }
702
703
704 const pdvector<mapped_module *> &mapped_object::getModules() {
705     // everyModule may be out of date...
706     std::vector<pdmodule *> pdmods;
707     parse_img()->getModules(pdmods);
708     if (everyModule.size() == pdmods.size())
709         return everyModule;
710     for (unsigned i = 0; i < pdmods.size(); i++) {
711         findModule(pdmods[i]);
712     }
713
714     return everyModule;
715 }
716
717 bool mapped_object::getAllFunctions(pdvector<func_instance *> &funcs) {
718     unsigned start = funcs.size();
719
720     const CodeObject::funclist &img_funcs = parse_img()->getAllFunctions();
721     CodeObject::funclist::const_iterator fit = img_funcs.begin();
722     for( ; fit != img_funcs.end(); ++fit) {
723         if(funcs_.find((parse_func*)*fit) == funcs_.end()) {
724             findFunction((parse_func*)*fit);
725         }
726         funcs.push_back(SCAST_FI(funcs_[*fit]));
727     }
728     return funcs.size() > start;
729 }
730
731 bool mapped_object::getAllVariables(pdvector<int_variable *> &vars) {
732     unsigned start = vars.size();
733
734     const pdvector<image_variable *> &img_vars = parse_img()->getAllVariables();
735
736     for (unsigned i = 0; i < img_vars.size(); i++) {
737         if (!everyUniqueVariable.defines(img_vars[i])) {
738             findVariable(img_vars[i]);
739         }
740         vars.push_back(everyUniqueVariable[img_vars[i]]);
741     }
742     return vars.size() > start;
743 }
744
745 func_instance *mapped_object::findFunction(ParseAPI::Function *papi_func) {
746   return SCAST_FI(getFunc(papi_func));
747 }
748
749 void mapped_object::addFunctionName(func_instance *func,
750                                     const std::string newName,
751                                     nameType_t nameType) {
752     // DEBUG
753     pdvector<func_instance *> *funcsByName = NULL;
754
755     if (nameType & mangledName) {
756         if (!allFunctionsByMangledName.find(newName,
757                                             funcsByName)) {
758             funcsByName = new pdvector<func_instance *>;
759             allFunctionsByMangledName[newName] = funcsByName;
760         }
761     }
762     if (nameType & prettyName) {
763         if (!allFunctionsByPrettyName.find(newName,
764                                            funcsByName)) {
765             funcsByName = new pdvector<func_instance *>;
766             allFunctionsByPrettyName[newName] = funcsByName;
767         }
768     }
769     if (nameType & typedName) {
770         return;
771         /*
772           // TODO add?
773         if (!allFunctionsByPrettyName.find(newName,
774                                            funcsByName)) {
775             funcsByName = new pdvector<func_instance *>;
776             allFunctionsByPrettyName[newName] = funcsByName;
777         }
778         */
779     }
780
781     assert(funcsByName != NULL);
782     funcsByName->push_back(func);
783 }
784
785
786 void mapped_object::addFunction(func_instance *func) {
787     // Possibly multiple demangled (pretty) names...
788     // And multiple functions (different addr) with the same pretty
789     // name. So we have a many::many mapping...
790     for (unsigned pretty_iter = 0;
791          pretty_iter < func->prettyNameVector().size();
792          pretty_iter++) {
793         string pretty_name = func->prettyNameVector()[pretty_iter];
794         addFunctionName(func, pretty_name.c_str(), prettyName);
795     }
796
797     for (unsigned typed_iter = 0;
798          typed_iter < func->typedNameVector().size();
799          typed_iter++) {
800         string typed_name = func->typedNameVector()[typed_iter];
801         addFunctionName(func, typed_name.c_str(), typedName);
802     }
803
804     // And multiple symtab namevs...
805     for (unsigned symtab_iter = 0;
806          symtab_iter < func->symTabNameVector().size();
807          symtab_iter++) {
808         string symtab_name = func->symTabNameVector()[symtab_iter];
809         addFunctionName(func, symtab_name.c_str(), mangledName);
810     }
811
812     func->mod()->addFunction(func);
813 }
814
815 // Enter a function in all the appropriate tables
816 int_variable *mapped_object::findVariable(image_variable *img_var) {
817     if (!img_var) return NULL;
818
819     if (everyUniqueVariable.defines(img_var))
820         return everyUniqueVariable[img_var];
821
822     mapped_module *mod = findModule(img_var->pdmod());
823     assert(mod);
824
825     int_variable *var = new int_variable(img_var, dataBase_, mod);
826     addVariable(var);
827     return var;
828 }
829
830 void mapped_object::addVariable(int_variable *var) {
831
832     // Possibly multiple demangled (pretty) names...
833     // And multiple functions (different addr) with the same pretty
834     // name. So we have a many::many mapping...
835     for (unsigned pretty_iter = 0;
836          pretty_iter < var->prettyNameVector().size();
837          pretty_iter++) {
838         string pretty_name = var->prettyNameVector()[pretty_iter];
839         pdvector<int_variable *> *varsByPrettyEntry = NULL;
840
841         // Ensure a vector exists
842         if (!allVarsByPrettyName.find(pretty_name.c_str(),
843                                       varsByPrettyEntry)) {
844             varsByPrettyEntry = new pdvector<int_variable *>;
845             allVarsByPrettyName[pretty_name.c_str()] = varsByPrettyEntry;
846         }
847
848         (*varsByPrettyEntry).push_back(var);
849     }
850
851     // And multiple symtab names...
852     for (unsigned symtab_iter = 0;
853          symtab_iter < var->symTabNameVector().size();
854          symtab_iter++) {
855         string symtab_name = var->symTabNameVector()[symtab_iter];
856         pdvector<int_variable *> *varsBySymTabEntry = NULL;
857
858         // Ensure a vector exists
859         if (!allVarsByMangledName.find(symtab_name.c_str(),
860                                        varsBySymTabEntry)) {
861             varsBySymTabEntry = new pdvector<int_variable *>;
862             allVarsByMangledName[symtab_name.c_str()] = varsBySymTabEntry;
863         }
864
865         (*varsBySymTabEntry).push_back(var);
866     }
867
868     everyUniqueVariable[var->ivar()] = var;
869
870     var->mod()->addVariable(var);
871 }
872
873 /////////// Dinky functions
874
875 // This way we don't have to cross-include every header file in the
876 // world.
877
878 AddressSpace *mapped_object::proc() const { return proc_; }
879
880 bool mapped_object::isSharedLib() const
881 {
882     if (isMemoryImg()) return false;
883
884     return parse_img()->isSharedObj();
885     // HELL NO
886     //return desc_.isSharedObject();
887 }
888
889 bool mapped_object::isStaticExec() const
890 {
891     return parse_img()->getObject()->isStaticBinary();
892 }
893
894 const std::string mapped_object::debugString() const
895 {
896     std::string debug;
897     debug = std::string(fileName_.c_str()) + ":"
898        + utos(codeBase_)
899        + "/" + utos(imageSize());
900     return debug;
901 }
902
903 // Search an object for heapage
904 bool mapped_object::getInfHeapList(pdvector<heapDescriptor> &infHeaps) {
905     vector<pair<string,Address> > foundHeaps;
906
907     getInferiorHeaps(foundHeaps);
908
909     for (u_int j = 0; j < foundHeaps.size(); j++) {
910         // The string layout is: DYNINSTstaticHeap_size_type_unique
911         // Can't allocate a variable-size array on NT, so malloc
912         // that sucker
913         char *temp_str = (char *)malloc(strlen(foundHeaps[j].first.c_str())+1);
914         strcpy(temp_str, foundHeaps[j].first.c_str());
915         char *garbage_str = strtok(temp_str, "_"); // Don't care about beginning
916         assert(!strcmp("DYNINSTstaticHeap", garbage_str));
917         // Name is as is.
918         // If address is zero, then skip (error condition)
919         if (foundHeaps[j].second == 0) {
920             cerr << "Skipping heap " << foundHeaps[j].first.c_str()
921                  << "with address 0" << endl;
922             continue;
923         }
924         // Size needs to be parsed out (second item)
925         // Just to make life difficult, the heap can have an optional
926         // trailing letter (k,K,m,M,g,G) which indicates that it's in
927         // kilobytes, megabytes, or gigabytes. Why gigs? I was bored.
928         char *heap_size_str = strtok(NULL, "_"); // Second element, null-terminated
929         unsigned heap_size = (unsigned) atol(heap_size_str);
930         if (heap_size == 0)
931             /* Zero size or error, either way this makes no sense for a heap */
932         {
933             free(temp_str);
934             continue;
935         }
936         switch (heap_size_str[strlen(heap_size_str)-1]) {
937         case 'g':
938         case 'G':
939             heap_size *= 1024;
940         case 'm':
941         case 'M':
942             heap_size *= 1024;
943         case 'k':
944         case 'K':
945             heap_size *= 1024;
946         default:
947             break;
948         }
949
950         // Type needs to be parsed out. Can someone clean this up?
951         inferiorHeapType heap_type;
952         char *heap_type_str = strtok(NULL, "_");
953
954         if (!strcmp(heap_type_str, "anyHeap"))
955             heap_type = anyHeap;
956         else if (!strcmp(heap_type_str, "lowmemHeap"))
957             heap_type = lowmemHeap;
958         else if (!strcmp(heap_type_str, "dataHeap"))
959             heap_type = dataHeap;
960         else if (!strcmp(heap_type_str, "textHeap"))
961             heap_type = textHeap;
962         else if (!strcmp(heap_type_str, "uncopiedHeap"))
963             heap_type = uncopiedHeap;
964         else {
965             cerr << "Unknown heap string " << heap_type_str << " read from file!" << endl;
966             free(temp_str);
967             continue;
968         }
969         infHeaps.push_back(heapDescriptor(foundHeaps[j].first.c_str(),
970                                           foundHeaps[j].second,
971                                           heap_size, heap_type));
972         free(temp_str);
973     }
974     return foundHeaps.size() > 0;
975 }
976
977 unsigned mapped_object::memoryEnd() 
978
979     if ((long)memEnd_ != -1) {
980         return memEnd_;
981     }
982     memEnd_ = 0;
983     vector<SymtabAPI::Region*> regs;
984     parse_img()->getObject()->getMappedRegions(regs);
985     for (unsigned ridx=0; ridx < regs.size(); ridx++) {
986         if (memEnd_ < regs[ridx]->getMemOffset() + regs[ridx]->getMemSize()) {
987             memEnd_ = regs[ridx]->getMemOffset() + regs[ridx]->getMemSize();
988         }
989     }
990     memEnd_ += codeBase();
991     return memEnd_;
992 }
993
994
995 // This gets called once per image. Poke through to the internals;
996 // all we care about, amusingly, is symbol table information.
997
998 void mapped_object::getInferiorHeaps(vector<pair<string, Address> > &foundHeaps)
999 {
1000     vector<pair<string, Address> > code_heaps;
1001     vector<pair<string, Address> > data_heaps;
1002
1003     if (!parse_img()->getInferiorHeaps(code_heaps, data_heaps)) {
1004 #if !defined(os_aix)
1005         // AIX: see auxiliary lookup, below.
1006         return;
1007 #endif
1008     }
1009
1010
1011     // We have a bunch of offsets, now add in the base addresses
1012     for (unsigned i = 0; i < code_heaps.size(); i++) {
1013                 foundHeaps.push_back(pair<string,Address>(code_heaps[i].first,
1014                                                   code_heaps[i].second + codeBase()));
1015     }
1016     for (unsigned i = 0; i < data_heaps.size(); i++) {
1017         foundHeaps.push_back(pair<string,Address>(data_heaps[i].first,
1018                                                   data_heaps[i].second + dataBase()));
1019     }
1020
1021     // AIX: we scavenge space. Do that here.
1022
1023 #if defined(os_aix)
1024     // ...
1025
1026     // a.out: from the end of the loader to 0x20000000
1027     // Anything in 0x2....: skip
1028     // Anything in 0xd....: to the next page
1029
1030     Address start = 0;
1031     unsigned size = 0;
1032
1033 #if 0
1034     fprintf(stderr, "Looking for inferior heap in %s/%s, codeAbs 0x%x (0x%x/0x%x)\n",
1035             getFileDesc().file().c_str(),
1036             getFileDesc().member().c_str(),
1037             codeAbs(),
1038             codeBase(),
1039             codeOffset());
1040 #endif
1041
1042     if (codeAbs() >= 0xd0000000) {
1043         // This caused problems on sp3-01.cs.wisc.edu; apparently we were overwriting
1044         // necessary library information. For now I'm disabling it (10FEB06) until
1045         // we can get a better idea of what was going on.
1046 #if 0
1047         start = codeAbs() + imageSize();
1048         start += instruction::size() - (start % (Address)instruction::size());
1049         size = PAGESIZE - (start % PAGESIZE);
1050 #endif
1051     }
1052     else if (codeAbs() > 0x20000000) {
1053         // ...
1054     }
1055     else if (codeAbs() > 0x10000000) {
1056         // We also have the loader; there is no information on where
1057         // it goes (ARGH) so we pad the end of the code segment to
1058         // try and avoid it.
1059
1060         SymtabAPI::Region *sec;
1061         image_->getObject()->findRegion(sec, ".loader");
1062         Address loader_end = codeAbs() +
1063             //sec.getSecAddr() +
1064             image_->getObject()->getLoadOffset() +
1065             sec->getDiskSize();
1066         //Address loader_end = codeAbs() +
1067         //    image_->getObject()->loader_off() +
1068         //    image_->getObject()->loader_len();
1069         // If we loaded it up in the data segment, don't use...
1070         if (loader_end > 0x20000000)
1071             loader_end = 0;
1072         Address code_end = codeAbs() + imageSize();
1073
1074         start = (loader_end > code_end) ? loader_end : code_end;
1075
1076         start += instruction::size() - (start % (Address)instruction::size());
1077         size = (0x20000000 - start);
1078     }
1079
1080
1081     if (start) {
1082         char name_scratch[1024];
1083         snprintf(name_scratch, 1023,
1084                  "DYNINSTstaticHeap_%i_uncopiedHeap_0x%lx_scratchpage_%s",
1085                  (unsigned) size,
1086                  start,
1087                  fileName().c_str());
1088
1089         foundHeaps.push_back(pair<string,Address>(string(name_scratch),start));
1090     }
1091 #endif
1092 }
1093
1094
1095 void *mapped_object::getPtrToInstruction(Address addr) const {
1096    if (!isCode(addr)) return NULL;
1097    
1098    Address offset;
1099    if (proc()->getAddressWidth() == 8) {
1100       offset = addr - codeBase();
1101    }
1102    else {
1103       offset = ((unsigned) addr) - ((unsigned) codeBase());
1104    }
1105
1106   return image_->codeObject()->cs()->getPtrToInstruction(offset);
1107 }
1108
1109 void *mapped_object::getPtrToData(Address addr) const
1110 {
1111    assert(addr >= dataAbs());
1112    assert(addr < (dataAbs() + dataSize()));
1113
1114    // Don't go from the code base... the image adds back in the code
1115    // offset.
1116    Address offset = addr - dataBase();
1117    return image_->codeObject()->cs()->getPtrToData(offset);
1118 }
1119
1120 // mapped objects may contain multiple Symtab::Regions, this function
1121 // should not be used, but must be included in the class because this
1122 // function is a subclass of codeRange
1123 void *mapped_object::get_local_ptr() const
1124 {
1125     assert(0);// if you crash here, blame me. -kevin
1126     return NULL;
1127     //   return image_->getObject()->image_ptr();
1128 }
1129
1130
1131 bool mapped_object::getSymbolInfo(const std::string &n, int_symbol &info)
1132 {
1133     using SymtabAPI::Symbol;
1134
1135     assert(image_);
1136
1137     Symbol *lowlevel_sym = image_->symbol_info(n);
1138     if (!lowlevel_sym) {
1139         lowlevel_sym = image_->symbol_info(std::string("_") + n);
1140     }
1141
1142     if (!lowlevel_sym) return false;
1143
1144     if (lowlevel_sym->getType() == Symbol::ST_OBJECT)
1145         info = int_symbol(lowlevel_sym, dataBase_);
1146     else
1147         info = int_symbol(lowlevel_sym, codeBase_);
1148
1149     return true;
1150 }
1151
1152 mapped_module *mapped_object::getOrCreateForkedModule(mapped_module *parMod)
1153 {
1154    // Okay. We're forking, and this is the child mapped_object.
1155    // And now, given a parent module, we need to find the right one
1156    // in our little baby modules.
1157
1158    // Since we've already copied modules, we can just do a name lookup.
1159    mapped_module *childModule = findModule(parMod->fileName(), false);
1160    assert(childModule);
1161    return childModule;
1162
1163 }
1164
1165 mapped_module* mapped_object::getDefaultModule()
1166 {
1167   mapped_module* ret = findModule("DEFAULT_MODULE");
1168   if(ret) return ret;
1169
1170   // Make sure the everyModule vector is initialized
1171   getModules();
1172
1173   assert(everyModule.size() > 0);
1174   return everyModule[0];
1175
1176 }
1177
1178
1179 // Grabs all block_instances corresponding to the region (horribly inefficient)
1180 bool mapped_object::findBlocksByRange(Address startAddr,
1181                                       Address endAddr,
1182                                       list<block_instance*> &rangeBlocks)//output
1183 {
1184    std::set<ParseAPI::Block *> papiBlocks;
1185    for (Address cur = startAddr; cur < endAddr; ++cur) {
1186       Address papiCur = cur - codeBase();
1187       parse_img()->codeObject()->findBlocks(NULL, papiCur, papiBlocks);
1188    }
1189
1190    for (std::set<ParseAPI::Block *>::iterator iter = papiBlocks.begin();
1191         iter != papiBlocks.end(); ++iter) {
1192       // For each parseAPI block, up-map it to a block_instance
1193       block_instance *bbl = this->findBlock(*iter);
1194       assert(bbl);
1195       rangeBlocks.push_back(bbl);
1196    }
1197    return !rangeBlocks.empty();
1198 }
1199
1200 void mapped_object::findFuncsByRange(Address startAddr,
1201                                       Address endAddr,
1202                                       std::set<func_instance*> &pageFuncs)
1203 {
1204    std::list<block_instance *> bbls;
1205    findBlocksByRange(startAddr, endAddr, bbls);
1206    for (std::list<block_instance *>::iterator iter = bbls.begin();
1207         iter != bbls.end(); ++iter) {
1208       (*iter)->getFuncs(std::inserter(pageFuncs, pageFuncs.end()));
1209    }
1210 }
1211
1212 /* Re-trigger parsing in the object.  This function should
1213  * only be invoked if all funcEntryAddrs lie within the boundaries of
1214  * the object.
1215  *
1216  * Copies over the raw data if a funcEntryAddr lies in between
1217  * the region's disk size and memory size, also copies raw data
1218  * if the memory around the entry point has changed
1219  *
1220  * A true return value means that new functions were parsed
1221 */
1222 bool mapped_object::parseNewFunctions(vector<Address> &funcEntryAddrs)
1223 {
1224
1225     bool reparsedObject = false;
1226     Address baseAddress = codeBase();
1227     SymtabAPI::Region *reg;
1228     std::set<SymtabAPI::Region*> visitedRegions;
1229
1230     // code page bytes may need updating
1231     if (BPatch_defensiveMode == analysisMode_) {
1232         setCodeBytesUpdated(false);
1233     }
1234
1235     assert(!parse_img()->hasNewBlocks());
1236
1237     // update regions if necessary, check that functions not parsed already
1238     vector<Address>::iterator curEntry = funcEntryAddrs.begin();
1239     while (curEntry != funcEntryAddrs.end()) {
1240         Address entryOffset = (*curEntry)-baseAddress;
1241         reg = parse_img()->getObject()->findEnclosingRegion(entryOffset);
1242         if (reg != NULL) {
1243
1244             if (parse_img()->codeObject()->defensiveMode() &&
1245                 visitedRegions.end() == visitedRegions.find(reg))
1246             {
1247                 updateCodeBytesIfNeeded(*curEntry);
1248                 visitedRegions.insert(reg);
1249             }
1250
1251             if (parse_img()->findFuncByEntry(entryOffset)) {
1252                 fprintf(stderr,"WARNING: tried to parse at %lx, where a "
1253                         "function entry exists already %s[%d]\n",
1254                         *curEntry, FILE__,__LINE__);
1255                 curEntry = funcEntryAddrs.erase(curEntry);
1256             }
1257             else {
1258                 curEntry++;
1259             }
1260
1261         }
1262         else {
1263             fprintf(stderr,"ERROR: passed invalid address %lx to "
1264                     "parseNewFunctions %s[%d]\n", *curEntry,FILE__,__LINE__);
1265             assert(0);
1266             curEntry++;
1267         }
1268     }
1269
1270     // parse at funcEntryAddrs
1271     curEntry = funcEntryAddrs.begin();
1272     set<ParseAPI::Function*> tmpfuncs;
1273     while (curEntry != funcEntryAddrs.end()) {
1274         Address entryOffset = (*curEntry)  - baseAddress;
1275         parse_img()->codeObject()->parse( entryOffset, true );
1276
1277         if ( ! parse_img()->findFuncs(entryOffset, tmpfuncs) ) {
1278             // parse failed, this can happen when the function is just a
1279             // jump or return instruction, but it doesn't mean that we
1280             // didn't do any parsing
1281             fprintf(stderr,"WARNING, failed to parse function at %lx, "
1282                     "%s[%d]\n", *curEntry, FILE__, __LINE__);
1283         }
1284         else {
1285             reparsedObject = true;
1286             tmpfuncs.clear();
1287         }
1288         curEntry++;
1289     }
1290
1291     assert(consistency(&(*addrSpace())));
1292     return reparsedObject;
1293 }
1294
1295
1296 /* 0. The target and source must be in the same mapped region, make sure memory
1297  *    for the target is up to date
1298  * 1. Parse from target address, add new edge at image layer
1299  * 2. Register all newly created functions as a result of new edge parsing
1300  * 3. Add image blocks as block_instances
1301  * 4. fix up mapping of split blocks with points
1302  * 5. Add image points, as instPoints
1303 */
1304 bool mapped_object::parseNewEdges(const std::vector<edgeStub> &stubs)
1305 {
1306     using namespace SymtabAPI;
1307     using namespace ParseAPI;
1308
1309     vector<ParseAPI::CodeObject::NewEdgeToParse> edgesInThisObject;
1310
1311 /* 0. Make sure memory for the target is up to date */
1312
1313     // Do various checks and set edge types, if necessary
1314     for (unsigned idx=0; idx < stubs.size(); idx++) {
1315         mapped_object *targ_obj = proc()->findObject(stubs[idx].trg);
1316         assert(targ_obj);
1317
1318         // update target region if needed
1319         if (BPatch_defensiveMode == hybridMode())
1320         {
1321           targ_obj->updateCodeBytesIfNeeded(stubs[idx].trg);
1322         }
1323
1324         EdgeTypeEnum edgeType = stubs[idx].type;
1325
1326         // Determine if this stub already has been parsed
1327         // Which means looking up a block at the target address
1328         if (targ_obj->findBlockByEntry(stubs[idx].trg)) {
1329            cerr << "KEVINTEST: VERIFY THAT I WORK: parsing edge for target that already exists" << endl;
1330           //continue; //KEVINTODO: don't we maybe want to add the edge anyway?
1331         }
1332
1333         // Otherwise we don't have a target block, so we need to make one.
1334         if (stubs[idx].type == ParseAPI::NOEDGE)
1335         {
1336             using namespace InstructionAPI;
1337             // And we don't know what type of edge this is. Lovely. Let's
1338             // figure it out from the instruction class, since that's
1339             // the easy way to do things.
1340
1341             block_instance::Insns insns;
1342             stubs[idx].src->getInsns(insns);
1343             InstructionAPI::Instruction::Ptr cf = insns[stubs[idx].src->last()];
1344             assert(cf);
1345             switch (cf->getCategory()) {
1346             case c_CallInsn:
1347                 if (stubs[idx].trg == stubs[idx].src->end())
1348                 {
1349                     edgeType = CALL_FT;
1350                 }
1351                 else
1352                 {
1353                     edgeType = CALL;
1354                 }
1355                 break;
1356             case c_ReturnInsn:
1357                 //edgeType = RET;
1358                 // The above doesn't work according to Nate
1359                 edgeType = INDIRECT;
1360                 break;
1361             case c_BranchInsn:
1362                 if (cf->readsMemory())
1363                 {
1364                     edgeType = INDIRECT;
1365                 }
1366                 else if (!cf->allowsFallThrough())
1367                 {
1368                     edgeType = DIRECT;
1369                 }
1370                 else if (stubs[idx].trg == stubs[idx].src->end())
1371                 {
1372                     edgeType = COND_NOT_TAKEN;
1373                 }
1374                 else
1375                 {
1376                     edgeType = COND_TAKEN;
1377                 }
1378                 break;
1379             default:
1380                 edgeType = FALLTHROUGH;
1381                 break;
1382             }
1383         }
1384
1385                 /* 1. Parse from target address, add new edge at image layer  */
1386                 CodeObject::NewEdgeToParse newEdge(stubs[idx].src->llb(),
1387             stubs[idx].trg - targ_obj->codeBase(),
1388             edgeType);
1389                 if (this != targ_obj) {
1390                         std::vector<ParseAPI::CodeObject::NewEdgeToParse> newEdges;
1391                         newEdges.push_back(newEdge);
1392                         targ_obj->parse_img()->codeObject()->parseNewEdges(newEdges);
1393                 }
1394                 else {
1395                         edgesInThisObject.push_back(newEdge);
1396                 }
1397         }
1398  
1399         /* 2. Parse intra-object edges, after removing any edges that 
1400           would be duplicates at the image-layer */
1401         parse_img()->codeObject()->parseNewEdges(edgesInThisObject);
1402
1403     // build list of potentially modified functions
1404     vector<ParseAPI::Function*> modIFuncs;
1405     vector<func_instance*> modFuncs;
1406     for(unsigned sidx=0; sidx < stubs.size(); sidx++) {
1407         if (stubs[sidx].src != NULL) {
1408             stubs[sidx].src->llb()->getFuncs(modIFuncs);
1409         }
1410     }
1411
1412     for (unsigned fidx=0; fidx < modIFuncs.size(); fidx++)
1413     {
1414        func_instance *func = findFunction(modIFuncs[fidx]);
1415        modFuncs.push_back(func);
1416
1417        //func->ifunc()->invalidateCache();//KEVINTEST: used to call this, which might have been important
1418
1419        modFuncs[fidx]->triggerModified();
1420        modFuncs[fidx]->blocks();
1421        modFuncs[fidx]->callBlocks();
1422        modFuncs[fidx]->exitBlocks();
1423     }
1424
1425     assert(consistency(&(*addrSpace())));
1426     return true;
1427 }
1428
1429
1430 /* 1. Copy the entire region in from the mutatee,
1431  * 2. if memory emulation is not on, copy blocks back in from the
1432  * mapped file, since we don't want to copy instrumentation into
1433  * the mutatee.
1434  */
1435 void mapped_object::expandCodeBytes(SymtabAPI::Region *reg)
1436 {
1437     assert(reg);
1438     void *mappedPtr = reg->getPtrToRawData();
1439     Address regStart = reg->getMemOffset();
1440     ParseAPI::Block *cur = NULL;
1441     ParseAPI::CodeObject *cObj = parse_img()->codeObject();
1442     ParseAPI::CodeRegion *parseReg = NULL;
1443     Address copySize = reg->getMemSize();
1444     void* regBuf = malloc(copySize);
1445     Address initializedEnd = regStart + copySize;
1446
1447     set<ParseAPI::CodeRegion*> parseRegs;
1448     cObj->cs()->findRegions(regStart, parseRegs);
1449     parseReg = * parseRegs.begin();
1450     parseRegs.clear();
1451
1452     // 1. copy memory into regBuf
1453     Address readAddr = regStart + codeBase();
1454     if (proc()->isMemoryEmulated()) {
1455         bool valid = false;
1456         boost::tie(valid, readAddr) = proc()->getMemEm()->translate(readAddr);
1457         assert(valid);
1458     }
1459     if (!proc()->readDataSpace((void*)readAddr,
1460                                copySize,
1461                                regBuf,
1462                                true))
1463     {
1464         fprintf(stderr, "%s[%d] Failed to read from region [%lX %lX]\n",
1465                 __FILE__, __LINE__, (long)regStart+codeBase(), copySize);
1466         assert(0);
1467     }
1468     mal_printf("EXTEND_CB: copied to [%lx %lx)\n", codeBase()+regStart, codeBase()+regStart+copySize);
1469
1470
1471     if ( ! proc()->isMemoryEmulated() ) {
1472
1473     // 2. copy code bytes back into the regBuf to wipe out instrumentation
1474     //    and set regBuf to be the data for the region
1475
1476         // find the first block in the region
1477         set<ParseAPI::Block*> analyzedBlocks;
1478         cObj->findBlocks(parseReg, regStart, analyzedBlocks);
1479         if (analyzedBlocks.size()) {
1480             cur = * analyzedBlocks.begin();
1481         } else {
1482             cur = cObj->findNextBlock(parseReg, regStart);
1483         }
1484
1485         // copy code ranges from old mapped data into regBuf
1486         while (cur != NULL &&
1487                cur->start() < initializedEnd)
1488         {
1489             if ( ! memcpy((void*)((Address)regBuf + cur->start() - regStart),
1490                           (void*)((Address)mappedPtr + cur->start() - regStart),
1491                           cur->size()) )
1492             {
1493                 assert(0);
1494             }
1495             mal_printf("EX: uncopy [%lx %lx)\n", codeBase()+cur->start(),codeBase()+cur->end());
1496             // advance to the next block
1497             Address prevEnd = cur->end();
1498             cur = cObj->findBlockByEntry(parseReg,prevEnd);
1499             if (!cur) {
1500                 cur = cObj->findNextBlock(parseReg,prevEnd);
1501             }
1502         }
1503         mal_printf("Expand region: %lx blocks copied back into mapped file\n",
1504                    analyzedBlocks.size());
1505     }
1506
1507     if (reg->isDirty()) {
1508         // if isDirty is true, the pointer was created via malloc
1509         // and we can free it.  If not, isDirty is part of a mapped
1510         // file and we can't free it
1511         free( mappedPtr );
1512     }
1513
1514     // swap out rawDataPtr for the mapped file
1515     static_cast<SymtabCodeSource*>(cObj->cs())->
1516         resizeRegion( reg, reg->getMemSize() );
1517     reg->setPtrToRawData( regBuf , copySize );
1518
1519     // expand this mapped_object's codeRange
1520     if (codeBase() + reg->getMemOffset() + reg->getMemSize()
1521         >
1522         codeAbs() + get_size())
1523     {
1524         parse_img()->setImageLength( codeBase()
1525                                      + reg->getMemOffset()
1526                                      + reg->getMemSize()
1527                                      - codeAbs() );
1528
1529     }
1530 }
1531
1532 // 1. use other update functions to update non-code areas of mapped files,
1533 //    expanding them if we overwrote into unmapped areas
1534 // 2. copy overwritten regions into the mapped objects
1535 void mapped_object::updateCodeBytes(const list<pair<Address,Address> > &owRanges)
1536 {
1537     bool memEmulation = proc()->isMemoryEmulated();
1538 // 1. use other update functions to update non-code areas of mapped files,
1539 //    expanding them if we wrote in un-initialized memory
1540     using namespace SymtabAPI;
1541     std::set<Region *> expandRegs;// so we don't update regions more than once
1542     Address baseAddress = codeBase();
1543
1544     // figure out which regions need expansion and which need updating
1545     list<pair<Address,Address> >::const_iterator rIter = owRanges.begin();
1546     for(; rIter != owRanges.end(); rIter++) {
1547         Address lastChangeOffset = (*rIter).second -1 -baseAddress;
1548         Region *curReg = parse_img()->getObject()->findEnclosingRegion
1549                                                     ( lastChangeOffset );
1550         if ( lastChangeOffset - curReg->getMemOffset() >= curReg->getDiskSize() ) {
1551             expandRegs.insert(curReg);
1552         }
1553     }
1554     // expand and update regions
1555     for (set<Region*>::iterator regIter = expandRegs.begin();
1556          regIter != expandRegs.end(); regIter++)
1557     {
1558         expandCodeBytes(*regIter);
1559     }
1560     std::vector<Region *> allregions;
1561     parse_img()->getObject()->getCodeRegions(allregions);
1562     for (unsigned int ridx=0; ridx < allregions.size(); ridx++)
1563     {
1564         Region *curreg = allregions[ridx];
1565         if (expandRegs.end() == expandRegs.find(curreg)) {
1566             updateCodeBytes(curreg); // KEVINOPTIMIZE: major overkill here, only update regions that had unprotected pages
1567         }
1568     }
1569
1570 // 2. copy overwritten regions into the mapped objects
1571     for(rIter = owRanges.begin(); rIter != owRanges.end(); rIter++)
1572     {
1573         Address readAddr = rIter->first;
1574         if (memEmulation) {
1575             bool valid = false;
1576             boost::tie(valid, readAddr) = proc()->getMemEm()->translate(readAddr);
1577             assert(valid);
1578         }
1579
1580         Region *reg = parse_img()->getObject()->findEnclosingRegion
1581             ( (*rIter).first - baseAddress );
1582         unsigned char* regPtr = (unsigned char*)reg->getPtrToRawData()
1583             + (*rIter).first - baseAddress - reg->getMemOffset();
1584
1585         if (!proc()->readDataSpace((void*)readAddr,
1586                                    (*rIter).second - (*rIter).first,
1587                                    regPtr,
1588                                    true) )
1589         {
1590             assert(0);
1591         }
1592         if (0) {
1593             mal_printf("OW_CB: copied to [%lx %lx): ", rIter->first,rIter->second);
1594             for (unsigned idx=0; idx < rIter->second - rIter->first; idx++) {
1595                 mal_printf("%2x ", (unsigned) regPtr[idx]);
1596             }
1597             mal_printf("\n");
1598         }
1599     }
1600     pagesUpdated_ = true;
1601 }
1602
1603 // this is a helper function
1604 //
1605 // update mapped data for whole object, or just one region, if specified
1606 //
1607 // Read unprotected pages into the mapped file
1608 // (not analyzed code regions so we don't get instrumentation in our parse)
1609 void mapped_object::updateCodeBytes(SymtabAPI::Region * symReg)
1610 {
1611     assert(NULL != symReg);
1612
1613     Address base = codeBase();
1614     ParseAPI::CodeObject *cObj = parse_img()->codeObject();
1615     std::vector<SymtabAPI::Region *> regions;
1616
1617     Block *curB = NULL;
1618     set<ParseAPI::Block *> analyzedBlocks;
1619     set<ParseAPI::CodeRegion*> parseRegs;
1620
1621     void *mappedPtr = symReg->getPtrToRawData();
1622     Address regStart = symReg->getMemOffset();
1623
1624     cObj->cs()->findRegions(regStart, parseRegs);
1625     ParseAPI::CodeRegion *parseReg = * parseRegs.begin();
1626     parseRegs.clear();
1627
1628     // find the first block in the region
1629     cObj->findBlocks(parseReg, regStart, analyzedBlocks);
1630     if (analyzedBlocks.size()) {
1631         curB = * analyzedBlocks.begin();
1632         analyzedBlocks.clear();
1633     } else {
1634         curB = cObj->findNextBlock(parseReg, regStart);
1635     }
1636
1637     Address prevEndAddr = regStart;
1638     while ( curB != NULL &&
1639             curB->start() < regStart + symReg->getDiskSize() )
1640     {
1641         // if there's a gap between previous and current block
1642         if (prevEndAddr < curB->start()) {
1643             // update the mapped file
1644             Address readAddr = prevEndAddr + base;
1645             if (proc()->isMemoryEmulated()) {
1646                 bool valid = false;
1647                 boost::tie(valid, readAddr) = proc()->getMemEm()->translate(readAddr);
1648                 assert(valid);
1649             }
1650             if (!proc()->readDataSpace(
1651                     (void*)readAddr,
1652                     curB->start() - prevEndAddr,
1653                     (void*)((Address)mappedPtr + prevEndAddr - regStart),
1654                     true))
1655             {
1656                 assert(0);//read failed
1657             }
1658             //mal_printf("UPDATE_CB: copied to [%lx %lx)\n", prevEndAddr+base,curB->start()+base);
1659         }
1660
1661         // advance curB to last adjacent block and set prevEndAddr
1662         prevEndAddr = curB->end();
1663         Block *ftBlock = cObj->findBlockByEntry(parseReg,prevEndAddr);
1664         while (ftBlock) {
1665             curB = ftBlock;
1666             prevEndAddr = curB->end();
1667             ftBlock = cObj->findBlockByEntry(parseReg,prevEndAddr);
1668         }
1669
1670         curB = cObj->findNextBlock(parseReg, prevEndAddr);
1671
1672     }
1673     // read in from prevEndAddr to the end of the region
1674         // (will read in whole region if there are no ranges in the region)
1675     if (prevEndAddr < regStart + symReg->getDiskSize()) {
1676         Address readAddr = prevEndAddr + base;
1677         if (proc()->isMemoryEmulated()) {
1678             bool valid = false;
1679             boost::tie(valid, readAddr) = proc()->getMemEm()->translate(readAddr);
1680             assert(valid);
1681         }
1682         if (!proc()->readDataSpace(
1683                 (void*)readAddr,
1684                 regStart + symReg->getDiskSize() - prevEndAddr,
1685                 (void*)((Address)mappedPtr + prevEndAddr - regStart),
1686                 true))
1687         {
1688             assert(0);// read failed
1689         }
1690     }
1691     // change all region pages with REPROTECTED status to PROTECTED status
1692     Address page_size = proc()->proc()->getMemoryPageSize();
1693     Address curPage = (regStart / page_size) * page_size + base;
1694     Address regEnd = base + regStart + symReg->getDiskSize();
1695     for (; protPages_.end() == protPages_.find(curPage)  && curPage < regEnd;
1696          curPage += page_size) {};
1697     for (map<Address,WriteableStatus>::iterator pit = protPages_.find(curPage);
1698          pit != protPages_.end() && pit->first < regEnd;
1699          pit++)
1700     {
1701         pit->second = PROTECTED;
1702     }
1703 }
1704
1705 // checks if update is needed by looking in the gap between the previous
1706 // and next block for changes to the underlying bytes
1707 //
1708 // should only be called if we've already checked that we're not on an
1709 // analyzed page that's been protected from overwrites, as this
1710 // check would not be needed
1711 bool mapped_object::isUpdateNeeded(Address entry)
1712 {
1713     using namespace ParseAPI;
1714     bool updateNeeded = false;
1715     void* regBuf = NULL;
1716     Address base = codeBase();
1717
1718     assert( BPatch_defensiveMode == hybridMode() );
1719
1720     set<CodeRegion*> cregs;
1721     CodeObject *co = parse_img()->codeObject();
1722     co->cs()->findRegions(entry-base, cregs);
1723     assert( ! co->cs()->regionsOverlap() );
1724     if (0 == cregs.size()) {
1725         mal_printf("Object update request has invalid addr[%lx] %s[%d]\n",
1726                    entry, FILE__,__LINE__);
1727         return false;
1728     }
1729     SymtabCodeRegion *creg = static_cast<SymtabCodeRegion*>( * cregs.begin() );
1730
1731     // update the range tree, if necessary
1732     set<ParseAPI::Block *> analyzedBlocks;
1733     if (parse_img()->findBlocksByAddr(entry-base, analyzedBlocks)) {
1734         return false; // don't need to update if target is in analyzed code
1735     }
1736
1737     // see if the underlying bytes have changed
1738     //
1739     // read until the next basic block or until the end of the region
1740     // to make sure nothing has changed, otherwise we'll want to read
1741     // the section in again
1742     Block *nextBlk = co->findNextBlock(creg, entry-base);
1743     unsigned comparison_size = 0;
1744     if (nextBlk) {
1745         comparison_size = nextBlk->start() - (entry-base);
1746     } else {
1747         comparison_size = creg->symRegion()->getDiskSize()
1748             - ( (entry - base) - creg->symRegion()->getMemOffset() );
1749     }
1750
1751     // read until first difference, then see if the difference is to known
1752     // in which case the difference is due to instrumentation, as we would
1753     // have otherwise detected the overwrite
1754     Address page_size = proc()->proc()->getMemoryPageSize();
1755     comparison_size = ( comparison_size <  page_size)
1756                       ? comparison_size : page_size;
1757     regBuf = malloc(comparison_size);
1758     Address readAddr = entry;
1759     if (proc()->isMemoryEmulated()) {
1760         bool valid = false;
1761                 Address translated = 0;
1762                 boost::tie(valid, translated) = proc()->getMemEm()->translate(readAddr);
1763                 if (valid) readAddr = translated;
1764         }
1765
1766    // mal_printf("%s[%d] Comparing %lx bytes starting at %lx\n",
1767       //      FILE__,__LINE__,comparison_size,entry);
1768     if (!proc()->readDataSpace((void*)readAddr, comparison_size, regBuf, true)) {
1769         assert(0);
1770     }
1771     void *mappedPtr = (void*)
1772                       ((Address)creg->symRegion()->getPtrToRawData() +
1773                         (entry - base - creg->symRegion()->getMemOffset()) );
1774     //compare
1775     if (0 != memcmp(mappedPtr,regBuf,comparison_size) ) {
1776         updateNeeded = true;
1777     }
1778     free(regBuf);
1779     regBuf = NULL;
1780
1781     return updateNeeded;
1782 }
1783
1784 // checks to see if expansion is needed
1785 bool mapped_object::isExpansionNeeded(Address entry)
1786 {
1787     using namespace SymtabAPI;
1788     Address base = codeBase();
1789     Region * reg = parse_img()->getObject()->findEnclosingRegion(entry - base);
1790
1791     if (reg->getMemSize() <= reg->getDiskSize()) {
1792         return false;
1793     }
1794
1795     if ( ! parse_img()->getObject()->isCode(entry - base) ) {
1796         return true;
1797     }
1798
1799     if (expansionCheckedRegions_.end() !=
1800         expansionCheckedRegions_.find(reg)) {
1801         return false;
1802     }
1803     expansionCheckedRegions_.insert(reg);
1804
1805     // if there is uninitialized space in the region,
1806     // see if the first few bytes have been updated
1807     Address compareStart =
1808         base + reg->getMemOffset() + reg->getDiskSize();
1809     if (proc()->isMemoryEmulated()) {
1810         bool valid = false;
1811         boost::tie(valid, compareStart) = proc()->getMemEm()->translate(compareStart);
1812         assert(valid);
1813     }
1814 #if defined(cap_instruction_api)
1815     unsigned compareSize = InstructionAPI::InstructionDecoder::maxInstructionLength;
1816 #else
1817     unsigned compareSize = 2 * proc()->getAddressWidth();
1818 #endif
1819     Address uninitSize = reg->getMemSize() - reg->getDiskSize();
1820     if (compareSize > uninitSize) {
1821         compareSize = uninitSize;
1822     }
1823     unsigned char* regBuf = (unsigned char*) malloc(compareSize);
1824     if (!proc()->readDataSpace((void*)compareStart,compareSize,regBuf,true)) {
1825         fprintf(stderr, "%s[%d] Failed to read from region [%lX %lX]\n",
1826                 __FILE__, __LINE__, compareStart, compareStart+compareSize);
1827         assert(0);
1828     }
1829     // compare to zero if the region has not been expanded yet
1830     bool allZeros = true;
1831     for (unsigned idx=0; allZeros && idx < compareSize; idx++) {
1832         if (0 != regBuf[idx]) {
1833             allZeros = false;
1834         }
1835     }
1836     if (allZeros) {
1837         return false;
1838     } else {
1839         return true;
1840     }
1841 }
1842
1843 // updates the raw code bytes by fetching from memory, if needed
1844 //
1845 // updates if we haven't updated since the last time code could have
1846 // changed, and if the entry address is on an unprotected code page,
1847 // or if the address is in an uninitialized memory,
1848 bool mapped_object::updateCodeBytesIfNeeded(Address entry)
1849 {
1850         //cerr << "updateCodeBytes @ " << hex << entry << dec << endl;
1851
1852         assert( BPatch_defensiveMode == analysisMode_ );
1853
1854     Address pageAddr = entry -
1855         (entry % proc()->proc()->getMemoryPageSize());
1856
1857     if ( pagesUpdated_ ) {
1858                 //cerr << "\t No pages have been updated in mapped_object, ret false" << endl;
1859         return false;
1860     }
1861
1862     if (protPages_.end() != protPages_.find(pageAddr) &&
1863         PROTECTED == protPages_[pageAddr])
1864     {
1865                 //cerr << "\t Address corresponds to protected page, ret false" << endl;
1866         return false;
1867     }
1868
1869     bool expand = isExpansionNeeded(entry);
1870     if ( ! expand ) {
1871         if ( ! isUpdateNeeded(entry) ) {
1872                         //cerr << "\t Expansion false and no update needed, ret false" << endl;
1873             return false;
1874         }
1875     }
1876
1877     SymtabAPI::Region * reg = parse_img()->getObject()->findEnclosingRegion
1878         (entry - codeBase());
1879     mal_printf("%s[%d] updating region [%lx %lx] for entry point %lx\n",
1880                FILE__,__LINE__,
1881                reg->getMemOffset(),
1882                reg->getMemOffset()+reg->getDiskSize(),
1883                entry);
1884
1885     if ( expand ) {
1886         expandCodeBytes(reg);
1887     }
1888     else {
1889         updateCodeBytes(reg);
1890     }
1891
1892     codeByteUpdates_++;
1893     pagesUpdated_ = true;
1894     return true;
1895 }
1896
1897 void mapped_object::remove(func_instance *func) {
1898
1899     if (as()->isMemoryEmulated()) {
1900         as()->getMemEm()->removeSpringboards(func);
1901     }
1902     
1903     // clear out module- and BPatch-level data structures 
1904     BPatch_addressSpace* bpAS = (BPatch_addressSpace*)proc()->up_ptr();
1905     BPatch_module *bpmod = bpAS->getImage()->findModule(func->mod());
1906     BPatch_function *bpfunc = bpAS->findOrCreateBPFunc(SCAST_FI(func), bpmod);
1907     bpfunc->removeCFG();
1908     bpmod->remove(bpfunc);
1909     func->mod()->remove(func);
1910
1911     // remove from func_instance vector
1912     funcs_.erase(func->ifunc());
1913
1914     // remove pretty names
1915     pdvector<func_instance *> *funcsByName = NULL;
1916     for (unsigned pretty_iter = 0;
1917          pretty_iter < func->prettyNameVector().size();
1918          pretty_iter++)
1919     {
1920         allFunctionsByPrettyName.find
1921             (func->prettyNameVector()[pretty_iter], funcsByName);
1922         if (funcsByName) {
1923             for (unsigned fIdx=0; fIdx < funcsByName->size(); fIdx++) {
1924                 if (func == (*funcsByName)[fIdx]) {
1925                     unsigned lastIdx = funcsByName->size() -1;
1926                     (*funcsByName)[fIdx] = (*funcsByName)[lastIdx];
1927                     funcsByName->pop_back();
1928                     if (funcsByName->size() == 0) {
1929                         allFunctionsByPrettyName.undef
1930                             (func->symTabNameVector()[pretty_iter]);
1931                     }
1932                 }
1933             }
1934         }
1935     }
1936     // remove typed names
1937     for (unsigned typed_iter = 0;
1938          typed_iter < func->typedNameVector().size();
1939          typed_iter++)
1940     {
1941         allFunctionsByPrettyName.find
1942             (func->typedNameVector()[typed_iter], funcsByName);
1943         if (funcsByName) {
1944             for (unsigned fIdx=0; fIdx < funcsByName->size(); fIdx++) {
1945                 if (func == (*funcsByName)[fIdx]) {
1946                     unsigned lastIdx = funcsByName->size() -1;
1947                     (*funcsByName)[fIdx] = (*funcsByName)[lastIdx];
1948                     funcsByName->pop_back();
1949                     if (funcsByName->size() == 0) {
1950                         allFunctionsByPrettyName.undef
1951                             (func->symTabNameVector()[typed_iter]);
1952                     }
1953                 }
1954             }
1955         }
1956     }
1957     // remove symtab names
1958     for (unsigned symtab_iter = 0;
1959          symtab_iter < func->symTabNameVector().size();
1960          symtab_iter++)
1961     {
1962         allFunctionsByMangledName.find
1963             (func->symTabNameVector()[symtab_iter], funcsByName);
1964         if (funcsByName) {
1965             for (unsigned fIdx=0; fIdx < funcsByName->size(); fIdx++) {
1966                 if (func == (*funcsByName)[fIdx]) {
1967                     unsigned lastIdx = funcsByName->size() -1;
1968                     (*funcsByName)[fIdx] = (*funcsByName)[lastIdx];
1969                     funcsByName->pop_back();
1970                     if (funcsByName->size() == 0) {
1971                         allFunctionsByMangledName.undef
1972                             (func->symTabNameVector()[symtab_iter]);
1973                     }
1974                 }
1975             }
1976         }
1977     }
1978 }
1979
1980 void mapped_object::remove(instPoint *point)
1981 {
1982     BPatch_addressSpace* bpAS = (BPatch_addressSpace*)proc()->up_ptr();
1983     BPatch_module *bpmod = bpAS->getImage()->findModule(point->func()->mod());
1984     bpmod->remove(point);
1985 }
1986
1987 // does not delete
1988 void mapped_object::destroy(PatchAPI::PatchBlock *b) {
1989    calleeNames_.erase(SCAST_BI(b));
1990    if (as()->isMemoryEmulated()) {
1991       as()->getMemEm()->removeSpringboards(SCAST_BI(b));
1992    }
1993 }
1994
1995 // does not delete
1996 void mapped_object::destroy(PatchAPI::PatchFunction *f) {
1997     remove(SCAST_FI(f));
1998 }
1999
2000 void mapped_object::removeEmptyPages()
2001 {
2002     // get all pages currently containing code from the mapped modules
2003     set<Address> curPages;
2004     vector<Address> emptyPages;
2005     const vector<mapped_module*> & mods = getModules();
2006     for (unsigned midx=0; midx < mods.size(); midx++) {
2007         mods[midx]->getAnalyzedCodePages(curPages);
2008     }
2009     // find entries in protPages_ that aren't in curPages, add to emptyPages
2010     for (map<Address,WriteableStatus>::iterator pit= protPages_.begin();
2011          pit != protPages_.end();
2012          pit++)
2013     {
2014         if (curPages.end() == curPages.find(pit->first)) {
2015             emptyPages.push_back(pit->first);
2016         }
2017     }
2018     // erase emptyPages from protPages
2019     for (unsigned pidx=0; pidx < emptyPages.size(); pidx++) {
2020         protPages_.erase(emptyPages[pidx]);
2021     }
2022 }
2023
2024 bool mapped_object::isSystemLib(const std::string &objname)
2025 {
2026    std::string lowname = objname;
2027    std::transform(lowname.begin(),lowname.end(),lowname.begin(),
2028                   (int(*)(int))std::tolower);
2029
2030    if (std::string::npos != lowname.find("libdyninstapi_rt"))
2031       return true;
2032
2033 #if defined(os_linux)
2034    if (std::string::npos != lowname.find("libc.so"))
2035       return true;
2036    if (std::string::npos != lowname.find("libpthread"))
2037       return true;
2038 #endif
2039
2040 #if defined(os_freebsd)
2041    if(std::string::npos != lowname.find("libc.so"))
2042        return true;
2043    if(std::string::npos != lowname.find("libthr"))
2044        return true;
2045 #endif
2046
2047 #if defined(os_windows)
2048    if (std::string::npos != lowname.find("windows\\system32\\") &&
2049        std::string::npos != lowname.find(".dll"))
2050        return true;
2051    if (std::string::npos != lowname.find("kernel32.dll"))
2052       return true;
2053    if (std::string::npos != lowname.find("user32.dll"))
2054       return true;
2055    if (std::string::npos != lowname.find("advapi32.dll"))
2056       return true;
2057    if (std::string::npos != lowname.find("ntdll.dll"))
2058       return true;
2059    if (std::string::npos != lowname.find("msvcrt") &&
2060        std::string::npos != lowname.find(".dll"))
2061       return true;
2062    if (std::string::npos != lowname.find(".dll"))
2063        return true; //KEVINTODO: find a reliable way of detecting windows system libraries
2064 #endif
2065
2066    return false;
2067 }
2068
2069 bool mapped_object::isExploratoryModeOn()
2070 {
2071     return BPatch_exploratoryMode == analysisMode_ ||
2072            BPatch_defensiveMode == analysisMode_;
2073 }
2074
2075 void mapped_object::addProtectedPage(Address pageAddr)
2076 {
2077     map<Address,WriteableStatus>::iterator iter = protPages_.find(pageAddr);
2078     if (protPages_.end() == iter) {
2079         protPages_[pageAddr] = PROTECTED;
2080     }
2081     else if (PROTECTED != iter->second) {
2082         iter->second = REPROTECTED;
2083     }
2084 }
2085
2086 void mapped_object::removeProtectedPage(Address pageAddr)
2087 {
2088     map<Address,WriteableStatus>::iterator iter = protPages_.find(pageAddr);
2089     if (iter == protPages_.end()) {
2090         // sanity check, make sure there isn't any code on the page, in which
2091         // case we're unprotecting a page that was originally set to be writeable
2092         Address pageOffset = pageAddr - codeBase();
2093         SymtabAPI::Region *reg = parse_img()->getObject()->findEnclosingRegion(pageOffset);
2094         assert(reg);
2095         set<CodeRegion*> cregs;
2096         parse_img()->codeObject()->cs()->findRegions(reg->getMemOffset(), cregs);
2097         if (!cregs.empty()) { // (if empty, pageAddr is in uninitialized memory)
2098             ParseAPI::Block *blk = parse_img()->codeObject()->findNextBlock
2099                 (*cregs.begin(), pageOffset);
2100             Address pageEnd =  pageOffset + proc()->proc()->getMemoryPageSize();
2101             if (blk && blk->start() < pageEnd) {
2102                 assert(0);
2103             }
2104         }
2105         return;
2106     }
2107     iter->second = UNPROTECTED;
2108 }
2109
2110 void mapped_object::setCodeBytesUpdated(bool newval)
2111 {
2112     if (BPatch_defensiveMode == analysisMode_) {
2113         if (false == newval && newval != pagesUpdated_) {
2114             expansionCheckedRegions_.clear();
2115         }
2116         pagesUpdated_ = newval;
2117     } else {
2118         cerr << "WARNING: requesting update of code bytes from memory "
2119              <<  "on non-defensive mapped object, ignoring request "
2120              << fileName().c_str() << " " << __FILE__ << __LINE__ << endl;
2121     }
2122 }
2123
2124 #if !( (defined(os_linux) || defined(os_freebsd)) && \
2125        (defined(arch_x86) || defined(arch_x86_64) || defined(arch_power)) )
2126 func_instance *mapped_object::findGlobalConstructorFunc(const std::string &) {
2127     assert(!"Not implemented");
2128     return NULL;
2129 }
2130
2131 func_instance *mapped_object::findGlobalDestructorFunc(const std::string &) {
2132     assert(!"Not implemented");
2133     return NULL;
2134 }
2135 #endif
2136
2137 bool mapped_object::isEmulInsn(Address insnAddr)
2138 {
2139     return ( emulInsns_.end() != emulInsns_.find(insnAddr) );
2140 }
2141
2142
2143 void mapped_object::setEmulInsnVal(Address insnAddr, void * val)
2144 {
2145     assert(emulInsns_.end() != emulInsns_.find(insnAddr));
2146     emulInsns_[insnAddr] = pair<Register,void*>(emulInsns_[insnAddr].first,val);
2147 }
2148
2149 Register mapped_object::getEmulInsnReg(Address insnAddr)
2150 {
2151     assert(emulInsns_.end() != emulInsns_.find(insnAddr));
2152     return emulInsns_[insnAddr].first;
2153 }
2154
2155 void mapped_object::addEmulInsn(Address insnAddr, Register effectiveAddrReg)
2156 {
2157     emulInsns_[insnAddr] = pair<Register,void*>(effectiveAddrReg,(void *)0);
2158 }
2159
2160 std::string mapped_object::getCalleeName(block_instance *b) {
2161    std::map<block_instance *, std::string>::iterator iter = calleeNames_.find(b);
2162    if (iter != calleeNames_.end()) return iter->second;
2163
2164 #if defined(os_windows)
2165    string calleeName;
2166    if (parse_img()->codeObject()->isIATcall(b->last() - codeBase(), calleeName)) {
2167       setCalleeName(b, calleeName);
2168       return calleeName;
2169    }
2170 #endif
2171
2172    return std::string();
2173 }
2174
2175 void mapped_object::setCalleeName(block_instance *b, std::string s) {
2176    calleeNames_[b] = s;
2177 }
2178
2179 // Missing
2180 // findEdge
2181 // findBlock
2182 // findOneBlockByAddr
2183 // splitBlock
2184 // findFuncByEntry
2185 // findBlock (again)
2186
2187 edge_instance *mapped_object::findEdge(ParseAPI::Edge *e,
2188                                        block_instance *src,
2189                                        block_instance *trg) {
2190   edge_instance *inst = SCAST_EI(getEdge(e, src, trg));
2191   return inst;
2192 }
2193
2194 block_instance *mapped_object::findBlock(ParseAPI::Block *b) {
2195   return SCAST_BI(getBlock(b));
2196 }
2197
2198 block_instance *mapped_object::findOneBlockByAddr(const Address addr) {
2199    std::set<block_instance *> possibles;
2200    findBlocksByAddr(addr, possibles);
2201    for (std::set<block_instance *>::iterator iter = possibles.begin();
2202         iter != possibles.end(); ++iter) {
2203       block_instance::Insns insns;
2204       (*iter)->getInsns(insns);
2205       if (insns.find(addr) != insns.end()) {
2206          return *iter;
2207       }
2208    }
2209    return NULL;
2210 }
2211
2212 void mapped_object::splitBlock(block_instance * b1, 
2213                                block_instance * b2) 
2214 {
2215     // fix block mappings in: map<block_instance *, std::string> calleeNames_
2216     map<block_instance *, std::string>::iterator nit = calleeNames_.find(b1);
2217     if (calleeNames_.end() != nit) {
2218         string name = nit->second;
2219         calleeNames_.erase(nit);
2220         calleeNames_[b2] = name;
2221     }
2222 }
2223
2224 func_instance *mapped_object::findFuncByEntry(const block_instance *blk) {
2225   parse_block *llb = SCAST_PB(blk->llb());
2226   parse_func* f = llb->getEntryFunc();
2227   if (!f) return NULL;
2228   return findFunction(f);
2229 }
2230
2231 func_instance *mapped_object::getCallee(const block_instance *b) const {
2232    std::map<const block_instance *, func_instance *>::const_iterator iter = callees_.find(b);
2233    if (iter == callees_.end()) return NULL;
2234    return iter->second;
2235 }
2236
2237 void mapped_object::setCallee(const block_instance *b, func_instance *f) {
2238    callees_[b] = f;
2239 }
2240
2241 #include "Symtab.h"
2242
2243 void mapped_object::replacePLTStub(SymtabAPI::Symbol *sym, func_instance *orig, Address newAddr) {
2244    // Let's play relocation games...
2245    vector<SymtabAPI::relocationEntry> fbt;
2246    bool ok = parse_img()->getObject()->getFuncBindingTable(fbt);
2247    if(!ok) return;
2248    
2249    
2250    for (unsigned i = 0; i < fbt.size(); ++i) {
2251       if (fbt[i].name() == sym->getMangledName()) {
2252          proc()->bindPLTEntry(fbt[i], codeBase(), orig, newAddr);
2253       }
2254    }
2255 }