mods/additions largely under the USE_STL_VECTOR and IBM_BPATCH_COMPAT flags
[dyninst.git] / dyninstAPI / src / BPatch_image.C
1 /*
2  * Copyright (c) 1996 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: BPatch_image.C,v 1.34 2002/03/19 22:57:20 jaw Exp $
43
44 #define BPATCH_FILE
45
46 #include <stdio.h>
47 #include <assert.h>
48 #include <string.h>
49
50 #include "process.h"
51 #include "symtab.h"
52 #include "instPoint.h"
53
54 #include "BPatch.h"
55 #include "BPatch_image.h"
56 #include "BPatch_type.h"
57 #include "BPatch_collections.h"
58 #include "LineInformation.h"
59 #include "ast.h"
60
61 //
62 // We made this a seperate class to allow us to only expose a pointer to
63 //    it in the public header files of the dyninst API.  This keeps 
64 //    dictionary_hash and other internal dyninst things hidden.  The
65 //    things we do decouple interface from implementation! - jkh 8/28/99
66 //
67 class AddrToVarExprHash {
68     public:
69         AddrToVarExprHash(): hash(addrHash) { }
70         dictionary_hash <Address, BPatch_variableExpr*> hash;
71 };
72
73 /*
74  * BPatch_image::BPatch_image
75  *
76  * Construct a BPatch_image for the given process.
77  */
78
79 BPatch_image::BPatch_image(process *_proc) : proc(_proc)
80 {
81     modlist = NULL;
82
83     AddrToVarExpr = new AddrToVarExprHash();
84
85     _srcType = BPatch_sourceProgram;
86 }
87
88 /*
89  * BPatch_image::BPatch_image
90  *
91  * Construct a BPatch_image.
92  */
93 BPatch_image::BPatch_image() : proc(NULL), modlist(NULL) 
94 {
95     AddrToVarExpr = new AddrToVarExprHash();
96
97     _srcType = BPatch_sourceProgram;
98 }
99
100 /* 
101  * Cleanup the image's memory usage when done.
102  *
103  */
104 BPatch_image::~BPatch_image()
105 {
106     // modules are shared by multuple programs, don't delete them
107     // for (unsigned int i = 0; i < modlist->size(); i++) {
108          // delete (*modlist)[i];
109     // }
110
111     delete AddrToVarExpr;
112 }
113
114 /* 
115  * getSourceObj - Return the children (modules)
116  *
117  */
118 bool BPatch_image::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &vect)
119 {
120     BPatch_Vector<BPatch_module *> *temp =  getModules();
121     if (temp) {
122        vect = * (BPatch_Vector<BPatch_sourceObj *> *) temp;
123        return (true);
124     } else {
125         return (false);
126     }
127 }
128
129 /* 
130  * getObjParent - Return the parent (this is the top level so its null)
131  *
132  */
133 BPatch_sourceObj *BPatch_image::getObjParent()
134 {
135     return NULL;
136 }
137
138 /*
139  * BPatch_image::getProcedures
140  *
141  * Returns a list of all procedures in the image upon success, and NULL
142  * upon failure.
143  */
144 BPatch_Vector<BPatch_function *> *BPatch_image::getProcedures()
145 {
146     BPatch_Vector<BPatch_function *> *proclist =
147         new BPatch_Vector<BPatch_function *>;
148
149     if (proclist == NULL) return NULL;
150
151     // XXX Also, what should we do about getting rid of this?  Should
152     //     the BPatch_functions already be made and kept around as long
153     //     as the process is, so the user doesn't have to delete them?
154     BPatch_Vector<BPatch_module *> *mods = getModules();
155
156     for (unsigned int i = 0; i < (unsigned) mods->size(); i++) {
157         BPatch_Vector<BPatch_function *> *funcs = (*mods)[i]->getProcedures();
158         for (unsigned int j=0; j < (unsigned) funcs->size(); j++) {
159             proclist->push_back((*funcs)[j]);
160         }
161     }
162
163     return proclist;
164 }
165
166
167 BPatch_variableExpr *BPatch_image::createVarExprByName(BPatch_module *mod, const char *name)
168 {
169     Symbol syminfo;
170     BPatch_type *type;
171     
172     type = mod->moduleTypes->globalVarsByName[name];
173     assert(type);
174     if (!proc->getSymbolInfo(name, syminfo)) {
175         printf("unable to find variable %s\n", name);
176     }
177     BPatch_variableExpr *var = AddrToVarExpr->hash[syminfo.addr()];
178     if (!var) {
179         var = new BPatch_variableExpr( (char *)name, proc, 
180             (void *)syminfo.addr(), (const BPatch_type *) type);
181         AddrToVarExpr->hash[syminfo.addr()] = var;
182     }
183     return var;
184 }
185
186
187 /*
188  * BPatch_image::getProcedures
189  *
190  * Returns a list of all procedures in the image upon success, and NULL
191  * upon failure.
192  */
193 BPatch_Vector<BPatch_variableExpr *> *BPatch_image::getGlobalVariables()
194 {
195     BPatch_variableExpr *var;
196     BPatch_Vector<BPatch_variableExpr *> *varlist =
197         new BPatch_Vector<BPatch_variableExpr *>;
198
199     if (varlist == NULL) return NULL;
200
201     // XXX - should this stuff really be by image ??? jkh 3/19/99
202     BPatch_Vector<BPatch_module *> *mods = getModules();
203     //BPatch_type *type;
204     for (unsigned int m = 0; m < mods->size(); m++) {
205         BPatch_module *module = (*mods)[m];
206         char name[255];
207         module->getName(name, sizeof(name));
208         vector<string> keys = module->moduleTypes->globalVarsByName.keys();
209         int limit = keys.size();
210         for (int j = 0; j < limit; j++) {
211             string name = keys[j];
212             var = createVarExprByName(module, name.string_of());
213             varlist->push_back(var);
214         }
215     }
216
217
218     return varlist;
219 }
220
221 bool BPatch_image::getVariables(BPatch_Vector<BPatch_variableExpr *> &vars)
222 {
223     BPatch_Vector<BPatch_variableExpr *> *temp = BPatch_image::getGlobalVariables();
224
225     if (temp) {
226         vars = *temp;
227         return true;
228     } else {
229         vars = BPatch_Vector<BPatch_variableExpr *>();
230         return false;
231     }
232 }
233
234
235 /*
236  * BPatch_image::getModules
237  *
238  * Returns a list of all procedures in the image upon success, and NULL
239  * upon failure.
240  */
241 BPatch_Vector<BPatch_module *> *BPatch_image::getModules()
242 {
243   if (modlist) {
244     return modlist;
245   }
246   
247   modlist = new BPatch_Vector<BPatch_module *>;
248   if (modlist == NULL) return NULL;
249   
250   // XXX Also, what should we do about getting rid of this?  Should
251   //     the BPatch_modules already be made and kept around as long
252   //     as the process is, so the user doesn't have to delete them?
253   vector<module *> *mods = proc->getAllModules();
254   
255   for (unsigned int m = 0; m < mods->size(); m++) {
256     pdmodule *curr = (pdmodule *) (*mods)[m];
257     BPatch_module *bpmod = new BPatch_module(proc, curr, this);
258     modlist->push_back(bpmod);
259   }
260   
261   // BPatch_procedures are only built on demand, and we need to make sure
262   //    they get built.
263   (void) getProcedures();
264
265   return modlist;
266 }
267
268 /*
269  * BPatch_image::findProcedurePoint
270  *
271  * Returns a vector of the instrumentation points from a procedure that is
272  * identified by the parameters, or returns NULL upon failure.
273  *
274  * name         The name of the procedure in which to look up the points.
275  * loc          The points within the procedure to return.  The following
276  *              values are valid for this parameter:
277  *                BPatch_entry         The function's entry point.
278  *                BPatch_exit          The function's exit point(s).
279  *                BPatch_subroutine    The points at which the procedure calls
280  *                                     other procedures.
281  *                BPatch_longJump      The points at which the procedure make
282  *                                     long jump calls.
283  *                BPatch_allLocations  All of the points described above.
284  */
285 BPatch_Vector<BPatch_point*> *BPatch_image::findProcedurePoint(
286         const char *name, const BPatch_procedureLocation loc)
287 {
288     /* XXX Right now this assumes that there's only one function with
289      * the given name.
290      */
291
292     BPatch_function *func = findBPFunction(name);
293     if (func == NULL) return NULL;
294
295     return func->findPoint(loc);
296 }
297
298 /*
299  * BPatch_image::findProcedurePoint (VG 09/05/01)
300  *
301  * Returns a vector of the instrumentation points from a procedure that is
302  * identified by the parameters, or returns NULL upon failure.
303  *
304  * name         The name of the procedure in which to look up the points.
305  * ops          The points within the procedure to return. A set of op codes
306  *              defined in ast.h
307  */
308 BPatch_Vector<BPatch_point*> *BPatch_image::findProcedurePoint(
309         const char *name, const BPatch_Set<BPatch_opCode>& ops)
310 {
311     /* XXX Right now this assumes that there's only one function with
312      * the given name.
313      */
314
315     BPatch_function *func = findBPFunction(name);
316     if (func == NULL) return NULL;
317
318     return func->findPoint(ops);
319 }
320
321 /*
322  * BPatch_image::createInstPointAtAddr
323  *
324  * Returns a pointer to a BPatch_point object representing an
325  * instrumentation point at the given address.
326  *
327  * Returns the pointer to the BPatch_point on success, or NULL upon
328  * failure.
329  *
330  * address      The address that the instrumenation point should refer to.
331  */
332 BPatch_point *BPatch_image::createInstPointAtAddr(void *address)
333 {
334         return createInstPointAtAddr(address,NULL);
335 }
336
337 BPatch_point *BPatch_image::createInstPointAtAddr(void *address,
338                                                   BPatch_point** alternative)
339 {
340     unsigned i;
341
342     /* First look in the list of non-standard instPoints. */
343     if (proc->instPointMap.defines((Address)address)) {
344         return proc->instPointMap[(Address)address];
345     }
346
347     /* Look in the regular instPoints of the enclosing function. */
348     function_base *func = proc->findFuncByAddr((Address)address);
349
350     // If it's in an uninstrumentable function, just return an error.
351     if (!((pd_Function*)func)->isInstrumentable())
352         return NULL;
353
354     pd_Function* pointFunction = (pd_Function*)func;
355     Address pointImageBase = 0;
356     if(!pointFunction || !pointFunction->file())
357         return NULL;
358     image* pointImage = pointFunction->file()->exec();
359     proc->getBaseAddress((const image*)pointImage,pointImageBase);
360
361     if (func != NULL) {
362         instPoint *entry = const_cast<instPoint *>(func->funcEntry(NULL));
363         assert(entry);
364         if ((entry->iPgetAddress() == (Address)address) ||
365             (pointImageBase && 
366              ((entry->iPgetAddress() + pointImageBase) == (Address)address))) 
367         {
368             return proc->findOrCreateBPPoint(NULL, entry, BPatch_entry);
369         }
370
371         const vector<instPoint*> &exits = func->funcExits(NULL);
372         for (i = 0; i < exits.size(); i++) {
373             assert(exits[i]);
374             if ((exits[i]->iPgetAddress() == (Address)address) ||
375                 (pointImageBase && 
376                  ((exits[i]->iPgetAddress() + pointImageBase) == (Address)address))) 
377             {
378                 return proc->findOrCreateBPPoint(NULL, exits[i], BPatch_exit);
379             }
380         }
381
382         const vector<instPoint*> &calls = func->funcCalls(NULL);
383         for (i = 0; i < calls.size(); i++) {
384             assert(calls[i]);
385             if ((calls[i]->iPgetAddress() == (Address)address) ||
386                 (pointImageBase && 
387                  ((calls[i]->iPgetAddress() + pointImageBase) == (Address)address))) 
388             {
389                 return proc->findOrCreateBPPoint(NULL, calls[i],
390                                                  BPatch_subroutine);
391             }
392         }
393     }
394
395     if(alternative)
396         *alternative = NULL;
397
398     /* We don't have an instPoint for this address, so make one. */
399     return createInstructionInstPoint(proc, address, alternative);
400 }
401
402
403 /*
404  * BPatch_image::findFunctionInImage
405  *
406  * Searches a single image (class image object) for all functions of
407  * the given name.  Results are returned in the vector that is passed in.
408  * Note that the vector is not cleared first, so anything in the vector
409  * when it is passed in remains there.
410  *
411  * name         The name of function to look up.
412  * img          The image to search.
413  * funcs        The vector in which to return the results.
414  *
415  * This function would make a lot more sense as a method of the image class,
416  * but it's here since it deals with BPatch_functions and not pd_Functions.
417  */
418 void BPatch_image::findFunctionInImage(
419         const char *name, image *img, BPatch_Vector<BPatch_function*>& funcs)
420 {
421     pd_Function *pdf;
422     vector<pd_Function*> *pdfv;
423
424     if ((pdfv = img->findFuncVectorByPretty(name)) != NULL) {
425         assert(pdfv->size() > 0);
426
427         for (unsigned int i = 0; i < pdfv->size(); i++)
428             funcs.push_back(proc->findOrCreateBPFunc((*pdfv)[i]));
429     } else {
430
431         if ((pdf = img->findFuncByMangled(name)) != NULL)
432             funcs.push_back(proc->findOrCreateBPFunc(pdf));
433     }
434
435     // Note that we can only return one non instrumentable function right now.
436     if ((pdf = img->findNonInstruFunc(name)) != NULL)
437         funcs.push_back(proc->findOrCreateBPFunc(pdf));
438
439     // Note that we can only return one excluded function right now.
440     if ((pdf = img->findExcludedFunc(name)) != NULL)
441         funcs.push_back(proc->findOrCreateBPFunc(pdf));
442 }
443
444
445 /*
446  * BPatch_image::findFunction
447  *
448  * Returns a BPatch_function* representing the named function upon success,
449  * and NULL upon failure.
450  *
451  * name         The name of function to look up.
452  */
453 BPatch_function *BPatch_image::findFunction(const char *name, bool showError)
454 {
455     BPatch_Vector<BPatch_function*> funcs;
456
457     findFunction(name, funcs, false);
458
459     if (funcs.size() == 0) {
460         string fullname = string(name) + string("_");
461         findFunction(fullname.string_of(), funcs, false);
462     }
463
464     if (funcs.size() > 0) {
465         return funcs[0];
466     }
467     else {
468         if (showError) {
469             string msg = string("Unable to find function: ") + string(name);
470             BPatch_reportError(BPatchSerious, 100, msg.string_of());
471         }
472         return NULL;
473     }
474 }
475
476
477 /*
478  * BPatch_image::findFunction
479  *
480  * Fills a vector with BPatch_function pointers representing all functions in
481  * the image with the given name.  Returns a pointer to the vector that was
482  * passed in on success, and NULL on error.
483  *
484  * name         The name of function to look up.
485  * funcs        The vector in which to place the results.
486  */
487 BPatch_Vector<BPatch_function*> *BPatch_image::findFunction(
488         const char *name, BPatch_Vector<BPatch_function*> &funcs, bool showError)
489 {
490
491 #ifdef USE_STL_VECTOR
492   BPatch_Vector<BPatch_function*> *init_funcs = new BPatch_Vector<BPatch_function*>();
493   funcs = *init_funcs;
494 #else  
495   funcs = BPatch_Vector<BPatch_function*>();
496 #endif
497
498     findFunctionInImage(name, proc->symbols, funcs);
499
500     if (proc->dynamiclinking && proc->shared_objects) {
501         for(unsigned int j = 0; j < proc->shared_objects->size(); j++){
502             const image *obj_image = ((*proc->shared_objects)[j])->getImage();
503             if (obj_image) {
504               findFunctionInImage(name, (image*)obj_image, funcs);
505             }
506         }
507     }
508
509     if (funcs.size() > 0) {
510         return &funcs;
511     } else {
512
513         if (showError) {
514             string msg = string("Unable to find function: ") + string(name);
515             BPatch_reportError(BPatchSerious, 100, msg.string_of());
516         }
517         return NULL;
518     }
519 }
520
521
522 /*
523  * BPatch_image::findVariable
524  *
525  * Returns a BPatch_variableExpr* representing the given variable in the
526  * application image.  If no such variable exists, returns NULL.
527  *
528  * name         The name of the variable to look up.
529  *
530  * First look for the name with an `_' prepended to it, and if that is not
531  *   found try the original name.
532  */
533 BPatch_variableExpr *BPatch_image::findVariable(const char *name, bool showError)
534 {
535     string full_name = string("_") + string(name);
536
537     Symbol syminfo;
538     if (!proc->getSymbolInfo(full_name, syminfo)) {
539         string short_name(name);
540         if (!proc->getSymbolInfo(short_name, syminfo) && showError) {
541             string msg = string("Unable to find variable: ") + string(name);
542             showErrorCallback(100, msg);
543             return NULL;
544         }
545     }
546     if( syminfo.type() == Symbol::PDST_FUNCTION)
547       return NULL;
548     
549     BPatch_variableExpr *bpvar = AddrToVarExpr->hash[syminfo.addr()];
550     if (bpvar) return bpvar;
551
552     // XXX - should this stuff really be by image ??? jkh 3/19/99
553     BPatch_Vector<BPatch_module *> *mods = getModules();
554     BPatch_type *type = NULL;
555     for (unsigned int m = 0; m < mods->size(); m++) {
556         BPatch_module *module = (*mods)[m];
557         //printf("The moduleType address is : %x\n", &(module->moduleTypes));
558         type = module->moduleTypes->findVariableType(name);
559         if (type) break;
560     }
561     if (!type) {
562         type = BPatch::bpatch->type_Untyped;
563     }
564
565     char *nameCopy = strdup(name);
566     assert(nameCopy);
567     BPatch_variableExpr *ret = new BPatch_variableExpr((char *) nameCopy, 
568         proc, (void *)syminfo.addr(), (const BPatch_type *) type);
569     AddrToVarExpr->hash[syminfo.addr()] = ret;
570     return ret;
571 }
572
573 //
574 // findVariable
575 //      scp     - a BPatch_point that defines the scope of the current search
576 //      name    - name of the variable to find.
577 //
578 BPatch_variableExpr *BPatch_image::findVariable(BPatch_point &scp,
579                                                 const char *name)
580 {
581     // Get the function to search for it's local variables.
582     // XXX - should really use more detailed scoping info here - jkh 6/30/99
583     BPatch_function *func = (BPatch_function *) scp.getFunction();
584     if (!func) {
585         string msg = string("point passed to findVariable lacks a function\n address point type passed?");
586         showErrorCallback(100, msg);
587         return NULL;
588     }
589
590     BPatch_localVar *lv = func->findLocalVar(name);
591
592     if (!lv) {
593         // look for it in the parameter scope now
594         lv = func->findLocalParam(name);
595     }
596     if (lv) {
597         // create a local expr with the correct frame offset or absolute
598         //   address if that is what is needed
599         return new BPatch_variableExpr(proc, (void *) lv->getFrameOffset(), 
600             lv->getType(), lv->getFrameRelative(), &scp);
601     }
602
603     // finally check the global scope.
604     return findVariable(name);
605 }
606
607 /*
608  * BPatch_image::findType
609  *
610  * Returns a BPatch_type* representing the named type.  If no such type
611  * exists, returns NULL.
612  *
613  * name         The name of type to look up.
614  */
615 BPatch_type *BPatch_image::findType(const char *name)
616 {
617     BPatch_type *type;
618
619     assert(BPatch::bpatch != NULL);
620
621     // XXX - should this stuff really be by image ??? jkh 3/19/99
622     BPatch_Vector<BPatch_module *> *mods = getModules();
623     for (unsigned int m = 0; m < mods->size(); m++) {
624         BPatch_module *module = (*mods)[m];
625         type = module->moduleTypes->findType(name);
626         if (type) return type;
627     }
628
629     // check the default base types
630     type = BPatch::bpatch->stdTypes->findType(name);
631     if(type) return type;
632
633     // check the API types of last resort
634     return BPatch::bpatch->APITypes->findType(name);
635
636 }
637
638 /*
639  * BPatch_image::findBPFunnction
640  *
641  * Returns a BPatch_function* representing the named function or if no func
642  * exists, returns NULL.
643  *
644  * name         The name of function to look up.
645  */
646 BPatch_function  *BPatch_image::findBPFunction(const char *name)
647 {
648     char *fullName;
649     BPatch_function *func;
650     BPatch_Vector<BPatch_function *> * funclist =
651       new BPatch_Vector<BPatch_function *>;
652       
653     assert(BPatch::bpatch != NULL);
654
655     // XXX - should this stuff really be by image ??? jkh 3/19/99
656     BPatch_Vector<BPatch_module *> *mods = getModules();
657     //printf(" Number of Modules %d\n",mods->size());
658     for (unsigned int m = 0; m < mods->size(); m++) {
659         BPatch_module *module = (*mods)[m];
660         func = module->findFunction(name);
661         if (func) {
662             if (func->getProc() != proc) {
663                 printf("got func in the wrong proc\n");
664             }
665             funclist->push_back(func);
666         }
667     }
668
669     if (!funclist->size()) {
670         fullName = (char *) malloc(strlen(name) + 2);
671         sprintf(fullName, "%s_", name);
672         for (unsigned int m = 0; m < mods->size(); m++) {
673             BPatch_module *module = (*mods)[m];
674             func = module->findFunction(fullName);
675             if (func) {
676                 if (func->getProc() != proc) {
677                     printf("got func in the wrong proc\n");
678                 }
679                 funclist->push_back(func);
680             }
681         }
682         free(fullName);
683     }
684
685     if( funclist->size()){
686       //printf("Function list has %d functions\n", funclist->size());
687       if( funclist->size() == 2)
688         return (*funclist)[1];
689       else 
690         return (*funclist)[0];
691     }
692     // check the default base types of last resort
693     else
694       return NULL;
695 }
696
697
698 /*
699  * BPatch_image::addModule
700  *
701  * Adds a new module to the BPatch_module vector
702  * if modlist exists. 
703  *
704  * bpmod is a pointer to the BPatch_module to add to the vector
705  */
706 void BPatch_image::addModuleIfExist(BPatch_module *bpmod){
707
708   if( modlist )
709     modlist->push_back(bpmod);
710   
711 }
712
713 /*
714  * BPatch_image::ModuleListExist
715  *
716  * Checks to see if modlist has been created.
717  */
718 bool BPatch_image::ModuleListExist(){
719
720   if ( modlist )
721     return true;
722   else
723     return false;
724 }
725
726 /** method that retrieves the addresses corresponding to a line number
727   * in a file.It returns true in success. If the file is not in the image
728   * or line number is not found it retuns false. In case of exact match is not
729   * asked then the next line number which is greater or equal to the given one
730   * is used
731   */
732 //method to get the addresses corresponding to a line number given
733 //in case of success it returns true and inserts the addresses in to
734 //the vector given. If the file name is not found or the line information
735 //is not valid or if the exact match is not found it retuns false.
736 //If exact match is not asked then the line number is taken to be the
737 //first one greater or equal to the given one.
738 bool BPatch_image::getLineToAddr(const char* fileName,unsigned short lineNo,
739                                  BPatch_Vector<unsigned long>& buffer,
740                                  bool exactMatch)
741 {
742         string fName(fileName);
743
744         //first get all modules
745         BPatch_Vector<BPatch_module*>* appModules =  getModules();
746
747         LineInformation* lineInformation;
748         FileLineInformation* fLineInformation = NULL;
749                 
750         //in each module try to find the file
751         for(unsigned int i=0;i<appModules->size();i++){
752                 lineInformation = (*appModules)[i]->lineInformation;
753                 if(!lineInformation)
754                         continue;
755                 fLineInformation = lineInformation->getFileLineInformation(fName);              
756                 if(fLineInformation)
757                         break;
758         }
759         
760         //if there is no entry for the file is being found then give warning and return
761         if(!fLineInformation){
762                 return false;
763         }
764
765         //get the addresses for the line number
766         BPatch_Set<Address> addresses;
767         if(!fLineInformation->getAddrFromLine(fName,addresses,lineNo,true,exactMatch))
768                 return false;
769
770         //then insert the elements to the vector given
771         Address* elements = new Address[addresses.size()];
772         addresses.elements(elements);
773         for(int j=0;j<addresses.size();j++)
774                 buffer.push_back(elements[j]);
775         delete[] elements;
776
777         return true;
778 }
779
780 #ifdef IBM_BPATCH_COMPAT
781 char *BPatch_image::programName(char *name, unsigned int len) { 
782     return getProgramName(name, len); 
783 }
784
785 char *BPatch_image::getProgramName(char *name, unsigned int len) {
786   len < strlen("<unknown") ?   
787     strncpy(name, "<unknown>", len) : strcpy(name, "<unknown>");
788     return name;
789 }
790
791 int  BPatch_image::lpType() 
792 {
793     return 0;
794 };
795 #endif