Changes to work towards compatability with IBM's version of dyninst.
[dyninst.git] / dyninstAPI / src / BPatch_module.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 #include <stdio.h>
43 #include <ctype.h>
44
45 #define BPATCH_FILE
46
47 #include "process.h"
48 #include "symtab.h"
49 #include "showerror.h"
50 #include "BPatch.h"
51 #include "BPatch_module.h"
52 #include "BPatch_snippet.h" // For BPatch_function; remove if we move it
53 #include "BPatch_collections.h"
54 #include "common/h/String.h"
55 #include "BPatch_type.h"    // For BPatch_type related stuff
56 #include "BPatch_Vector.h"
57 #include "LineInformation.h"
58
59 char * current_func_name = NULL;
60
61
62 /*
63  * BPatch_module::getSourceObj()
64  *
65  * Return the contained source objects (e.g. functions).
66  *
67  */
68 bool BPatch_module::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &vect)
69 {
70     BPatch_Vector<BPatch_function *> *temp;
71     temp = getProcedures();
72     if (temp) {
73        vect = *(BPatch_Vector<BPatch_sourceObj *> *) temp;
74        return true;
75     } else {
76        return false;
77     }
78 }
79
80 /*
81  * BPatch_function::getObjParent()
82  *
83  * Return the parent of the function (i.e. the image)
84  *
85  */
86 BPatch_sourceObj *BPatch_module::getObjParent()
87 {
88     return (BPatch_sourceObj *) img;
89 }
90
91 /* XXX temporary */
92 char *BPatch_module::getName(char *buffer, int length)
93 {
94     string str = mod->fileName();
95
96     strncpy(buffer, str.string_of(), length);
97
98     return buffer;
99 }
100
101
102 char *BPatch_module::getFullName(char *buffer, int length)
103 {
104     string str = mod->fullName();
105
106     strncpy(buffer, str.string_of(), length);
107
108     return buffer;
109 }
110
111
112 BPatch_module::BPatch_module(process *_proc, pdmodule *_mod,BPatch_image *_img):
113     proc(_proc), mod(_mod), img(_img), BPfuncs(NULL),lineInformation(NULL) 
114 {
115     _srcType = BPatch_sourceModule;
116
117     moduleTypes = new BPatch_typeCollection;
118
119     // load all of the type information
120 #if !defined(mips_sgi_irix6_4)
121
122     if (BPatch::bpatch->parseDebugInfo()){ 
123         lineInformation = new LineInformation(mod->fileName());
124         parseTypes();
125     }
126 #endif
127 }
128
129 BPatch_module::~BPatch_module()
130 {
131     delete moduleTypes;
132
133     for (int f = 0; f < BPfuncs->size(); f++) {
134         delete (*BPfuncs)[f];
135     }
136     delete BPfuncs;
137     if(lineInformation) delete lineInformation;
138 }
139
140 /*
141  * BPatch_module::getProcedures
142  *
143  * Returns a list of all procedures in the module upon success, and NULL
144  * upon failure.
145  */
146 BPatch_Vector<BPatch_function *> *BPatch_module::getProcedures()
147 {
148     if (BPfuncs) return BPfuncs;
149     
150     BPfuncs = new BPatch_Vector<BPatch_function *>;
151
152     if (BPfuncs == NULL) return NULL;
153
154     // XXX Also, what should we do about getting rid of this?  Should
155     //     the BPatch_functions already be made and kept around as long
156     //     as the process is, so the user doesn't have to delete them?
157     vector<function_base *> *funcs = mod->getFunctions();
158
159     for (unsigned int f = 0; f < funcs->size(); f++) {
160         BPatch_function *bpfunc;
161         bpfunc = proc->PDFuncToBPFuncMap[(*funcs)[f]];
162         if (!bpfunc) bpfunc = new BPatch_function(proc, (*funcs)[f], this);
163         BPfuncs->push_back(bpfunc);
164     }
165
166     return BPfuncs;
167 }
168
169 /*
170  * BPatch_module::findFunction
171  *
172  * Returns a BPatch_function* with the same name that is provided or
173  * NULL if no function with that name is in the module.  This function
174  * searches the BPatch_function vector of the module followed by
175  * the function_base of the module.  If a function_base is found, then
176  * a BPatch_function is created and added to the BPatch_function vector of
177  * the module.
178  * name The name of function to look up.
179  */
180
181 extern bool buildDemangledName(const string &mangled, string &use);
182
183 BPatch_function * BPatch_module::findFunction(const char * name)
184 {
185
186     // Did not find BPatch_function with name match in BPatch_function vector
187     // trying pdmodule
188     function_base *func = mod->findFunction(name);
189
190     if (func == NULL) {
191         string fullname = string("_") + string(name);
192         func = mod->findFunction(fullname);
193     }
194
195     if (func == NULL) {
196         //Try with demangled name
197         string mangled_name = name;
198         string demangled;
199         if (buildDemangledName(mangled_name, demangled))
200                 func = mod->findFunction(demangled);
201     }
202
203     if (func == NULL) {
204         return NULL;
205     }
206   
207     BPatch_function * bpfunc; 
208     if ((bpfunc = proc->PDFuncToBPFuncMap[func])) {
209         // we have a BPatch_function for this already
210         return bpfunc;
211     }
212
213     // Found function in module and creating BPatch_function
214     bpfunc = new BPatch_function(proc, func, this);
215
216 #if defined(sparc_sun_solaris2_4)
217     // Adding new BPatch_Function to BPatch_function vector
218     if (this->BPfuncs) this->BPfuncs->push_back(bpfunc);
219 #endif
220     return bpfunc;
221     
222 }
223
224 string* processDirectories(string* fn){
225         if(!fn)
226                 return NULL;
227
228         if(!strstr(fn->string_of(),"/./") &&
229            !strstr(fn->string_of(),"/../"))
230                 return fn;
231
232         string* ret = NULL;
233         char* suffix = NULL;
234         char* prefix = NULL;
235         char* pPath = new char[strlen(fn->string_of())+1];
236         strcpy(pPath,fn->string_of());
237
238         if(pPath[0] == '/')
239                 prefix = "/";
240         else
241                 prefix = "";
242
243         if(pPath[strlen(pPath)-1] == '/')
244                 suffix = "/";
245         else
246                 suffix = "";
247
248         int count = 0;
249         char* pPathLocs[1024];
250         char* p = strtok(pPath,"/");
251         while(p){
252                 if(!strcmp(p,".")){
253                         p = strtok(NULL,"/");
254                         continue;
255                 }
256                 else if(!strcmp(p,"..")){
257                         count--;
258                         if(((count < 0) && (*prefix != '/')) || 
259                            ((count >= 0) && !strcmp(pPathLocs[count],"..")))
260                         {
261                                 count++;
262                                 pPathLocs[count++] = p;
263                         }
264                         if(count < 0) count = 0;
265                 }
266                 else
267                         pPathLocs[count++] = p;
268
269                 p = strtok(NULL,"/");
270         }
271         ret = new string;
272         *ret += prefix;
273         for(int i=0;i<count;i++){
274                 *ret += pPathLocs[i];
275                 if(i != (count-1))
276                         *ret += "/";
277         }
278         *ret += suffix;
279
280         delete pPath;
281         delete fn;
282         return ret;
283 }
284 extern char *parseStabString(BPatch_module *, int linenum, char *str, 
285         int fPtr, BPatch_type *commonBlock = NULL);
286
287 #if defined(rs6000_ibm_aix4_1)
288
289 #include <linenum.h>
290 #include <syms.h>
291
292 void parseLineInformation(process* proc,LineInformation* lineInformation,
293                           BPatch_Vector<IncludeFileInfo>& includeFiles,string* currentSourceFile,
294                           char* symbolName,
295                           SYMENT *sym,
296                           Address linesfdptr,char* lines,int nlines)
297 {
298       int j;
299       union auxent *aux;
300
301       /* if it is beginning of include files then update the data structure 
302          that keeps the beginning of the include files. If the include files contain 
303          information about the functions and lines we have to keep it */
304       if (sym->n_sclass == C_BINCL){
305                 includeFiles.push_back(IncludeFileInfo((sym->n_value-linesfdptr)/LINESZ, symbolName));
306       }
307       /* similiarly if the include file contains function codes and line information
308          we have to keep the last line information entry for this include file */
309       else if (sym->n_sclass == C_EINCL){
310                 if (includeFiles.size() > 0) {
311                         includeFiles[includeFiles.size()-1].end = (sym->n_value-linesfdptr)/LINESZ;
312                 }
313       }
314       /* if the enrty is for a function than we have to collect all info
315          about lines of the function */
316       else if (sym->n_sclass == C_FUN){
317                 assert(currentSourceFile);
318                 /* creating the string for function name */
319                 char* ce = strchr(symbolName,':'); if(ce) *ce = '\0';
320                 string currentFunctionName(symbolName);
321
322                 /* getting the real function base address from the symbols*/
323                 Address currentFunctionBase=0;
324                 Symbol info;
325                 proc->getSymbolInfo(currentFunctionName,info,
326                                     currentFunctionBase);
327                 currentFunctionBase += info.addr();
328
329                 /* getting the information about the function from C_EXT */
330                 int initialLine = 0;
331                 int initialLineIndex = 0;
332                 Address funcStartAddress = 0;
333                 for(j=-1;;j--){
334                         SYMENT *extsym = (SYMENT*)(((unsigned)sym)+j*SYMESZ);
335                         if(extsym->n_sclass == C_EXT){
336                                 aux = (union auxent*)((char*)extsym+SYMESZ);
337 #ifndef __64BIT__
338                                 initialLineIndex = (aux->x_sym.x_fcnary.x_fcn.x_lnnoptr-linesfdptr)/LINESZ;
339 #endif
340                                 funcStartAddress = extsym->n_value;
341                                 break;
342                         }
343                 }
344
345                 /* access the line information now using the C_FCN entry*/
346                 SYMENT *bfsym = (SYMENT*)(((unsigned)sym)+SYMESZ);
347
348                 if (bfsym->n_sclass != C_FCN) {
349                     printf("unable to process line info for %s\n", symbolName);
350                     return;
351                 }
352
353                 aux = (union auxent*)((char*)bfsym+SYMESZ);
354                 initialLine = aux->x_sym.x_misc.x_lnsz.x_lnno;
355
356                 string whichFile = *currentSourceFile;
357                 /* find in which file is it */
358                 for(j=0;j<includeFiles.size();j++)
359                         if((includeFiles[j].begin <= (unsigned)initialLineIndex) &&
360                            (includeFiles[j].end >= (unsigned)initialLineIndex)){
361                                 whichFile = includeFiles[j].name;
362                                 break;
363                         }
364                 lineInformation->insertSourceFileName(currentFunctionName,
365                                                       whichFile);
366                 for(j=initialLineIndex+1;j<nlines;j++){
367                         LINENO* lptr = (LINENO*)(lines+j*LINESZ);
368                         if(!lptr->l_lnno)
369                                 break;
370                         lineInformation->insertLineAddress(
371                                 currentFunctionName,whichFile,
372                                 lptr->l_lnno+initialLine-1,
373                                 (lptr->l_addr.l_paddr-funcStartAddress)+currentFunctionBase);
374                 }
375       }
376 }
377
378
379 // Gets the stab and stabstring section and parses it for types
380 // and variables
381 void BPatch_module::parseTypes()
382 {
383     int i, j;
384     int nlines;
385     int nstabs;
386     char* lines;
387     SYMENT *syms;
388     SYMENT *tsym;
389     char *stringPool;
390     char tempName[9];
391     char *stabstr=NULL;
392     union auxent *aux;
393     image * imgPtr=NULL;
394     char* funcName = NULL;
395     Address staticBlockBaseAddr;
396     unsigned long linesfdptr;
397     BPatch_type *commonBlock = NULL;
398     BPatch_variableExpr *commonBlockVar;
399     string* currentSourceFile = NULL;
400
401     BPatch_Vector<IncludeFileInfo> includeFiles;
402
403     //Using pdmodule to get the image Object.
404     imgPtr = mod->exec();
405
406     //Using the image to get the Object (class)
407     Object *objPtr = (Object *) &(imgPtr->getObject());
408
409     //Using the Object to get the pointers to the .stab and .stabstr
410     objPtr->get_stab_info(stabstr, nstabs, ((Address&) syms), stringPool); 
411
412     this->BPfuncs = this->getProcedures();
413
414
415     objPtr->get_line_info(nlines,lines,linesfdptr); 
416
417     bool parseActive = true;
418     for (i=0; i < nstabs; i++) {
419       /* do the pointer addition by hand since sizeof(struct syment)
420        *   seems to be 20 not 18 as it should be */
421       SYMENT *sym = (SYMENT *) (((unsigned) syms) + i * SYMESZ);
422       // SYMENT *sym = (SYMENT *) (((unsigned) syms) + i * sizeof(struct syment));
423
424
425       if (sym->n_sclass == C_FILE) {
426          char *moduleName;
427          if (!sym->n_zeroes) {
428             moduleName = &stringPool[sym->n_offset];
429          } else {
430             memset(tempName, 0, 9);
431             strncpy(tempName, sym->n_name, 8);
432             moduleName = tempName;
433          }
434          /* look in aux records */
435          for (j=1; j <= sym->n_numaux; j++) {
436             aux = (union auxent *) ((char *) sym + j * SYMESZ);
437             if (aux->x_file._x.x_ftype == XFT_FN) {
438                 if (!aux->x_file._x.x_zeroes) {
439                      moduleName = &stringPool[aux->x_file._x.x_offset];
440                 } else {
441                      // x_fname is 14 bytes
442                      memset(moduleName, 0, 15);
443                      strncpy(moduleName, aux->x_file.x_fname, 14);
444                 }
445             }
446          }
447
448          if(currentSourceFile) delete currentSourceFile;
449          currentSourceFile = new string(moduleName);
450          currentSourceFile = processDirectories(currentSourceFile);
451
452          if (strrchr(moduleName, '/')) {
453              moduleName = strrchr(moduleName, '/');
454              moduleName++;
455          }
456
457          if (!strcmp(moduleName, mod->fileName().string_of())) {
458                 parseActive = true;
459          } else {
460                 parseActive = false;
461          }
462       }
463
464       if (!parseActive) continue;
465
466       char *nmPtr;
467       if (!sym->n_zeroes && ((sym->n_sclass & DBXMASK) ||
468                              (sym->n_sclass == C_BINCL) ||
469                              (sym->n_sclass == C_EINCL))) {
470           if (sym->n_offset < 3) {
471               if (sym->n_offset == 2 && stabstr[0]) {
472                   nmPtr = &stabstr[0];
473               } else {
474                   nmPtr = &stabstr[sym->n_offset];
475               }
476           } else if (!stabstr[sym->n_offset-3]) {
477               nmPtr = &stabstr[sym->n_offset];
478           } else {
479               /* has off by two error */
480               nmPtr = &stabstr[sym->n_offset-2];
481           }
482 #ifdef notdef
483           printf("using nmPtr = %s\n", nmPtr);
484           printf("got n_offset = (%d) %s\n", sym->n_offset, &stabstr[sym->n_offset]);
485           if (sym->n_offset>=2) 
486               printf("got n_offset-2 = %s\n", &stabstr[sym->n_offset-2]);
487           if (sym->n_offset>=3) 
488               printf("got n_offset-3 = %x\n", stabstr[sym->n_offset-3]);
489           if (sym->n_offset>=4) 
490               printf("got n_offset-4 = %x\n", stabstr[sym->n_offset-4]);
491 #endif
492       } else {
493           // names 8 or less chars on inline, not in stabstr
494           memset(tempName, 0, 9);
495           strncpy(tempName, sym->n_name, 8);
496           nmPtr = tempName;
497       }
498
499       if ((sym->n_sclass == C_BINCL) ||
500           (sym->n_sclass == C_EINCL) ||
501           (sym->n_sclass == C_FUN)) {
502                 if (funcName) { 
503                     free(funcName);
504                     funcName = NULL;
505                 }
506                 funcName = strdup(nmPtr);
507                 parseLineInformation(proc,lineInformation,includeFiles,
508                                      currentSourceFile,funcName,sym,
509                                      linesfdptr,lines,nlines);
510       }
511
512       if (sym->n_sclass & DBXMASK) {
513           if (sym->n_sclass == C_BCOMM) {
514               char *commonBlockName;
515
516               commonBlockName = nmPtr;
517
518               // find the variable for the common block
519               BPatch_image *progam = (BPatch_image *) getObjParent();
520               
521               commonBlockVar = progam->findVariable(commonBlockName);
522               if (!commonBlockVar) {
523                   printf("unable to find variable %s\n", commonBlockName);
524               } else {
525                   commonBlock = 
526                       const_cast<BPatch_type *> (commonBlockVar->getType());
527                   if (commonBlock->getDataClass() != BPatch_dataCommon) {
528                       // its still the null type, create a new one for it
529                       commonBlock = new BPatch_type(commonBlockName, false);
530                       commonBlockVar->setType(commonBlock);
531                       moduleTypes->addGlobalVariable(commonBlockName, commonBlock);
532
533                       commonBlock->setDataClass(BPatch_dataCommon);
534                   }
535                   // reset field list
536                   commonBlock->beginCommonBlock();
537               }
538           } else if (sym->n_sclass == C_ECOMM) {
539               // copy this set of fields
540               BPatch_function *func = findFunction(funcName);
541               if (!func) {
542                   printf("unable to locate current function %s\n", funcName);
543               } else {
544                   commonBlock->endCommonBlock(func, 
545                       commonBlockVar->getBaseAddr());
546               }
547
548               // update size if needed
549               if (commonBlockVar)
550                   commonBlockVar->setSize(commonBlock->getSize());
551               commonBlockVar = NULL;
552               commonBlock = NULL;
553           } else if (sym->n_sclass == C_BSTAT) {
554               char *staticName, tempName[9];
555               // begin static block
556               // find the variable for the common block
557               tsym = (SYMENT *) (((unsigned) syms) + sym->n_value * SYMESZ);
558
559               if (!tsym->n_zeroes) {
560                   staticName = &stringPool[tsym->n_offset];
561               } else {
562                   memset(tempName, 0, 9);
563                   strncpy(tempName, tsym->n_name, 8);
564                   staticName = tempName;
565               }
566               BPatch_image *progam = (BPatch_image *) getObjParent();
567
568               BPatch_variableExpr *staticBlockVar = progam->findVariable(staticName);
569               if (!staticBlockVar) {
570                   printf("unable to find static block %s\n", staticName);
571                   staticBlockBaseAddr = 0;
572               } else {
573                   staticBlockBaseAddr = (Address) staticBlockVar->getBaseAddr();
574               }
575           } else if (sym->n_sclass == C_ESTAT) {
576               staticBlockBaseAddr = 0;
577           }
578
579           if (staticBlockBaseAddr && (sym->n_sclass == C_STSYM)) {
580               parseStabString(this, 0, nmPtr, 
581                   sym->n_value+staticBlockBaseAddr, commonBlock);
582           } else {
583               parseStabString(this, 0, nmPtr, sym->n_value, commonBlock);
584           }
585       }
586     }
587 }
588
589 #endif
590
591 #if defined(sparc_sun_solaris2_4) || \
592     defined(i386_unknown_solaris2_5) || \
593     defined(i386_unknown_linux2_0)
594
595 // Gets the stab and stabstring section and parses it for types
596 // and variables
597 void BPatch_module::parseTypes()
598 {
599   int i;
600   char *modName;
601   int stab_nsyms;
602   char * temp=NULL;
603   image * imgPtr=NULL;
604   char *commonBlockName;
605   char *ptr, *ptr2, *ptr3;
606   bool parseActive = false;
607   char *stabstr_nextoffset;
608   const char *stabstrs = 0;
609   struct stab_entry *stabptr = NULL;
610   BPatch_type *commonBlock = NULL;
611   BPatch_variableExpr *commonBlockVar;
612   
613   //Using pdmodule to get the image Object.
614   imgPtr = mod->exec();
615   
616   //Using the image to get the Object (class)
617   Object *objPtr = (Object *) &(imgPtr->getObject());
618
619   //Using the Object to get the pointers to the .stab and .stabstr
620   // XXX - Elf32 specific needs to be in seperate file -- jkh 3/18/99
621   objPtr->get_stab_info((void **) &stabptr, stab_nsyms, 
622         (void **) &stabstr_nextoffset);
623
624   // Building the BPatch_Vector<BPatch_function *> for use later when playing
625   // with BPatch_functions
626   //printf("GETTING PROCEDURES for BPatch_Function VECTOR %x!!!\n", &(this->BPfuncs));
627   this->BPfuncs = this->getProcedures();
628
629   //these variables are used to keep track of the source files
630   //and function names being processes at a moment
631
632   string* currentFunctionName = NULL;
633   Address currentFunctionBase = 0;
634   string* currentSourceFile = NULL;
635   string* absoluteDirectory = NULL;
636   
637
638   for(i=0;i<stab_nsyms;i++){
639     // if (stabstrs) printf("parsing #%d, %s\n", stabptr[i].type, &stabstrs[stabptr[i].name]);
640
641     switch(stabptr[i].type){
642
643     case N_UNDF: /* start of object file */
644             /* value contains offset of the next string table for next module */
645             // assert(stabptr[i].name == 1);
646             stabstrs = stabstr_nextoffset;
647             stabstr_nextoffset = (char*)stabstrs + stabptr[i].val;
648
649             //N_UNDF is the start of object file. It is time to 
650             //clean source file name at this moment.
651             if(currentSourceFile){
652                 delete currentSourceFile;
653                 currentSourceFile = NULL;
654                 delete absoluteDirectory;
655                 absoluteDirectory = NULL;
656             }
657             break;
658
659     case N_ENDM: /* end of object file */
660             break;
661
662     case N_SO: /* compilation source or file name */
663       /* printf("Resetting CURRENT FUNCTION NAME FOR NEXT OBJECT FILE\n");*/
664             current_func_name = NULL; // reset for next object file
665             modName = (char*)(&stabstrs[stabptr[i].name]);
666             ptr = strrchr(modName, '/');
667             if (ptr) {
668                 ptr++;
669                 modName = ptr;
670             }
671
672             if (!strcmp(modName, mod->fileName().string_of())) {
673                 parseActive = true;
674                 switch (stabptr[i].desc) {
675                     case N_SO_FORTRAN:
676                         setLanguage(BPatch_fortran);
677                         break;
678
679                     case N_SO_F90:
680                         setLanguage(BPatch_fortran90);
681                         break;
682
683                     case N_SO_AS:
684                         setLanguage(BPatch_assembly);
685                         break;
686
687                     case N_SO_ANSI_C:
688                     case N_SO_C:
689                         setLanguage(BPatch_c);
690                         break;
691
692                     case N_SO_CC:
693                         setLanguage(BPatch_cPlusPlus);
694                         break;
695
696                     default:
697                         setLanguage(BPatch_unknownLanguage);
698                         break;
699                 }
700             } else {
701                 parseActive = false;
702             }
703
704             //time to create the source file name to be used
705             //for latter processing of line information
706             if(!currentSourceFile){
707                 currentSourceFile = new string(&stabstrs[stabptr[i].name]);
708                 absoluteDirectory = new string(*currentSourceFile);
709             }
710             else if(!strlen(&stabstrs[stabptr[i].name])){
711                 delete currentSourceFile;
712                 currentSourceFile = NULL;
713                 delete absoluteDirectory;
714                 absoluteDirectory = NULL;
715             }
716             else
717                 *currentSourceFile += &stabstrs[stabptr[i].name];
718
719             currentSourceFile = processDirectories(currentSourceFile);
720             break;
721
722     case N_SOL:
723             if(absoluteDirectory){
724                 const char* newSuffix = &stabstrs[stabptr[i].name];
725                 if(newSuffix[0] == '/'){
726                         delete currentSourceFile;
727                         currentSourceFile = new string;
728                 }
729                 else{
730                         char* tmp = new char[absoluteDirectory->length()+1];
731                         strcpy(tmp,absoluteDirectory->string_of());
732                         char* p=strrchr(tmp,'/');
733                         if(p) 
734                                 *(++p)='\0';
735                         delete currentSourceFile;
736                         currentSourceFile = new string(tmp);
737                         delete[] tmp;
738                 }
739                 (*currentSourceFile) += newSuffix;
740                 currentSourceFile = processDirectories(currentSourceFile);
741                 if(currentFunctionName)
742                         lineInformation->insertSourceFileName(
743                                 *currentFunctionName,
744                                 *currentSourceFile);
745             }
746             else{
747                 currentSourceFile = new string(&stabstrs[stabptr[i].name]);
748                 currentSourceFile = processDirectories(currentSourceFile);
749                 if(currentFunctionName)
750                         lineInformation->insertSourceFileName(
751                                         *currentFunctionName,
752                                         *currentSourceFile);
753             }
754             break;
755     }
756
757     if (!parseActive) continue;
758
759     switch(stabptr[i].type){
760         case N_SLINE:
761             //if the stab information is a line information
762             //then insert an entry to the line info object
763             if(!currentFunctionName) break;
764             lineInformation->insertLineAddress(
765                         *currentFunctionName,*currentSourceFile,
766                         stabptr[i].desc,
767                         stabptr[i].val+currentFunctionBase);
768             break;
769
770         case N_BCOMM:   {
771             // begin Fortran named common block 
772             commonBlockName = (char *) &stabstrs[stabptr[i].name];
773
774             // find the variable for the common block
775             BPatch_image *progam = (BPatch_image *) getObjParent();
776               
777             commonBlockVar = progam->findVariable(commonBlockName);
778             if (!commonBlockVar) {
779                 printf("unable to find variable %s\n", commonBlockName);
780             } else {
781                 commonBlock = const_cast<BPatch_type *> (commonBlockVar->getType());
782                 if (commonBlock->getDataClass() != BPatch_dataCommon) {
783                     // its still the null type, create a new one for it
784                     commonBlock = new BPatch_type(commonBlockName, false);
785                     commonBlockVar->setType(commonBlock);
786                     moduleTypes->addGlobalVariable(commonBlockName, commonBlock);
787
788                     commonBlock->setDataClass(BPatch_dataCommon);
789                 }
790                 // reset field list
791                 commonBlock->beginCommonBlock();
792             }
793             break;
794         }
795
796         case N_ECOMM: {
797             // copy this set of fields
798             assert(currentFunctionName);
799             BPatch_function *func = findFunction(currentFunctionName->string_of());
800             if (!func) {
801                 printf("unable to locate current function %s\n", currentFunctionName->string_of());
802             } else {
803                 commonBlock->endCommonBlock(func, commonBlockVar->getBaseAddr());
804             }
805
806             // update size if needed
807             if (commonBlockVar)
808                 commonBlockVar->setSize(commonBlock->getSize());
809             commonBlockVar = NULL;
810             commonBlock = NULL;
811             break;
812         }
813
814         // case C_BINCL: -- what is the elf version of this jkh 8/21/01
815         // case C_EINCL: -- what is the elf version of this jkh 8/21/01
816         case 32:    // Global symbols -- N_GYSM 
817         case N_FUN:
818         case 128:   // typedefs and variables -- N_LSYM
819         case 160:   // parameter variable -- N_PSYM 
820             int currentEntry;
821             currentEntry = i;
822
823             //if it is a function stab then we have to insert an entry 
824             //to initialize the entries in the line information object
825             if(stabptr[currentEntry].type == N_FUN){
826                 ptr = new char[1024];
827                 strcpy(ptr,(char *)&stabstrs[stabptr[currentEntry].name]);
828                 while(ptr[strlen(ptr)-1] == '\\'){
829                      ptr[strlen(ptr)-1] = '\0';
830                      currentEntry++;
831                      strcat(ptr,(char *)&stabstrs[stabptr[currentEntry].name]);
832                 }
833
834                 char* colonPtr = NULL;
835                 if(currentFunctionName) delete currentFunctionName;
836                 if(!ptr || !(colonPtr = strchr(ptr,':')))
837                      currentFunctionName = NULL;
838                 else {
839                      char* tmp = new char[colonPtr-ptr+1];
840                      strncpy(tmp,ptr,colonPtr-ptr);
841                      tmp[colonPtr-ptr] = '\0';
842                      currentFunctionName = new string(tmp);
843
844                      currentFunctionBase = 0;
845                      Symbol info;
846                      if (!proc->getSymbolInfo(*currentFunctionName,info,
847                                     currentFunctionBase)) {
848                         string fortranName = *currentFunctionName + string("_");
849                         if (proc->getSymbolInfo(fortranName,info, currentFunctionBase)) {
850                             delete currentFunctionName;
851                             currentFunctionName = new string(fortranName);
852                         }
853                      }
854
855                      currentFunctionBase += info.addr();
856
857                      delete[] tmp;              
858                      if(currentSourceFile)
859                         lineInformation->insertSourceFileName(
860                                 *currentFunctionName,
861                                 *currentSourceFile);
862                 }
863                 delete ptr;
864              } 
865
866              ptr = (char *) &stabstrs[stabptr[i].name];
867              while (ptr[strlen(ptr)-1] == '\\') {
868                 //ptr[strlen(ptr)-1] = '\0';
869                   ptr2 =  (char *) &stabstrs[stabptr[i+1].name];
870                   ptr3 = (char *) malloc(strlen(ptr) + strlen(ptr2));
871                   strcpy(ptr3, ptr);
872                   ptr3[strlen(ptr)-1] = '\0';
873                   strcat(ptr3, ptr2);
874                   
875                   ptr = ptr3;
876                   i++;
877                   // XXX - memory leak on multiple cont. lines
878               }
879
880               // printf("stab #%d = %s\n", i, ptr);
881               // may be nothing to parse - XXX  jdd 5/13/99
882               temp = parseStabString(this, stabptr[i].desc, (char *)ptr, stabptr[i].val, commonBlock);
883               if (*temp) {
884                   //Error parsing the stabstr, return should be \0
885                   fprintf(stderr, "Stab string parsing ERROR!! More to parse: %s\n",
886                       temp);
887               }
888               break;
889         default:
890               break;
891     }                       
892   }
893 }
894
895 #endif //end of #if defined(i386_unknown_linux2_0)
896
897 // Parsing symbol table for Alpha platform
898 // Mehmet
899
900 #if defined(alpha_dec_osf4_0)
901 extern void parseCoff(BPatch_module *mod, char *exeName, 
902                         const string& modName, LineInformation* linfo);
903
904 void BPatch_module::parseTypes()
905 {
906   image * imgPtr=NULL;
907
908   //Using pdmodule to get the image Object.
909   imgPtr = mod->exec();
910
911   //Get the path name of the process
912   char *file = (char *)(imgPtr->file()).string_of();
913
914   // with BPatch_functions
915   this->BPfuncs = this->getProcedures();
916
917   parseCoff(this, file, mod->fileName(),lineInformation);
918 }
919
920 #endif
921
922
923
924 #if defined(i386_unknown_nt4_0) || defined(mips_unknown_ce2_11) //ccw 6 apr 2001
925
926 // Parsing symbol table for NT platform
927 // Mehmet 7/24/00
928
929 #include "CodeView.h"
930
931 void BPatch_module::parseTypes()
932 {
933   
934   image * imgPtr=NULL;
935
936   //Using pdmodule to get the image Object.
937   imgPtr = mod->exec();
938
939   // with BPatch_functions
940   this->BPfuncs = this->getProcedures();
941
942   //The code below is adapted from Object-nt.C
943   IMAGE_DEBUG_INFORMATION* pDebugInfo = NULL;
944
945   // access the module's debug information
946   pDebugInfo = MapDebugInformation(NULL, (LPTSTR)(imgPtr->file()).string_of(), NULL, 0);
947   if( pDebugInfo == NULL )
948   {
949         printf("Unable to get debug information!\n");
950         return;
951   }
952
953   // determine the location of the relevant sections
954   unsigned int i, textSectionId;
955
956   // currently we care only about the .text and .data segments
957   for( i = 0; i < pDebugInfo->NumberOfSections; i++ )
958   {
959         IMAGE_SECTION_HEADER& section = pDebugInfo->Sections[i];
960
961         if( strncmp( (const char*)section.Name, ".text", 5 ) == 0 ) {
962                 textSectionId = i + 1; // note that section numbers are one-based
963                 break;
964         }
965   }
966   DWORD executableBaseAddress = 0;
967   for( i = 0; i < pDebugInfo->NumberOfSections; i++ )
968   {
969         IMAGE_SECTION_HEADER& section = pDebugInfo->Sections[i];
970         if(section.Characteristics & IMAGE_SCN_MEM_EXECUTE){
971                 executableBaseAddress = 
972                         pDebugInfo->ImageBase + section.VirtualAddress;
973                 //cerr << "BASE ADDRESS : " << hex << executableBaseAddress 
974                 //    << dec << "\n";
975                 break;
976         }
977   }
978
979
980   //
981   // parse the symbols, if available
982   // (note that we prefer CodeView over COFF)
983   //
984   if( pDebugInfo->CodeViewSymbols != NULL )
985   {
986         // we have CodeView debug information
987         CodeView *cv = new CodeView( (const char*)pDebugInfo->CodeViewSymbols, 
988                                         textSectionId );
989
990         cv->CreateTypeAndLineInfo(this,executableBaseAddress,
991                            lineInformation);
992   }
993   else if( pDebugInfo->CoffSymbols != NULL )
994   {
995         // we have COFF debug information
996         // ParseCOFFSymbols( pDebugInfo );
997   }
998   else
999   {
1000         // TODO - what to do when there's no debug information?
1001   }
1002 }
1003 #endif
1004
1005
1006 /** method that finds the corresponding addresses for a source line
1007   * this methid returns true in sucess, otherwise false.
1008   * it can be called to find the exact match or, in case, exact match
1009   * does not occur, it will return the address set of the next
1010   * greater line. It uses the name of the module as a source file name
1011   * 
1012   */
1013 bool BPatch_module::getLineToAddr(unsigned short lineNo,
1014                                   BPatch_Vector<unsigned long>& buffer,
1015                                   bool exactMatch)
1016 {
1017         //if the line information is not created yet return false
1018
1019         if(!lineInformation){
1020 #ifdef DEBUG_LINE
1021                 cerr << "BPatch_module::getLineToAddr : ";
1022                 cerr << "Line information is not available.\n";
1023 #endif
1024                 return false;
1025         }
1026         
1027         //query the line info object to get set of addresses if it exists.
1028         BPatch_Set<Address> addresses;
1029         if(!lineInformation->getAddrFromLine(addresses,lineNo,exactMatch))
1030                 return false;
1031
1032         //then insert the elements to the vector given
1033         Address* elements = new Address[addresses.size()];
1034         addresses.elements(elements);
1035         for(int i=0;i<addresses.size();i++)
1036                 buffer.push_back(elements[i]);
1037         delete[] elements;
1038         return true;
1039 }
1040
1041
1042 bool BPatch_module::getVariables(BPatch_Vector<BPatch_variableExpr *> &vars)
1043 {
1044     BPatch_variableExpr *var;
1045     vector<string> keys = moduleTypes->globalVarsByName.keys();
1046     int limit = keys.size();
1047     for (int j = 0; j < limit; j++) {
1048         string name = keys[j];
1049         var = img->createVarExprByName(this, name.string_of());
1050         vars.push_back(var);
1051     }
1052     if (limit) 
1053         return true;
1054     else
1055         return false;
1056 }
1057
1058 #ifdef IBM_BPATCH_COMPAT
1059
1060 bool BPatch_module::getLineNumbers(unsigned int &start, unsigned int &end)
1061 {
1062     start = 0;
1063     end = 0;
1064 }
1065
1066 char *BPatch_module::getUniqueString(char *buffer, int length)
1067 {
1068     getName(buffer, length);
1069     return buffer;
1070 }
1071
1072 int BPatch_module::getSharedLibType()   
1073 {
1074     return 0;
1075 }
1076
1077 int BPatch_module::getBindingType()
1078 {
1079     return 0;
1080 }
1081
1082 #endif
1083