Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / BPatch_image.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: BPatch_image.C,v 1.120 2008/06/20 22:00:02 legendre Exp $
33
34 #define BPATCH_FILE
35
36 #include <stdio.h>
37 #include <assert.h>
38 #include <string.h>
39 #include <string>
40
41 #include "process.h"
42 #include "instPoint.h"
43 #include "instP.h"
44 #include "function.h"
45
46 #include "mapped_module.h"
47 #include "mapped_object.h"
48
49 #include "BPatch.h"
50 #include "BPatch_image.h"
51 #include "BPatch_type.h"
52 #include "BPatch_collections.h"
53 #include "BPatch_libInfo.h"
54 #include "BPatch_statement.h"
55 #include "BPatch_function.h" 
56
57 #include "addressSpace.h"
58
59 #include "ast.h"
60 using namespace Dyninst;
61 using namespace std;
62
63 /*
64  * BPatch_image::BPatch_image
65  *
66  * Construct a BPatch_image for the given process.
67  */
68
69 BPatch_image::BPatch_image(BPatch_addressSpace *_addSpace) :
70    addSpace(_addSpace)
71 {
72    _srcType = BPatch_sourceProgram;
73 }
74
75 /*
76  * BPatch_image::BPatch_image
77  *
78  * Construct a BPatch_image.
79  */
80 BPatch_image::BPatch_image() :
81    addSpace(NULL)
82 {
83    _srcType = BPatch_sourceProgram;
84 }
85
86 /* 
87  * Cleanup the image's memory usage when done.
88  *
89  */
90 BPatch_image::~BPatch_image()
91 {
92    for (unsigned int i = 0; i < modlist.size(); i++) {
93       delete modlist[i];
94    }
95
96    for (unsigned j = 0; j < removed_list.size(); j++) {
97       delete removed_list[j];
98    }
99 }
100
101
102 /*
103  * getThr - Return the BPatch_thread
104  *
105  */
106 BPatch_thread *BPatch_image::getThrInt()
107 {
108    assert(addSpace->getType() == TRADITIONAL_PROCESS);
109    BPatch_process * bpTemp = dynamic_cast<BPatch_process *>(addSpace);
110
111    assert(bpTemp->threads.size() > 0);
112    return bpTemp->threads[0];
113 }
114
115 BPatch_process *BPatch_image::getProcessInt()
116 {
117    if (addSpace->getType() == TRADITIONAL_PROCESS)
118       return dynamic_cast<BPatch_process *>(addSpace);
119    else
120       return NULL;   
121 }
122
123 BPatch_addressSpace *BPatch_image::getAddressSpaceInt()
124 {
125    return addSpace;
126 }
127
128 /* 
129  * getSourceObj - Return the children (modules)
130  *
131  */
132 bool BPatch_image::getSourceObjInt(BPatch_Vector<BPatch_sourceObj *> &vect)
133 {
134    BPatch_Vector<BPatch_module *> *temp = getModules();
135    if (temp) {
136       vect = * (BPatch_Vector<BPatch_sourceObj *> *) temp;
137       return (true);
138    } else {
139       return (false);
140    }
141 }
142
143 /* 
144  * getObjParent - Return the parent (this is the top level so its null)
145  *
146  */
147
148 BPatch_sourceObj *BPatch_image::getObjParentInt()
149 {
150    return NULL;
151 }
152
153 /*
154  * BPatch_image::getProcedures
155  *
156  * Returns a list of all procedures in the image upon success, and NULL
157  * upon failure.
158  */
159
160 BPatch_Vector<BPatch_function *> *BPatch_image::getProceduresInt(bool incUninstrumentable)
161 {
162    BPatch_Vector<BPatch_function *> *proclist = new BPatch_Vector<BPatch_function *>;
163    bool some_succeeded = false;
164    if (proclist == NULL) return NULL;
165
166    BPatch_Vector<BPatch_module *> *mods = getModules();
167
168    for (unsigned int i = 0; i < (unsigned) mods->size(); i++) {
169       bool result = (*mods)[i]->getProcedures(*proclist, incUninstrumentable);
170       if (result)
171          some_succeeded = true;
172    }
173    if (!some_succeeded) {
174       delete proclist;
175       return NULL;
176    }
177    
178    return proclist;
179 }
180
181 bool BPatch_image::getProceduresInt(BPatch_Vector<BPatch_function*> &procs, bool incUninstrumentable)
182 {
183    bool some_succeeded = false;
184    BPatch_Vector<BPatch_module *> *mods = getModules();
185
186    for (unsigned int i = 0; i < (unsigned) mods->size(); i++) {
187       bool result = (*mods)[i]->getProcedures(procs, incUninstrumentable);
188       if (result)
189          some_succeeded = true;
190    }
191    return some_succeeded;
192 }
193
194
195 BPatch_Vector<BPatch_parRegion *> *BPatch_image::getParRegionsInt(bool incUninstrumentable)
196 {
197    BPatch_Vector<BPatch_function *> procList;
198    bool result = getProcedures(procList, incUninstrumentable);
199    if (!result)
200       return NULL;
201
202    BPatch_Vector<BPatch_parRegion *> *parRegionList = new BPatch_Vector<BPatch_parRegion *>;
203    if (parRegionList == NULL) return NULL;
204
205
206    for (unsigned int i=0; i < (unsigned) procList.size(); i++) {
207       int_function * intF = procList[i]->lowlevel_func();
208       const pdvector<int_parRegion *> intPR = intF->parRegions();
209
210       for (unsigned int j=0; j < (unsigned) intPR.size(); j++)
211       {
212          BPatch_parRegion * pR = new BPatch_parRegion(intPR[j], procList[i]);
213          parRegionList->push_back(pR);
214       }
215    }
216
217    return parRegionList;
218 }
219
220 /*
221  * BPatch_image::getGlobalVariables
222  *
223  * Returns a list of all variables in the image upon success, and NULL
224  * upon failure.
225  */
226 BPatch_Vector<BPatch_variableExpr *> *BPatch_image::getGlobalVariablesInt()
227 {
228    if (!addSpace)
229       return NULL;
230
231    BPatch_Vector<BPatch_variableExpr *> *varlist = new BPatch_Vector<BPatch_variableExpr *>;
232    if (!varlist) return NULL;
233
234    bool result = getVariablesInt(*varlist);
235    if (!result) {
236       delete varlist;
237       return NULL;
238    }
239    return varlist;
240 }
241
242 bool BPatch_image::getVariablesInt(BPatch_Vector<BPatch_variableExpr *> &vars)
243 {
244    bool some_succeeded = false;
245
246    if (!addSpace)
247       return false;
248
249    BPatch_Vector<BPatch_module *> mods;
250    getModules(mods);
251    
252    for (unsigned int m = 0; m < mods.size(); m++) {
253       BPatch_module *module = mods[m];
254       
255       bool result = module->getVariables(vars);
256       if (result)
257          some_succeeded = true;
258    }
259
260    return some_succeeded;
261 }
262
263 bool BPatch_image::setFuncModulesCallback(BPatch_function *bpf, void *data)
264 {
265    BPatch_image *img = (BPatch_image *) data;
266    if (bpf->getModule() == NULL && bpf->func->mod() != NULL) {
267       bpf->mod = img->findModule(bpf->func->mod()->fileName().c_str());
268    }
269
270    if ( bpf->getModule() == NULL ) {
271       char name[256];
272       fprintf(stderr, "Warning: bpf '%s' unclaimed, setting to DEFAULT_MODULE\n",
273             bpf->getName( name, 255 ) );
274       bpf->setModule( img->defaultModule );
275    }   
276    return true;
277 }
278
279 bool BPatch_image::getModulesInt(BPatch_Vector<BPatch_module *> &mods)
280 {
281    BPatch_Vector<BPatch_module *> *ret = getModulesInt();
282    if (!ret) {
283       return false;
284    }
285    mods = *ret;
286    return true;
287 }
288
289 BPatch_Vector<BPatch_module *> *BPatch_image::getModulesInt() 
290 {
291    pdvector<mapped_module *> modules;
292    std::vector<AddressSpace *> as;
293    addSpace->getAS(as);
294    
295    for (unsigned i=0; i<as.size(); i++) {
296       as[i]->getAllModules(modules);
297
298       // We may have created a singleton module already -- check to see that we 
299       // don't double-create
300       for (unsigned i = 0; i < modules.size(); i++ ) {
301          mapped_module *map_mod = modules[i];
302          findOrCreateModule(map_mod);
303       }
304    }
305
306    return &modlist;
307
308
309 /*
310  * BPatch_image::findModule
311  *
312  * Returns module with <name>, NULL if not found
313  */
314 BPatch_module *BPatch_image::findModuleInt(const char *name, bool substring_match) 
315 {
316    char buf[512];
317
318    if (!name) {
319       bperr("%s[%d]:  findModule:  no module name provided\n",
320             __FILE__, __LINE__);
321       return NULL;
322    }
323
324    BPatch_module *target = NULL;
325
326    for (unsigned int i = 0; i < modlist.size(); ++i) {
327       BPatch_module *mod = modlist[i];
328       assert(mod);
329       mod->getName(buf, 512); 
330       if (substring_match) { 
331          if (strstr(buf, name)) {
332             target = mod;
333             break;
334          }
335       }
336       else  {//exact match required
337          if (!strcmp(name, buf)) {
338             target = mod;
339             break;
340          }
341       }
342    }
343
344    if (target) 
345       return target;
346
347    // process::findModule does a wildcard match, not a substring match 
348
349    char *tmp = (char *) malloc(strlen(name) + 3);
350    if (substring_match)
351       sprintf(tmp, "*%s*", name); 
352    else 
353       sprintf(tmp, "%s", name);
354
355    std::vector<AddressSpace *> as;
356    addSpace->getAS(as);
357    
358    mapped_module *mod = NULL;
359    for (unsigned i=0; i<as.size(); i++) {
360       mod = as[i]->findModule(tmp,substring_match);
361       if (mod)
362          break;
363    }
364
365    free(tmp);
366    if (!mod) return false;
367
368    target = findOrCreateModule(mod);
369    return target;
370 }
371
372 /*
373  * BPatch_image::createInstPointAtAddr
374  *
375  * Returns a pointer to a BPatch_point object representing an
376  * instrumentation point at the given address.
377  *
378  * Returns the pointer to the BPatch_point on success, or NULL upon
379  * failure.
380  *
381  * address      The address that the instrumenation point should refer to.
382  */
383
384 BPatch_point *BPatch_image::createInstPointAtAddrInt(void *address)
385 {
386    return createInstPointAtAddr(address,NULL);
387 }
388
389 /*
390  * BPatch_image::createInstPointAtAddr
391  *
392  * Returns a pointer to a BPatch_point object representing an
393  * instrumentation point at the given address. If the BPatch_function
394  * argument is given it has to be the function that address belongs to or NULL.
395  * The function is used to bypass the function that the address belongs to
396  * The alternative argument is used to retrieve the point if the new point
397  * intersects with another already existing one.
398  *
399  * Returns the pointer to the BPatch_point on success, or NULL upon
400  * failure.
401  *
402  * address      The address that the instrumenation point should refer to.
403  */
404
405 BPatch_point *BPatch_image::createInstPointAtAddrWithAlt(void *address,
406       BPatch_point** alternative,
407       BPatch_function* bpf)
408 {
409    Address address_int = (Address) address;
410
411    unsigned i;
412
413    std::vector<AddressSpace *> as;
414    addSpace->getAS(as);
415    assert(as.size());   
416    AddressSpace *llAS = as[0];
417
418    int_function *func = NULL;
419
420    if (bpf) {
421       func = bpf->func;
422    }
423    else {
424       func = llAS->findFuncByAddr(address_int);
425    }
426
427    if (func == NULL) return NULL;
428
429    /* See if there is an instPoint at this address */
430    instPoint *p = NULL;
431
432    if ((p = func->findInstPByAddr(address_int))) {
433       return addSpace->findOrCreateBPPoint(NULL, p, BPatch_locInstruction);
434    }
435
436    /* Look in the regular instPoints of the enclosing function. */
437    /* This has an interesting side effect: "instrument the first
438       instruction" may return with "entry instrumentation", which can
439       have different semantics. */
440
441    // If it's in an uninstrumentable function, just return an error.
442    if (!func->isInstrumentable()) { 
443       return NULL;
444    }
445
446    const pdvector<instPoint *> entries = func->funcEntries();
447    for (unsigned t = 0; t < entries.size(); t++) {
448       assert(entries[t]);
449       if (entries[t]->match(address_int)) {
450          return addSpace->findOrCreateBPPoint(NULL, entries[t], BPatch_entry);
451       }
452    }
453
454    const pdvector<instPoint*> &exits = func->funcExits();
455    for (i = 0; i < exits.size(); i++) {
456       assert(exits[i]);
457       if (exits[i]->match(address_int)) {
458          return addSpace->findOrCreateBPPoint(NULL, exits[i], BPatch_exit);
459       }
460    }
461
462    const pdvector<instPoint*> &calls = func->funcCalls();
463    for (i = 0; i < calls.size(); i++) {
464       assert(calls[i]);
465       if (calls[i]->match(address_int))  {
466          return addSpace->findOrCreateBPPoint(NULL, calls[i], BPatch_subroutine);
467       }
468    }
469
470    if (alternative)
471       *alternative = NULL;
472
473    /* We don't have an instPoint for this address, so make one. */
474    instPoint *newInstP = instPoint::createArbitraryInstPoint(address_int, llAS, func);
475    if (!newInstP) return NULL;
476
477    return addSpace->findOrCreateBPPoint(NULL, newInstP, BPatch_locInstruction);
478 }
479
480 /*
481  * BPatch_image::findFunction
482  *
483  * Fills a vector with BPatch_function pointers representing all functions in
484  * the image with the given name.  Returns a pointer to the vector that was
485  * passed in on success, and NULL on error.
486  *
487  * name         The name of function to look up.
488  * funcs        The vector in which to place the results.
489  */
490
491 BPatch_Vector<BPatch_function*> *BPatch_image::findFunctionInt(const char *name, 
492       BPatch_Vector<BPatch_function*> &funcs, 
493       bool showError,
494       bool regex_case_sensitive,
495       bool incUninstrumentable)
496 {
497    std::vector<AddressSpace *> as;
498    addSpace->getAS(as);
499    assert(as.size());
500
501    if (NULL == strpbrk(name, REGEX_CHARSET)) {
502       //  usual case, no regex
503       pdvector<int_function *> foundIntFuncs;
504       for (unsigned i=0; i<as.size(); i++) {
505          as[i]->findFuncsByAll(std::string(name), foundIntFuncs);
506       }
507       if (!foundIntFuncs.size())
508       {
509          // Error callback...
510          if (showError) {
511             std::string msg = std::string("Image: Unable to find function: ") + 
512                std::string(name);
513             BPatch_reportError(BPatchSerious, 100, msg.c_str());
514          }
515          return NULL;
516       }
517       // We have a list; if we don't want to include uninstrumentable,
518       // scan and check
519       for (unsigned int fi = 0; fi < foundIntFuncs.size(); fi++) {
520          if (foundIntFuncs[fi]->isInstrumentable() || incUninstrumentable) {
521             BPatch_function *foo = addSpace->findOrCreateBPFunc(foundIntFuncs[fi], NULL);
522             funcs.push_back(foo);
523          }
524       }
525
526       if (funcs.size() > 0)
527          return &funcs;
528       if (showError) {
529          std::string msg = std::string("Image: Unable to find function: ") + 
530             std::string(name);
531          BPatch_reportError(BPatchSerious, 100, msg.c_str());
532       }
533       return NULL;
534    }
535
536 #if !defined(os_windows)
537    // REGEX falls through:
538    regex_t comp_pat;
539    int err, cflags = REG_NOSUB | REG_EXTENDED;
540
541    if ( !regex_case_sensitive )
542       cflags |= REG_ICASE;
543
544    //cerr << "compiling regex: " <<name<<endl;
545
546    if (0 != (err = regcomp( &comp_pat, name, cflags ))) {
547       char errbuf[80];
548       regerror( err, &comp_pat, errbuf, 80 );
549       if (showError) {
550          cerr << __FILE__ << ":" << __LINE__ << ":  REGEXEC ERROR: "<< errbuf << endl;
551          std::string msg = std::string("Image: Unable to find function pattern: ") 
552             + std::string(name) + ": regex error --" + std::string(errbuf);
553          BPatch_reportError(BPatchSerious, 100, msg.c_str());
554       }
555       // remove this line
556       cerr << __FILE__ << ":" << __LINE__ << ":  REGEXEC ERROR: "<< errbuf << endl;
557       return NULL;
558    }
559
560    // Regular expression search. This used to be handled at the image
561    // class level, but was moved up here to simplify semantics. We
562    // have to iterate over every function known to the process at some
563    // point, so it might as well be top-level. This is also an
564    // excellent candidate for a "value-added" library.
565
566    pdvector<int_function *> all_funcs;
567    for (unsigned i=0; i<as.size(); i++) {
568       as[i]->getAllFunctions(all_funcs);
569    }
570
571    for (unsigned ai = 0; ai < all_funcs.size(); ai++) {
572       int_function *func = all_funcs[ai];
573       // If it matches, push onto the vector
574       // Check all pretty names (and then all mangled names if 
575       // there is no match)
576       bool found_match = false;
577       unsigned piter, miter;
578       for (piter = 0; piter < func->prettyNameVector().size(); piter++) {
579          const string &pName = func->prettyNameVector()[piter];
580          int err;
581
582          if (0 == (err = regexec(&comp_pat, pName.c_str(), 1, NULL, 0 ))){
583             if (func->isInstrumentable() || incUninstrumentable) {
584                BPatch_function *foo = addSpace->findOrCreateBPFunc(func,NULL);
585                //BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
586                funcs.push_back(foo);
587             }
588             found_match = true;
589             break;
590          }
591       }
592       if (found_match) continue; // Don't check mangled names
593
594       for (miter = 0; miter < func->symTabNameVector().size(); miter++) {
595          const string &mName = func->symTabNameVector()[miter];
596          int err;
597
598          if (0 == (err = regexec(&comp_pat, mName.c_str(), 1, NULL, 0 ))){
599             if (func->isInstrumentable() || incUninstrumentable) {
600                BPatch_function *foo = addSpace->findOrCreateBPFunc(func,NULL);
601                //          BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
602                funcs.push_back(foo);
603             }
604             found_match = true;
605             break;
606          }
607       }
608    }
609
610    regfree(&comp_pat);
611
612    if (funcs.size() > 0) {
613       return &funcs;
614    } 
615
616    if (showError) {
617       std::string msg = std::string("Unable to find pattern: ") + std::string(name);
618       BPatch_reportError(BPatchSerious, 100, msg.c_str());
619    }
620 #endif
621    return NULL;
622 }
623
624 #ifdef IBM_BPATCH_COMPAT
625 //  a wrapper for IBM compatibility.  The function vector is assumed to be
626 //  allocated before calling.
627 BPatch_Vector<BPatch_function*> *BPatch_image::findFunctionPtr(
628       const char *name, BPatch_Vector<BPatch_function*> *funcs, bool showError,
629       bool regex_case_sensitive, bool incUninstrumentable)
630 {
631    return findFunction(name, *funcs, showError, regex_case_sensitive, incUninstrumentable);
632 }
633 #endif
634
635 /*
636  * BPatch_image::findFunction 2
637  *
638  * Fills a vector with BPatch_function pointers representing all functions in
639  * the image according to the user defined sieving function.  
640  * Returns a pointer to the vector that was passed in on success, and NULL on error.
641  * 
642  *
643  * bpsieve      User-provided boolean function used to determine inclusion in the
644  *              filtered set.
645  * user_data    a pointer to a user-defined data space for use by bpsieve
646  * funcs        The vector in which to place the results.
647  */
648
649    BPatch_Vector<BPatch_function *> *
650 BPatch_image::findFunctionWithSieve(BPatch_Vector<BPatch_function *> &funcs, 
651       BPatchFunctionNameSieve bpsieve,
652       void *user_data, int showError, 
653       bool incUninstrumentable)
654 {
655    pdvector<int_function *> all_funcs;
656    std::vector<AddressSpace *> as;
657    addSpace->getAS(as);
658    assert(as.size());
659
660    for (unsigned i=0; i<as.size(); i++)
661       as[i]->getAllFunctions(all_funcs);
662
663    for (unsigned ai = 0; ai < all_funcs.size(); ai++) {
664       int_function *func = all_funcs[ai];
665       // If it matches, push onto the vector
666       // Check all pretty names (and then all mangled names if there is no match)
667       bool found_match = false;
668
669       for (unsigned piter = 0; piter < func->prettyNameVector().size(); piter++) {
670          const string &pName = func->prettyNameVector()[piter];
671
672          if ((*bpsieve)(pName.c_str(), user_data)) {
673             if (func->isInstrumentable() || incUninstrumentable) {
674                BPatch_function *foo = addSpace->findOrCreateBPFunc(func,NULL);
675                //BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
676                funcs.push_back(foo);
677             }
678             found_match = true;
679             break;
680          }
681       }
682
683       if (found_match) continue; // Don't check mangled names
684
685 #if 0
686       // Apparently don't check mangled at all
687
688       for (unsigned miter = 0; miter < func->symTabNameVector().size(); miter++) {
689          const std::string &mName = func->symTabNameVector()[miter];
690          int err;
691
692          if (0 == (err = regexec(&comp_pat, mName.c_str(), 1, NULL, 0 ))){
693             if (func->isInstrumentable() || incUninstrumentable) {
694                BPatch_function *foo = proc->findOrCreateBPFunc(func, NULL);
695                funcs.push_back(foo);
696             }
697             found_match = true;
698             break;
699          }
700       }
701 #endif
702    }
703
704    if (funcs.size() > 0) {
705       return &funcs;
706    } 
707
708    if (showError) {
709       const char *msg = "No function matches for sieve provided";
710       BPatch_reportError(BPatchSerious, 100, msg);
711    }
712
713    return NULL;
714 }
715
716 /*
717  * BPatch_image::findFunctionP
718  *
719  * Finds a function based on an address in the mutatee
720  */
721
722 BPatch_function *BPatch_image::findFunctionInt(unsigned long addr)
723 {
724    std::vector<AddressSpace *> as;
725    addSpace->getAS(as);
726    assert(as.size());
727    int_function *ifunc = as[0]->findFuncByAddr(addr);
728    if (!ifunc)
729       return NULL;
730
731    return addSpace->findOrCreateBPFunc(ifunc,NULL);
732 }
733
734 bool BPatch_image::findFunctionInt(Dyninst::Address addr, 
735                                    BPatch_Vector<BPatch_function *> &funcs)
736 {
737    std::vector<AddressSpace *> as;
738    std::vector<int_function *> ifuncs;
739    bool result;
740
741    addSpace->getAS(as);
742    assert(as.size());
743
744    result = as[0]->findFuncsByAddr(addr, ifuncs);
745    if (!result)
746       return false;
747
748    assert(ifuncs.size());
749    for (unsigned i=0; i<ifuncs.size(); i++)
750    {
751       BPatch_function *bpfunc = addSpace->findOrCreateBPFunc(ifuncs[i], NULL);
752       funcs.push_back(bpfunc);
753    }
754
755    return true;
756 }
757
758
759 /*
760  * BPatch_image::findVariable
761  *
762  * Returns a BPatch_variableExpr* representing the given variable in the
763  * application image.  If no such variable exists, returns NULL.
764  *
765  * name         The name of the variable to look up.
766  *
767  * First look for the name with an `_' prepended to it, and if that is not
768  *   found try the original name.
769  */
770 BPatch_variableExpr *BPatch_image::findVariableInt(const char *name, 
771                                                    bool showError)
772 {
773     pdvector<int_variable *> vars;
774     std::vector<AddressSpace *> as;
775     int_variable *var = NULL;
776     AddressSpace *var_as = NULL;
777     
778     if (!addSpace)
779        return NULL;
780     
781     addSpace->getAS(as);
782
783     for (unsigned i=0; i<as.size(); i++) {
784        as[i]->findVarsByAll(name, vars);
785        if (vars.size()) {
786           var = vars[0];
787           var_as = as[i];
788           break;
789        }
790     }
791
792     if (!var) {
793        std::string under_name = std::string("_") + std::string(name);
794        for (unsigned i=0; i<as.size(); i++) {
795           as[i]->findVarsByAll(under_name, vars);
796           if (vars.size()) {
797              var = vars[0];
798              var_as = as[i];
799              break;
800           }
801        }
802     }
803        
804     if (!var) {
805        for (unsigned i=0; i<as.size(); i++) {
806           string defaultNamespacePref = as[i]->getAOut()->parse_img()->
807              getObject()->getDefaultNamespacePrefix();
808           string prefix_name = defaultNamespacePref + string(".") + string(name);
809           as[i]->findVarsByAll(prefix_name, vars);
810           if (vars.size()) {
811              var = vars[0];
812              var_as = as[i];
813              break;
814           }
815        }
816     }
817
818     if (!var) {
819        if (showError) {
820           string msg = std::string("Unable to find variable: ") + 
821              string(name);
822           showErrorCallback(100, msg);
823        }
824        return NULL;
825     }
826
827    BPatch_variableExpr *bpvar = addSpace->findOrCreateVariable(var);
828    assert(bpvar);
829    return bpvar;
830 }
831
832 //
833 // findVariable
834 //      scp     - a BPatch_point that defines the scope of the current search
835 //      name    - name of the variable to find.
836 //
837
838 BPatch_variableExpr *BPatch_image::findVariableInScope(BPatch_point &scp,
839                 const char *name)
840 {
841         // Get the function to search for it's local variables.
842         // XXX - should really use more detailed scoping info here - jkh 6/30/99
843         BPatch_function *func = const_cast<BPatch_function *> (scp.getFunction());
844
845         if (!func) 
846         {
847                 std::string msg = std::string("point passed to findVariable lacks a function\n address point type passed?");
848                 showErrorCallback(100, msg);
849                 return NULL;
850         }
851
852         AddressSpace *as = func->lladdSpace;
853
854         BPatch_localVar *lv = func->findLocalVar(name);
855
856         if (!lv) 
857         {
858                 // look for it in the parameter scope now
859                 lv = func->findLocalParam(name);
860         }
861
862         if (lv) 
863         {
864                 return new BPatch_variableExpr(addSpace, as, lv, lv->getType(), &scp); 
865         }
866
867         // finally check the global scope.
868         // return findVariable(name);
869
870         /* If we have something else to try, don't report errors on this failure. */
871         bool reportErrors = true;
872         char mangledName[100];
873         func->getName( mangledName, 100 );
874         char * lastScoping = NULL;      
875
876         if ( strrchr( mangledName, ':' ) != NULL ) 
877         { 
878                 reportErrors = false; 
879         }
880
881         BPatch_variableExpr * gsVar = findVariable( name, reportErrors );
882
883         if ( gsVar == NULL ) 
884         {
885                 /* Try finding it with the function's scope prefixed. */
886
887                 if ( (lastScoping = strrchr( mangledName, ':' )) != NULL ) 
888                 {
889                         * (lastScoping + sizeof(char)) = '\0';
890                         char scopedName[200];
891                         memmove( scopedName, mangledName, strlen( mangledName ) );
892                         memmove( scopedName + strlen( mangledName ), name, strlen( name ) );
893                         scopedName[ strlen( mangledName ) + strlen( name ) ] = '\0';
894                         bperr( "Searching for scoped name '%s'\n", scopedName );
895                         gsVar = findVariable( scopedName ); 
896                 }
897         }
898         return gsVar;
899 }
900
901 /*
902  * BPatch_image::findType
903  *
904  * Returns a BPatch_type* representing the named type.  If no such type
905  * exists, returns NULL.
906  *
907  * name         The name of type to look up.
908  */
909
910 BPatch_type *BPatch_image::findTypeInt(const char *name)
911 {
912     BPatch_type *type;
913
914     assert(BPatch::bpatch != NULL);
915
916     // XXX - should this stuff really be by image ??? jkh 3/19/99
917     BPatch_Vector<BPatch_module *> *mods = getModules();
918     for (int m = mods->size() -1; m >= 0; m--) {
919         BPatch_module *module = (*mods)[m];
920         type = module->getModuleTypes()->findType(name);
921         if (type) {
922            return type;
923         }
924     }
925
926     // check the default base types
927     type = BPatch::bpatch->stdTypes->findType(name);
928     if (type)  {
929       return type;
930     }
931     // check the API types of last resort
932     type = BPatch::bpatch->APITypes->findType(name);
933
934     return type;
935
936 }
937
938 bool BPatch_image::getSourceLinesInt(unsigned long addr, 
939                                      BPatch_Vector<BPatch_statement> &lines )
940 {
941    unsigned int originalSize = lines.size();
942    BPatch_Vector< BPatch_module * > * modules = getModules();
943
944    /* Iteratate over the modules, looking for addr in each. */
945
946    for (unsigned int i = 0; i < modules->size(); i++ ) 
947    {
948       BPatch_module *m = (*modules)[i];
949       //  address-to-offset conversion done in module routine 
950       m->getSourceLinesInt(addr,lines);
951    }
952
953    if ( lines.size() != originalSize ) 
954    {
955       return true; 
956    }    
957
958    //fprintf(stderr, "%s[%d]:  fail to getSourceLines for addr %lu\n", FILE__, __LINE__, addr);
959
960    return false;
961 } /* end getSourceLines() */
962
963 bool BPatch_image::getAddressRangesInt( const char * lineSource, 
964       unsigned int lineNo, 
965       std::vector< std::pair<unsigned long, unsigned long> > & ranges ) 
966 {
967    unsigned int originalSize = ranges.size();
968
969    //  First check to see if we can find the named module
970    //  If so, use it for the lookup
971
972    BPatch_module *target_mod = findModuleInt(lineSource, false);
973
974    if (target_mod)
975    {
976       target_mod->getAddressRanges(lineSource, lineNo, ranges);
977       if ( ranges.size() != originalSize ) 
978       {
979          return true; 
980       }
981    }
982
983    //  If we cannot find the given module, try (perhaps against all hope)
984    //  looking in all the modules sequentially
985
986    BPatch_Vector< BPatch_module * > * modules = getModules();
987
988    // Iteratate over the modules, looking for ranges in each. 
989
990    for ( unsigned int i = 0; i < modules->size(); i++ ) 
991    {
992       BPatch_module *m = (*modules)[i];
993       m->getAddressRanges(lineSource, lineNo, ranges);
994    }
995
996    if ( ranges.size() != originalSize ) 
997    {
998       return true; 
999    }
1000
1001    dwarf_printf("%s[%d]:  getAddressRanges failing\n", FILE__, __LINE__);
1002    return false;
1003
1004
1005
1006 char *BPatch_image::getProgramNameInt(char *name, unsigned int len) 
1007 {
1008    std::vector<AddressSpace*> as;
1009    addSpace->getAS(as);
1010    AddressSpace *aout = as[0];
1011
1012    if (!aout->mappedObjects().size()) {
1013       strncpy(name, "<no program defined>", len);
1014    }
1015
1016    const char *imname =  aout->getAOut()->fullName().c_str();
1017    if (NULL == imname) imname = "<unnamed image>";
1018
1019    strncpy(name, imname, len);
1020    return name;
1021 }
1022
1023 char *BPatch_image::getProgramFileNameInt(char *name, unsigned int len)
1024 {
1025    std::vector<AddressSpace*> as;
1026    addSpace->getAS(as);
1027    AddressSpace *aout = as[0];
1028
1029    if (!aout->mappedObjects().size()) {
1030       // No program defined yet
1031       strncpy(name, "<no program defined>", len);
1032    }
1033
1034    const char *imname =  aout->getAOut()->fileName().c_str();
1035    if (NULL == imname) imname = "<unnamed image file>";
1036
1037    strncpy(name, imname, len);
1038    return name;
1039 }
1040
1041 #ifdef IBM_BPATCH_COMPAT
1042 char *BPatch_image::programNameInt(char *name, unsigned int len) 
1043 {
1044    return getProgramName(name, len);
1045 }
1046
1047 int  BPatch_image::lpTypeInt() 
1048 {
1049    switch(addSpace->getAS()->getAddressWidth()) {
1050       case 4: return LP32; break;
1051       case 8: return LP64; break;
1052       default: return UNKNOWN_LP; break;
1053    }
1054 };
1055 #endif
1056
1057 BPatch_module *BPatch_image::findModule(mapped_module *base) 
1058 {
1059    // As below, but don't create if none already exists
1060
1061    BPatch_module *bpm = NULL;
1062    for (unsigned j = 0; j < modlist.size(); j++) {
1063       if (modlist[j]->lowlevel_mod() == base) {
1064          bpm = modlist[j];
1065          break;
1066       }
1067    }
1068    return bpm;
1069 }
1070
1071 BPatch_module *BPatch_image::findOrCreateModule(mapped_module *base) 
1072 {
1073    BPatch_module *bpm = findModule(base);
1074    
1075    if (bpm == NULL) {
1076       bpm = new BPatch_module( addSpace, base->proc(), base, this );
1077       modlist.push_back( bpm );
1078    }
1079    assert(bpm != NULL);
1080    return bpm;
1081 }
1082
1083
1084 /* This function should only be invoked when regionStart and regionEnd
1085  * have been verified as not conflicting with existing mapped objects,
1086  * and when it has also been verified that all elements of
1087  * funcEntryAddrs lie between the region regionStart and regionEnd
1088  */
1089 BPatch_module *parseRegion(BPatch_process *bpProc, 
1090                            const Address regionStart, const Address regionEnd, 
1091                            const vector<Address> &funcEntryAddrs, 
1092                            const string *namePrefix,
1093                            Address loadAddress, 
1094                            bool parseGaps = false)
1095 {
1096     // Copy the region to a temp file
1097     void *regionBuf = malloc(regionEnd - regionStart);
1098     if (!bpProc->lowlevel_process()->readDataSpace
1099           ((void*)regionStart, regionEnd-regionStart, regionBuf, false)) {
1100         fprintf(stderr, "%s[%d]: Failed to read from region [%lX %lX]\n",
1101                 __FILE__, __LINE__,(long)regionStart, 
1102                 (long)regionEnd);
1103     }
1104     char regName[64];
1105     if (namePrefix) {
1106         sprintf(regName, "%s_%lX_%lX", namePrefix->c_str(), regionStart, regionEnd);
1107     } else {
1108         sprintf(regName, "MemRegion_%lX_%lX", regionStart, regionEnd);
1109     }
1110     FILE *regionFD = fopen(regName, "wb");
1111     if (regionFD == NULL) {
1112         fprintf(stderr,"%s[%d]Was unable to open file %s for writing\n",
1113                 FILE__, __LINE__, regName);
1114         return NULL;
1115     }
1116     unsigned writeBytes = fwrite(regionBuf, 1, regionEnd-regionStart, regionFD);
1117     if (writeBytes != regionEnd-regionStart) {
1118         fprintf(stderr, "%s[%d] Wrote 0x%x bytes to file %s"
1119                 "when writing region [%lx %lx] to disk\n",
1120                 FILE__,__LINE__,writeBytes, regName, (long)regionStart, (long)regionEnd);
1121     }
1122     fclose(regionFD);
1123     free(regionBuf);
1124
1125     // create a fileDescriptor and mapped_object and add region as shared object
1126     fileDescriptor fdesc;
1127     if (loadAddress == 0) {
1128         loadAddress = regionStart;
1129     }
1130     fdesc = fileDescriptor(regName, regionStart - loadAddress, 
1131                            regionEnd - regionStart, loadAddress);
1132     mapped_object *obj = mapped_object::createMappedObject
1133         (fdesc, bpProc->lowlevel_process(), parseGaps);
1134
1135     // add function stubs for the entry points we found
1136     for (unsigned int i=0; i < funcEntryAddrs.size(); i++) {
1137         obj->parse_img()->addFunctionStub(funcEntryAddrs[i] - loadAddress);
1138     }
1139
1140     // force mapped_object to be parsed and return BPatch_module for it
1141     obj->analyze(); 
1142     bpProc->lowlevel_process()->addASharedObject(obj);
1143     pdvector<mapped_module*> mods = obj->getModules();
1144     if (mods.size() == 0) {
1145         fprintf(stderr,"%s[%d] Failed to create module for region [%lx %lx]\n",
1146                 FILE__, __LINE__, regionStart, regionEnd);
1147         return NULL;
1148     }
1149     return new BPatch_module(bpProc, mods[0]->proc(), mods[0], bpProc->getImage());
1150 }
1151
1152 /* Object re-parsed, if new modules need to be created in order to do
1153  * so they are added to the affectedModules vector.  This function should
1154  * only be invoked if all funcEntryAddrs lie within the boundaries of
1155  * the module.  A true return value means that an EXISTING object was
1156  * re-parsed via the addition of new code, a false return value means
1157  * that this was not the case.  
1158 */
1159 bool reparseObject(BPatch_addressSpace *addSpace, 
1160                    BPatch_Vector<BPatch_module*> &affectedModules,
1161                    mapped_object *obj, vector<Address> &funcEntryAddrs)
1162 {
1163     // parse all functions with valid entry addresses in the module
1164     bool reparsedObject = false;
1165     Address baseAddress = obj->parse_img()->desc().loadAddr();
1166     vector<Address>::iterator curEntry = funcEntryAddrs.begin();
1167     Region *reg;
1168     vector<image_func*> regFuncs;
1169     while (curEntry != funcEntryAddrs.end()) {
1170         reg = obj->parse_img()->getObject()->findEnclosingRegion
1171             ((*curEntry)-baseAddress);
1172         // if the address is in some region of the binary
1173         // and isCode is true, meaning that that code was mapped into
1174         // the binary from disk, analyze the function entry
1175         if (reg != NULL && obj->parse_img()->isCode((*curEntry) - baseAddress)) {
1176             image_func *imgfunc = obj->parse_img()->addFunctionStub
1177                 ((*curEntry) - baseAddress);
1178             regFuncs.clear();
1179             regFuncs.push_back(imgfunc);
1180             obj->analyzeNewFunctions(&regFuncs);
1181             curEntry = funcEntryAddrs.erase(curEntry);
1182             reparsedObject = true;
1183         } else {
1184             curEntry++;
1185         }
1186     }
1187
1188     // return now if there are no more unresolved funcEntryAddrs
1189     if (funcEntryAddrs.size() == 0) {
1190         return reparsedObject;
1191     }
1192     // get the binary's code regions from symtabAPI or return 
1193     std::vector<Region*> regions;
1194     if( ! obj->parse_img()->getObject()->getCodeRegions(regions) ) {
1195         fprintf(stderr,"%s[%d] Found no code regions for object %s\n", 
1196                 __FILE__,__LINE__, obj->parse_img()->pathname().c_str());
1197         return false;
1198     }
1199     vector<Address> regEntries;
1200     // for each region, determine which entry addrs lie within it
1201     for (unsigned ridx=0; funcEntryAddrs.size() && ridx < regions.size(); ridx++) { 
1202         regEntries.clear();
1203         // if entry point in region, pass from funcEntryAddrs to regEntries
1204         curEntry = funcEntryAddrs.begin();
1205         while (curEntry != funcEntryAddrs.end()) {
1206             if ((*curEntry) >=(regions[ridx]->getRegionAddr() + baseAddress) &&
1207                 (*curEntry) < (regions[ridx]->getRegionAddr() + 
1208                                regions[ridx]->getMemSize() + baseAddress)) {
1209                 regEntries.push_back(*curEntry);
1210                 curEntry = funcEntryAddrs.erase(curEntry);
1211             } else {
1212                 curEntry++;
1213             }
1214         }
1215         if (regEntries.size()) {
1216             // This case only happens on PE binaries.  We would like
1217             // to re-parse the region, but we already know that the
1218             // address lies in an unmapped memory region and SymtabAPI
1219             // doesn't have memory allocated for those addresses.  If
1220             // there's code here it didn't come from the binary on
1221             // disk, so the region was overwritten dynamically and the
1222             // data will have to be fetched from memory.
1223             Address regionStart;
1224             Address regionSize;
1225             unsigned long rawDataSize = regions[ridx]->getDiskSize();
1226             if (rawDataSize == 0 || regions[ridx]->getPtrToRawData() == NULL) {
1227                 // Case 1: There is no allocated memory for the region
1228                 // Set rawDataPtr for the region to a newly malloc'ed
1229                 // region and trigger parsing on the region.  
1230                 regionStart = regions[ridx]->getRegionAddr() + baseAddress;
1231                 regionSize = regions[ridx]->getMemSize();
1232                 void* regBuf = malloc (regionSize);
1233                 if (!((BPatch_process*)addSpace)->lowlevel_process()->
1234                     readDataSpace((void*)regionStart, regionSize, regBuf, true)) {
1235                     fprintf(stderr, "%s[%d] Failed to read from region [%lX %lX]\n",
1236                             __FILE__, __LINE__,(long)regions[ridx]->getRegionAddr(), 
1237                             regions[ridx]->getMemSize());
1238                     free(regBuf);
1239                     continue;
1240                 }
1241                 regions[ridx]->setPtrToRawData(regBuf,regions[ridx]->getMemSize());
1242                 curEntry = regEntries.begin();
1243                 regFuncs.clear();
1244                 while (curEntry != regEntries.end()) {
1245                     image_func *imgfunc = obj->parse_img()->addFunctionStub
1246                         ((*curEntry) - baseAddress);
1247                     regFuncs.push_back(imgfunc);
1248                     curEntry++;
1249                 }
1250                 obj->analyzeNewFunctions(&regFuncs);
1251                 reparsedObject = true;
1252             } else {
1253                 // Case 2: The points lie past the end of mapped region memory
1254                 // Create a new module corresponding to the gap between
1255                 // the end of the mapped memory for the region and the
1256                 // end of the region boundary, and parse it. 
1257                 // KEVINTODO: a better approach for this case would be to
1258                 // malloc a new region and copy over the mapped part and
1259                 // grab the rest from the mutatee's address space, but I'm
1260                 // not sure what would happen if I did that.
1261                 regionStart = baseAddress + regions[ridx]->getDiskSize();
1262                 regionSize = baseAddress + regions[ridx]->getMemSize()
1263                     - regionStart;
1264                 BPatch_module * mod = parseRegion((BPatch_process*)addSpace, 
1265                                                   regionStart,
1266                                                   regionStart + regionSize,
1267                                                   regEntries,
1268                                                   &obj->parse_img()->desc().file(),
1269                                                   obj->parse_img()->desc().loadAddr());
1270                 affectedModules.push_back(mod);
1271             }
1272         }
1273     }
1274     return reparsedObject;
1275 }
1276
1277 /* This function is only called when functionEntryAddrs contains
1278  * entries that do not overlap any existing mapped_object.  The
1279  * function's implementation depends on the second assumption.
1280  * Searches /proc for regions that might have mapped in.  The linker
1281  * tables changes are immediately handled and the mapped object list
1282  * gets updated, so we don't need to search for them.
1283  */
1284 #if defined(os_linux) //search /proc for regions
1285 void findNewEnclosingRegions(BPatch_Vector<Address> &funcEntryAddrs, 
1286                           vector<Address> &regionStartVec, 
1287                           vector<Address> &regionEndVec, 
1288                           vector<vector<Address> > &regionEntryPoints,
1289                           vector<string*> &regionNames, 
1290                           process *proc)
1291 {
1292     vector<Address>::iterator curEntry;
1293     unsigned maps_size=0; 
1294     map_entries *maps = getLinuxMaps(proc->getPid(), maps_size);
1295     if (maps) {
1296         for (unsigned i=0; i < maps_size; i++) {
1297             curEntry = funcEntryAddrs.begin();
1298             bool firstEntryInRegion = true;
1299             while (curEntry != funcEntryAddrs.end()) {
1300                 if (maps[i].start <= (*curEntry) &&
1301                     maps[i].end > (*curEntry)) {
1302                     if (firstEntryInRegion) {
1303                         regionStartVec.push_back(maps[i].start);
1304                         regionEndVec.push_back(maps[i].end);
1305                         regionEntryPoints.push_back(vector<Address>());
1306                         regionNames.push_back(new string(maps[i].path));
1307                         firstEntryInRegion = false;
1308                     }
1309                     regionEntryPoints.back().push_back(*curEntry);
1310                     curEntry = funcEntryAddrs.erase(curEntry);
1311                 }
1312                 else {
1313                     curEntry++;
1314                 }
1315             }
1316         }
1317         free(maps);
1318     }
1319     return;
1320 }
1321 #else
1322 void findNewEnclosingRegions(BPatch_Vector<Address> &, 
1323                              vector<Address> &,
1324                              vector<Address> &,
1325                              vector<vector<Address> > &,
1326                              vector<string*> &,
1327                              process *)
1328 {
1329 }
1330 #endif
1331
1332 /* BPatch_image::parseNewFunctions
1333  *
1334  * Uses function entry addresses to trigger the parsing of new
1335  * functions.  It may re-trigger parsing on existing modules or create
1336  * new ones to be parsed. 
1337  *
1338  * (full description in ../h/BPatch_image.h)
1339  */
1340 bool BPatch_image::parseNewFunctionsInt
1341      (BPatch_Vector<BPatch_module*> &affectedModules, 
1342       const BPatch_Vector<Dyninst::Address> &funcEntryAddrs)
1343 {
1344     if (!addSpace->getType() == TRADITIONAL_PROCESS) {
1345         fprintf(stderr,"%s[%d] ERROR: parseNewFunctions has only been "
1346                 "implemented for live processes\n", __FILE__, __LINE__);
1347         return false;
1348     }
1349     if (funcEntryAddrs.size() == 0) {
1350         fprintf(stderr,"%s[%d] parseNewFunctions requires a non-empty vector "
1351                 "of function entry points\n", __FILE__, __LINE__);
1352         return false;
1353     }
1354
1355     std::vector<AddressSpace*> asv;
1356     addSpace->getAS(asv);
1357     AddressSpace *as = asv[0];
1358     pdvector<mapped_object *> allobjs = as->mappedObjects();
1359
1360     // group funcEntryAddrs by the mapped_objects that they fit into
1361     vector<Address> funcEntryAddrs_(funcEntryAddrs); // make an editable copy
1362     vector<Address>::iterator curEntry;
1363     vector<Address> objEntries;
1364     for (unsigned int i=0; i < allobjs.size() && funcEntryAddrs_.size(); i++) { 
1365         image *curImg = allobjs[i]->parse_img();
1366         // determine region start/end boundaries
1367         Address regStart, regEnd;
1368         Address baseAddress = curImg->desc().loadAddr();
1369         // iterate through executable regions
1370         std::vector<Region*> regions;
1371         if( ! curImg->getObject()->getCodeRegions(regions) ) {
1372             fprintf(stderr,"%s[%d] Found no code regions for object %s\n", 
1373                     __FILE__,__LINE__, curImg->pathname().c_str());
1374             break;
1375         }
1376         std::vector<Region *>::const_iterator curreg = regions.begin();
1377         while(curreg != regions.end() && funcEntryAddrs_.size()) {
1378             regStart = baseAddress + (*curreg)->getRegionAddr();
1379             regEnd = regStart + (*curreg)->getMemSize();
1380             // iterate through func entry addrs
1381             curEntry = funcEntryAddrs_.begin();
1382             while (curEntry != funcEntryAddrs_.end()) {
1383                 if ((*curEntry) >= regStart && (*curEntry) < regEnd) {
1384                     objEntries.push_back(*curEntry);
1385                     curEntry = funcEntryAddrs_.erase(curEntry);
1386                 } else {
1387                     curEntry++;
1388                 }
1389             }
1390             curreg++;
1391         }
1392         // re-parse object if it contains entry points
1393         if (objEntries.size()) {
1394             if (reparseObject(addSpace, affectedModules, 
1395                               allobjs[i], objEntries)) {
1396                 pdvector<mapped_module*> mods = allobjs[i]->getModules();
1397                 //reparseObject adds all new functions to mods[0]
1398                 // since that's what image::addFunctionStub does
1399                 affectedModules.push_back(findOrCreateModule(mods[0]));
1400             }
1401             objEntries.clear();
1402         }
1403     }
1404     // if entry points left over, find regions that contain them
1405     // and parse each region
1406     if (funcEntryAddrs_.size()) {
1407         vector<Address> regionStartVec, regionEndVec;
1408         vector<vector<Address> > regionEntries;
1409         vector<string*> regionNames;
1410         findNewEnclosingRegions(funcEntryAddrs_, 
1411                              regionStartVec, 
1412                              regionEndVec, 
1413                              regionEntries, 
1414                              regionNames,
1415                              (process*)as);
1416         for (unsigned ridx=0; ridx < regionStartVec.size(); ridx++) {
1417             BPatch_module *mod = parseRegion((BPatch_process*)addSpace, 
1418                                              regionStartVec[ridx], 
1419                                              regionEndVec[ridx],
1420                                              regionEntries[ridx],
1421                                              regionNames[ridx],0);
1422             if (mod) {
1423                 affectedModules.push_back(mod);
1424             }
1425             free(regionNames[ridx]);
1426             regionNames[ridx] = NULL;
1427         }
1428     }
1429     if (affectedModules.size() == 0) {
1430         return false;
1431     }
1432     return true;
1433 }
1434
1435 // Merges unresolved control flow vectors of all mapped objects return
1436 // the merged vector of all unresolved control flow do this by
1437 // grabbing one module per mapped object, and calling
1438 // BPatch_module::getUnresolvedControlFlow on that module
1439 BPatch_Vector<BPatch_point *> *BPatch_image::getUnresolvedControlFlowInt()
1440 {
1441    unresolvedCF.clear();
1442    pdvector<mapped_object *> objs;
1443    
1444    std::vector<AddressSpace *> asv;
1445    addSpace->getAS(asv);
1446    for (unsigned i=0; i<asv.size(); i++) {
1447       const pdvector<mapped_object *> &mobjs = asv[i]->mappedObjects();
1448       for (unsigned j=0; j<mobjs.size(); j++) {
1449          objs.push_back(mobjs[j]);
1450       }
1451    }
1452
1453    for (unsigned i=0; i < objs.size(); i++) {
1454       pdvector<mapped_module *> mods = objs[i]->getModules();
1455       if (mods.size()) {
1456          BPatch_Vector<BPatch_point*> *badCF = 
1457              findOrCreateModule(mods[0])->getUnresolvedControlFlow();
1458          for (unsigned j=0; j < badCF->size(); j++) {
1459             unresolvedCF.push_back((*badCF)[j]);
1460          }
1461       }
1462    }
1463    return &unresolvedCF;
1464 }
1465
1466 void BPatch_image::removeAllModules()
1467 {
1468    BPatch_Vector<BPatch_module *>::iterator i;
1469    for (i = modlist.begin(); i != modlist.end(); i++)
1470    {
1471       (*i)->handleUnload();
1472    }
1473    modlist.clear();
1474 }
1475
1476 void BPatch_image::removeModule(BPatch_module *mod) 
1477 {
1478 #if !defined(USE_DEPRECATED_BPATCH_VECTOR)
1479    modlist.erase(std::find(modlist.begin(),
1480             modlist.end(),
1481             mod));
1482 #else
1483    for (unsigned j = 0; j < modlist.size(); j++) {
1484       if (modlist[j] == mod) {
1485          modlist.erase(j);
1486       }
1487    }
1488 #endif
1489    mod->handleUnload();
1490 }
1491
1492 bool BPatch_image::readStringInt(BPatch_variableExpr *expr, std::string &str,
1493                                  unsigned size_limit)
1494 {
1495    const BPatch_type *type = expr->getType();
1496    if (!type) {
1497       bperr("String read attempted on variable with no type information");
1498       return false;
1499    }
1500    
1501    Address addr = 0x0;
1502    if (type->getDataClass() == BPatch_dataPointer) {
1503       void *value;
1504       expr->readValue(&value);
1505       addr = (Address) value;
1506    }
1507    else if (type->getDataClass() == BPatch_dataArray) {
1508       addr = (Address) expr->getBaseAddr();
1509    }
1510    else {
1511       bperr("String read failed on variable with unexpected type");
1512       return false;
1513    }
1514    if (!addr)
1515       return false;
1516
1517    return readString(addr, str, size_limit);
1518 }
1519
1520
1521 bool BPatch_image::readStringInt(Address addr, std::string &str, unsigned size_limit)
1522 {
1523    char *buffer = NULL;
1524    unsigned buffer_offset = 0;
1525    unsigned buffer_size = 0;
1526    bool result;
1527    bool should_continue = false;
1528
1529    BPatch_process *proc = dynamic_cast<BPatch_process *>(getAddressSpace());
1530    if (!proc) {
1531       //Only works with dynamic processes;
1532       return false;
1533    }
1534    if (proc && !proc->isStoppedInt()) {
1535       should_continue = true;
1536       proc->stopExecution();
1537    }
1538
1539    std::vector<AddressSpace *> asv;
1540    getAddressSpace()->getAS(asv);
1541    AddressSpace *as = asv[0];
1542    assert(as);
1543
1544    unsigned word_size = as->getAddressWidth();
1545    assert(word_size == 4 || word_size == 8);
1546    
1547    Address start_word = (word_size == 4) ? (addr & ~0x3) : (addr & ~0x7);
1548    unsigned start_offset = addr - start_word;
1549
1550    for (;;) {
1551       if (!buffer) {
1552          buffer_size = 256;
1553          buffer = (char *) malloc(buffer_size);
1554          assert(buffer);
1555       }
1556       if (buffer_offset + word_size + 1 > buffer_size) {
1557          buffer_size *= 2;
1558          buffer = (char *) realloc(buffer, buffer_size);
1559          assert(buffer);
1560       }
1561
1562       result = as->readDataSpace((void *) (start_word + buffer_offset), word_size, 
1563                                  buffer + buffer_offset, false);
1564       if (!result) {
1565          signal_printf("[%s:%u] - ERROR reading address %x for string\n",
1566                        FILE__, __LINE__, start_word + buffer_offset);
1567          bperr("Error reading from target process");
1568          goto done;
1569       }
1570
1571       buffer_offset += word_size;
1572
1573       if (size_limit && 
1574           size_limit < buffer_offset - start_offset) {
1575          buffer[size_limit + start_offset] = '\0';
1576          signal_printf("[%s:%u] - WARN string read at %x exceeded size limit of %d",
1577                        FILE__, __LINE__, addr, size_limit);
1578          bpwarn("String read exceeded size limit");
1579          break;
1580       }
1581
1582       bool done = false;
1583       for (unsigned i=1; i<=word_size; i++) {
1584          if (buffer_offset-i < addr-start_word)
1585             continue;
1586          if (buffer[buffer_offset-i] == '\0') {
1587             done = true;
1588             break;
1589          }
1590       }
1591       if (done)
1592          break;
1593    }
1594
1595    str = buffer + start_offset;
1596    result = true;
1597
1598  done:
1599    if (buffer)
1600       free(buffer);
1601    if (should_continue) {
1602       assert(proc);
1603       proc->continueExecution();
1604    }
1605    
1606    return result;
1607 }
1608