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