2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
49 #include "showerror.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"
59 char * current_func_name = NULL;
63 * BPatch_module::getSourceObj()
65 * Return the contained source objects (e.g. functions).
68 bool BPatch_module::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &vect)
70 BPatch_Vector<BPatch_function *> *temp;
71 temp = getProcedures();
73 vect = *(BPatch_Vector<BPatch_sourceObj *> *) temp;
81 * BPatch_function::getObjParent()
83 * Return the parent of the function (i.e. the image)
86 BPatch_sourceObj *BPatch_module::getObjParent()
88 return (BPatch_sourceObj *) img;
92 char *BPatch_module::getName(char *buffer, int length)
94 string str = mod->fileName();
96 strncpy(buffer, str.string_of(), length);
102 char *BPatch_module::getFullName(char *buffer, int length)
104 string str = mod->fullName();
106 strncpy(buffer, str.string_of(), length);
112 BPatch_module::BPatch_module(process *_proc, pdmodule *_mod,BPatch_image *_img):
113 proc(_proc), mod(_mod), img(_img), BPfuncs(NULL),lineInformation(NULL)
115 _srcType = BPatch_sourceModule;
117 moduleTypes = new BPatch_typeCollection;
119 // load all of the type information
120 #if !defined(mips_sgi_irix6_4)
122 if (BPatch::bpatch->parseDebugInfo()){
123 lineInformation = new LineInformation(mod->fileName());
129 BPatch_module::~BPatch_module()
133 for (int f = 0; f < BPfuncs->size(); f++) {
134 delete (*BPfuncs)[f];
137 if(lineInformation) delete lineInformation;
141 * BPatch_module::getProcedures
143 * Returns a list of all procedures in the module upon success, and NULL
146 BPatch_Vector<BPatch_function *> *BPatch_module::getProcedures()
148 if (BPfuncs) return BPfuncs;
150 BPfuncs = new BPatch_Vector<BPatch_function *>;
152 if (BPfuncs == NULL) return NULL;
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();
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);
170 * BPatch_module::findFunction
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
178 * name The name of function to look up.
181 extern bool buildDemangledName(const string &mangled, string &use);
183 BPatch_function * BPatch_module::findFunction(const char * name)
186 // Did not find BPatch_function with name match in BPatch_function vector
188 function_base *func = mod->findFunction(name);
191 string fullname = string("_") + string(name);
192 func = mod->findFunction(fullname);
196 //Try with demangled name
197 string mangled_name = name;
199 if (buildDemangledName(mangled_name, demangled))
200 func = mod->findFunction(demangled);
207 BPatch_function * bpfunc;
208 if ((bpfunc = proc->PDFuncToBPFuncMap[func])) {
209 // we have a BPatch_function for this already
213 // Found function in module and creating BPatch_function
214 bpfunc = new BPatch_function(proc, func, this);
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);
224 string* processDirectories(string* fn){
228 if(!strstr(fn->string_of(),"/./") &&
229 !strstr(fn->string_of(),"/../"))
235 char* pPath = new char[strlen(fn->string_of())+1];
236 strcpy(pPath,fn->string_of());
243 if(pPath[strlen(pPath)-1] == '/')
249 char* pPathLocs[1024];
250 char* p = strtok(pPath,"/");
253 p = strtok(NULL,"/");
256 else if(!strcmp(p,"..")){
258 if(((count < 0) && (*prefix != '/')) ||
259 ((count >= 0) && !strcmp(pPathLocs[count],"..")))
262 pPathLocs[count++] = p;
264 if(count < 0) count = 0;
267 pPathLocs[count++] = p;
269 p = strtok(NULL,"/");
273 for(int i=0;i<count;i++){
274 *ret += pPathLocs[i];
284 extern char *parseStabString(BPatch_module *, int linenum, char *str,
285 int fPtr, BPatch_type *commonBlock = NULL);
287 #if defined(rs6000_ibm_aix4_1)
292 void parseLineInformation(process* proc,LineInformation* lineInformation,
293 BPatch_Vector<IncludeFileInfo>& includeFiles,string* currentSourceFile,
296 Address linesfdptr,char* lines,int nlines)
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));
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;
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);
322 /* getting the real function base address from the symbols*/
323 Address currentFunctionBase=0;
325 proc->getSymbolInfo(currentFunctionName,info,
326 currentFunctionBase);
327 currentFunctionBase += info.addr();
329 /* getting the information about the function from C_EXT */
331 int initialLineIndex = 0;
332 Address funcStartAddress = 0;
334 SYMENT *extsym = (SYMENT*)(((unsigned)sym)+j*SYMESZ);
335 if(extsym->n_sclass == C_EXT){
336 aux = (union auxent*)((char*)extsym+SYMESZ);
338 initialLineIndex = (aux->x_sym.x_fcnary.x_fcn.x_lnnoptr-linesfdptr)/LINESZ;
340 funcStartAddress = extsym->n_value;
345 /* access the line information now using the C_FCN entry*/
346 SYMENT *bfsym = (SYMENT*)(((unsigned)sym)+SYMESZ);
348 if (bfsym->n_sclass != C_FCN) {
349 printf("unable to process line info for %s\n", symbolName);
353 aux = (union auxent*)((char*)bfsym+SYMESZ);
354 initialLine = aux->x_sym.x_misc.x_lnsz.x_lnno;
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;
364 lineInformation->insertSourceFileName(currentFunctionName,
366 for(j=initialLineIndex+1;j<nlines;j++){
367 LINENO* lptr = (LINENO*)(lines+j*LINESZ);
370 lineInformation->insertLineAddress(
371 currentFunctionName,whichFile,
372 lptr->l_lnno+initialLine-1,
373 (lptr->l_addr.l_paddr-funcStartAddress)+currentFunctionBase);
379 // Gets the stab and stabstring section and parses it for types
381 void BPatch_module::parseTypes()
394 char* funcName = NULL;
395 Address staticBlockBaseAddr;
396 unsigned long linesfdptr;
397 BPatch_type *commonBlock = NULL;
398 BPatch_variableExpr *commonBlockVar;
399 string* currentSourceFile = NULL;
401 BPatch_Vector<IncludeFileInfo> includeFiles;
403 //Using pdmodule to get the image Object.
404 imgPtr = mod->exec();
406 //Using the image to get the Object (class)
407 Object *objPtr = (Object *) &(imgPtr->getObject());
409 //Using the Object to get the pointers to the .stab and .stabstr
410 objPtr->get_stab_info(stabstr, nstabs, ((Address&) syms), stringPool);
412 this->BPfuncs = this->getProcedures();
415 objPtr->get_line_info(nlines,lines,linesfdptr);
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));
425 if (sym->n_sclass == C_FILE) {
427 if (!sym->n_zeroes) {
428 moduleName = &stringPool[sym->n_offset];
430 memset(tempName, 0, 9);
431 strncpy(tempName, sym->n_name, 8);
432 moduleName = tempName;
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];
441 // x_fname is 14 bytes
442 memset(moduleName, 0, 15);
443 strncpy(moduleName, aux->x_file.x_fname, 14);
448 if(currentSourceFile) delete currentSourceFile;
449 currentSourceFile = new string(moduleName);
450 currentSourceFile = processDirectories(currentSourceFile);
452 if (strrchr(moduleName, '/')) {
453 moduleName = strrchr(moduleName, '/');
457 if (!strcmp(moduleName, mod->fileName().string_of())) {
464 if (!parseActive) continue;
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]) {
474 nmPtr = &stabstr[sym->n_offset];
476 } else if (!stabstr[sym->n_offset-3]) {
477 nmPtr = &stabstr[sym->n_offset];
479 /* has off by two error */
480 nmPtr = &stabstr[sym->n_offset-2];
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]);
493 // names 8 or less chars on inline, not in stabstr
494 memset(tempName, 0, 9);
495 strncpy(tempName, sym->n_name, 8);
499 if ((sym->n_sclass == C_BINCL) ||
500 (sym->n_sclass == C_EINCL) ||
501 (sym->n_sclass == C_FUN)) {
506 funcName = strdup(nmPtr);
507 parseLineInformation(proc,lineInformation,includeFiles,
508 currentSourceFile,funcName,sym,
509 linesfdptr,lines,nlines);
512 if (sym->n_sclass & DBXMASK) {
513 if (sym->n_sclass == C_BCOMM) {
514 char *commonBlockName;
516 commonBlockName = nmPtr;
518 // find the variable for the common block
519 BPatch_image *progam = (BPatch_image *) getObjParent();
521 commonBlockVar = progam->findVariable(commonBlockName);
522 if (!commonBlockVar) {
523 printf("unable to find variable %s\n", commonBlockName);
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);
533 commonBlock->setDataClass(BPatch_dataCommon);
536 commonBlock->beginCommonBlock();
538 } else if (sym->n_sclass == C_ECOMM) {
539 // copy this set of fields
540 BPatch_function *func = findFunction(funcName);
542 printf("unable to locate current function %s\n", funcName);
544 commonBlock->endCommonBlock(func,
545 commonBlockVar->getBaseAddr());
548 // update size if needed
550 commonBlockVar->setSize(commonBlock->getSize());
551 commonBlockVar = 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);
559 if (!tsym->n_zeroes) {
560 staticName = &stringPool[tsym->n_offset];
562 memset(tempName, 0, 9);
563 strncpy(tempName, tsym->n_name, 8);
564 staticName = tempName;
566 BPatch_image *progam = (BPatch_image *) getObjParent();
568 BPatch_variableExpr *staticBlockVar = progam->findVariable(staticName);
569 if (!staticBlockVar) {
570 printf("unable to find static block %s\n", staticName);
571 staticBlockBaseAddr = 0;
573 staticBlockBaseAddr = (Address) staticBlockVar->getBaseAddr();
575 } else if (sym->n_sclass == C_ESTAT) {
576 staticBlockBaseAddr = 0;
579 if (staticBlockBaseAddr && (sym->n_sclass == C_STSYM)) {
580 parseStabString(this, 0, nmPtr,
581 sym->n_value+staticBlockBaseAddr, commonBlock);
583 parseStabString(this, 0, nmPtr, sym->n_value, commonBlock);
591 #if defined(sparc_sun_solaris2_4) || \
592 defined(i386_unknown_solaris2_5) || \
593 defined(i386_unknown_linux2_0)
595 // Gets the stab and stabstring section and parses it for types
597 void BPatch_module::parseTypes()
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;
613 //Using pdmodule to get the image Object.
614 imgPtr = mod->exec();
616 //Using the image to get the Object (class)
617 Object *objPtr = (Object *) &(imgPtr->getObject());
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);
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();
629 //these variables are used to keep track of the source files
630 //and function names being processes at a moment
632 string* currentFunctionName = NULL;
633 Address currentFunctionBase = 0;
634 string* currentSourceFile = NULL;
635 string* absoluteDirectory = NULL;
638 for(i=0;i<stab_nsyms;i++){
639 // if (stabstrs) printf("parsing #%d, %s\n", stabptr[i].type, &stabstrs[stabptr[i].name]);
641 switch(stabptr[i].type){
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;
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;
659 case N_ENDM: /* end of object file */
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, '/');
672 if (!strcmp(modName, mod->fileName().string_of())) {
674 switch (stabptr[i].desc) {
676 setLanguage(BPatch_fortran);
680 setLanguage(BPatch_fortran90);
684 setLanguage(BPatch_assembly);
689 setLanguage(BPatch_c);
693 setLanguage(BPatch_cPlusPlus);
697 setLanguage(BPatch_unknownLanguage);
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);
710 else if(!strlen(&stabstrs[stabptr[i].name])){
711 delete currentSourceFile;
712 currentSourceFile = NULL;
713 delete absoluteDirectory;
714 absoluteDirectory = NULL;
717 *currentSourceFile += &stabstrs[stabptr[i].name];
719 currentSourceFile = processDirectories(currentSourceFile);
723 if(absoluteDirectory){
724 const char* newSuffix = &stabstrs[stabptr[i].name];
725 if(newSuffix[0] == '/'){
726 delete currentSourceFile;
727 currentSourceFile = new string;
730 char* tmp = new char[absoluteDirectory->length()+1];
731 strcpy(tmp,absoluteDirectory->string_of());
732 char* p=strrchr(tmp,'/');
735 delete currentSourceFile;
736 currentSourceFile = new string(tmp);
739 (*currentSourceFile) += newSuffix;
740 currentSourceFile = processDirectories(currentSourceFile);
741 if(currentFunctionName)
742 lineInformation->insertSourceFileName(
743 *currentFunctionName,
747 currentSourceFile = new string(&stabstrs[stabptr[i].name]);
748 currentSourceFile = processDirectories(currentSourceFile);
749 if(currentFunctionName)
750 lineInformation->insertSourceFileName(
751 *currentFunctionName,
757 if (!parseActive) continue;
759 switch(stabptr[i].type){
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,
767 stabptr[i].val+currentFunctionBase);
771 // begin Fortran named common block
772 commonBlockName = (char *) &stabstrs[stabptr[i].name];
774 // find the variable for the common block
775 BPatch_image *progam = (BPatch_image *) getObjParent();
777 commonBlockVar = progam->findVariable(commonBlockName);
778 if (!commonBlockVar) {
779 printf("unable to find variable %s\n", commonBlockName);
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);
788 commonBlock->setDataClass(BPatch_dataCommon);
791 commonBlock->beginCommonBlock();
797 // copy this set of fields
798 assert(currentFunctionName);
799 BPatch_function *func = findFunction(currentFunctionName->string_of());
801 printf("unable to locate current function %s\n", currentFunctionName->string_of());
803 commonBlock->endCommonBlock(func, commonBlockVar->getBaseAddr());
806 // update size if needed
808 commonBlockVar->setSize(commonBlock->getSize());
809 commonBlockVar = NULL;
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
818 case 128: // typedefs and variables -- N_LSYM
819 case 160: // parameter variable -- N_PSYM
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';
831 strcat(ptr,(char *)&stabstrs[stabptr[currentEntry].name]);
834 char* colonPtr = NULL;
835 if(currentFunctionName) delete currentFunctionName;
836 if(!ptr || !(colonPtr = strchr(ptr,':')))
837 currentFunctionName = NULL;
839 char* tmp = new char[colonPtr-ptr+1];
840 strncpy(tmp,ptr,colonPtr-ptr);
841 tmp[colonPtr-ptr] = '\0';
842 currentFunctionName = new string(tmp);
844 currentFunctionBase = 0;
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);
855 currentFunctionBase += info.addr();
858 if(currentSourceFile)
859 lineInformation->insertSourceFileName(
860 *currentFunctionName,
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));
872 ptr3[strlen(ptr)-1] = '\0';
877 // XXX - memory leak on multiple cont. lines
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);
884 //Error parsing the stabstr, return should be \0
885 fprintf(stderr, "Stab string parsing ERROR!! More to parse: %s\n",
895 #endif //end of #if defined(i386_unknown_linux2_0)
897 // Parsing symbol table for Alpha platform
900 #if defined(alpha_dec_osf4_0)
901 extern void parseCoff(BPatch_module *mod, char *exeName,
902 const string& modName, LineInformation* linfo);
904 void BPatch_module::parseTypes()
908 //Using pdmodule to get the image Object.
909 imgPtr = mod->exec();
911 //Get the path name of the process
912 char *file = (char *)(imgPtr->file()).string_of();
914 // with BPatch_functions
915 this->BPfuncs = this->getProcedures();
917 parseCoff(this, file, mod->fileName(),lineInformation);
924 #if defined(i386_unknown_nt4_0) || defined(mips_unknown_ce2_11) //ccw 6 apr 2001
926 // Parsing symbol table for NT platform
929 #include "CodeView.h"
931 void BPatch_module::parseTypes()
936 //Using pdmodule to get the image Object.
937 imgPtr = mod->exec();
939 // with BPatch_functions
940 this->BPfuncs = this->getProcedures();
942 //The code below is adapted from Object-nt.C
943 IMAGE_DEBUG_INFORMATION* pDebugInfo = NULL;
945 // access the module's debug information
946 pDebugInfo = MapDebugInformation(NULL, (LPTSTR)(imgPtr->file()).string_of(), NULL, 0);
947 if( pDebugInfo == NULL )
949 printf("Unable to get debug information!\n");
953 // determine the location of the relevant sections
954 unsigned int i, textSectionId;
956 // currently we care only about the .text and .data segments
957 for( i = 0; i < pDebugInfo->NumberOfSections; i++ )
959 IMAGE_SECTION_HEADER& section = pDebugInfo->Sections[i];
961 if( strncmp( (const char*)section.Name, ".text", 5 ) == 0 ) {
962 textSectionId = i + 1; // note that section numbers are one-based
966 DWORD executableBaseAddress = 0;
967 for( i = 0; i < pDebugInfo->NumberOfSections; i++ )
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
981 // parse the symbols, if available
982 // (note that we prefer CodeView over COFF)
984 if( pDebugInfo->CodeViewSymbols != NULL )
986 // we have CodeView debug information
987 CodeView *cv = new CodeView( (const char*)pDebugInfo->CodeViewSymbols,
990 cv->CreateTypeAndLineInfo(this,executableBaseAddress,
993 else if( pDebugInfo->CoffSymbols != NULL )
995 // we have COFF debug information
996 // ParseCOFFSymbols( pDebugInfo );
1000 // TODO - what to do when there's no debug information?
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
1013 bool BPatch_module::getLineToAddr(unsigned short lineNo,
1014 BPatch_Vector<unsigned long>& buffer,
1017 //if the line information is not created yet return false
1019 if(!lineInformation){
1021 cerr << "BPatch_module::getLineToAddr : ";
1022 cerr << "Line information is not available.\n";
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))
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]);
1042 bool BPatch_module::getVariables(BPatch_Vector<BPatch_variableExpr *> &vars)
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);
1058 #ifdef IBM_BPATCH_COMPAT
1060 bool BPatch_module::getLineNumbers(unsigned int &start, unsigned int &end)
1066 char *BPatch_module::getUniqueString(char *buffer, int length)
1068 getName(buffer, length);
1072 int BPatch_module::getSharedLibType()
1077 int BPatch_module::getBindingType()