2 * Copyright (c) 1996-1999 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.
42 // $Id: CodeView.C,v 1.10 2001/08/29 23:25:27 hollings Exp $
49 #include "common/h/String.h"
50 #include "common/h/Vector.h"
51 #include "dyninstAPI/src/CodeView.h"
52 #include "dyninstAPI/src/NTTypes.h"
55 //---------------------------------------------------------------------------
57 //---------------------------------------------------------------------------
60 CodeView::Parse( void )
65 // verify the CodeView signature
66 // currently, we only support the NB11 format
67 if( strncmp( pBase, "NB11", 4 ) != 0 )
69 // indicate that we do not understand this CodeView format
73 // obtain access to the subsection directory
74 SDHeader* pSDHdr = (SDHeader*)(pBase + *(DWORD*)(pBase + 4));
76 // parse the subsections, extracting the information we need
77 for( i = 0; i < pSDHdr->cDir; i++ )
80 (SDEntry*)(((char*)pSDHdr) +
81 pSDHdr->cbDirHeader + i * pSDHdr->cbDirEntry);
86 ParseModuleSubsection( pEntry );
90 ParseLibrariesSubsection( pEntry );
94 ParseAlignSymSubsection( pEntry );
98 ParseSrcModuleSubsection( pEntry );
104 ParseSymbolsWithHeaderSubsection( pEntry );
108 // it is a subsection type we do not care about - skip it
119 CodeView::ParseModuleSubsection( SDEntry* pEntry )
121 // ensure that the modules vector contains an element for this module
122 // recall that the modules vector uses a one-based index
123 if( pEntry->iMod >= modules.size() )
125 modules.resize( pEntry->iMod + 1 );
128 // make a new entry for this module, starting with this module subsection
129 modules[pEntry->iMod] =
130 Module((ModuleSubsection*)(pBase + pEntry->offset), textId );
135 CodeView::ParseLibrariesSubsection( SDEntry* pEntry )
137 const char* curr = pBase + pEntry->offset;
139 while( curr < (pBase + pEntry->offset + pEntry->cb) )
141 // add an entry for this library
142 libs.push_back(curr);
144 // advance to the next string
151 CodeView::ParseSymbolsWithHeaderSubsection( SDEntry* pEntry )
153 SymHeader* pSymHdr = (SymHeader*)(pBase + pEntry->offset);
155 syms.Parse( ((char*)pSymHdr) + sizeof(SymHeader), pSymHdr->cbSymbol );
160 CodeView::ParseAlignSymSubsection( SDEntry* pEntry )
162 // associate this subsection with the correct module
163 Module& mod = modules[pEntry->iMod];
164 mod.pas = (AlignSymSubsection*)(pBase + pEntry->offset);
166 // parse the symbols represented in this section
167 mod.syms.Parse( (const char*)mod.pas, pEntry->cb );
172 CodeView::ParseSrcModuleSubsection( SDEntry* pEntry )
174 // associate this subsection with the correct module
175 Module& mod = modules[pEntry->iMod];
176 mod.psrc = (SrcModuleSubsection*)(pBase + pEntry->offset);
179 #ifdef BPATCH_LIBRARY
181 #include "LineInformation.h"
184 * @param srcModuleTable the pointer to the beginning of the srcModuleSection
185 * of the debug information. This is the address where
186 * the line information table can be found in the exec.
187 * @param baseAddr the information for line numbers is given relative to
188 * beginning of the module. That is for a line number the
189 * information that can be obtained is the relative addres
190 * with respect to module so we pass also the start addres
191 * of the code in the module.
192 * @param lineInformation lineInformation object of ours
194 * !!!!!! IMPORTANT !!!!!!!
195 * This function only generates the data structures for source files and
196 * the mappings lineNumber <-> lineAddress in the source files. It does not
197 * relate the functions to the lines or files yet. Actual functions are related
198 * to data structure in CreateTypeAndLineInfo function.
202 CodeView::CreateLineInfo( const char* srcModuleTable, DWORD baseAddr ,
203 LineInformation* lineInformation)
205 SrcModuleSubsection* psrc = (SrcModuleSubsection*)srcModuleTable;
207 //get the number of segments in file to skip some fields
208 WORD segInModule = psrc->cSeg;
209 WORD fileInModule = psrc->cFile;
211 //cerr << "NUMBER OF FILES " << fileInModule << "\n";
213 //process each file in the module
214 for(WORD fileE=0 ; fileE < fileInModule ; fileE++){
216 //get the offset and claculate the address for the file record
218 *(DWORD*)(srcModuleTable + (1 + fileE)*sizeof(DWORD));
219 const char* fileEAddress = srcModuleTable + fileEOffset;
220 SrcModuleSubsection::FileInfo* fileI =
221 (SrcModuleSubsection::FileInfo*)fileEAddress;
223 //get the number of segments in this file record
224 WORD segInFile = fileI->cSegFile;
226 //get the pointer for the file name and then create string
228 fileEAddress + sizeof(DWORD)+ 3*segInFile*sizeof(DWORD);
229 LPString currentSourceFile(ptr);
231 //cerr << "FILE NAME : " << (string)currentSourceFile << "\n";
232 lineInformation->insertSourceFileName(string("___tmp___"),
233 (string)currentSourceFile);
235 for(WORD segmentE = 0; segmentE < segInFile; segmentE++){
236 //calculate the segment table offset and the address
238 DWORD segmentEOffset =
239 *(DWORD*)(fileEAddress+ (1+segmentE)*sizeof(DWORD));
240 const char* segmentEAddress =
241 srcModuleTable + segmentEOffset;
243 //find how many pais exist in the table for line numbers
245 *(WORD*)(segmentEAddress + sizeof(WORD));
247 //calculate the starting addresses for parallel arrays
248 const char* lineOffsetAddress =
249 segmentEAddress + sizeof(DWORD);
250 const char* lineNumberAddress =
251 lineOffsetAddress + sizeof(DWORD)*pairInSegment;
253 //for each pair (number,address) mapping insert to
254 //line number data structure
255 for(WORD pairE = 0; pairE < pairInSegment; pairE++){
256 DWORD lineOffset = *(DWORD*)(lineOffsetAddress + pairE*sizeof(DWORD));
257 WORD lineNumber = *(WORD*)(lineNumberAddress + pairE*sizeof(WORD));
258 //cerr << "LINE : " << lineNumber << " -- "
259 // << hex << (lineOffset + baseAddr)
260 // << " : " << lineOffset << dec << "\n";
261 lineInformation->insertLineAddress(
263 (string)currentSourceFile,
264 lineNumber,lineOffset + baseAddr);
268 //since at this point no function info is available we used
269 //a temporary function to insert the data but later this
270 //function is not going to be used so we delete the entry for
274 lineInformation->deleteFunction(string("___tmp___"));
278 // Create type information for a specific module
281 CodeView::CreateTypeAndLineInfo( BPatch_module *inpMod , DWORD baseAddr ,
282 LineInformation* lineInformation)
286 // verify the CodeView signature
287 // currently, we only support the NB11 format
288 if( strncmp( pBase, "NB11", 4 ) != 0 )
290 // indicate that we do not understand this CodeView format
294 // obtain access to the subsection directory
295 SDHeader* pSDHdr = (SDHeader*)(pBase + *(DWORD*)(pBase + 4));
297 //Find inp module name
298 char inpModName[1024];
299 inpMod->getName(inpModName, 1024);
300 char *ptr = strrchr(inpModName, '.');
305 SDEntry *alignSubSec = NULL;
307 TypesSubSection *pTypeBase = NULL;
308 SrcModuleSubsection* lineData = NULL; //to check line info is available
310 // parse the subsections, extracting the information we need
311 for( i = 0; i < pSDHdr->cDir; i++ )
314 (SDEntry*)(((char*)pSDHdr) +
315 pSDHdr->cbDirHeader + i * pSDHdr->cbDirEntry);
317 switch( pEntry->sst )
321 ModuleSubsection *pmod = (ModuleSubsection *)
322 (pBase + pEntry->offset);
324 LPString lpsName ( ((char*)pmod) + sizeof(ModuleSubsection) +
325 pmod->cSeg * sizeof( ModuleSubsection::SegInfo ) );
328 strcpy(modName, ((string)lpsName).string_of());
329 ptr = strrchr(modName, '.');
333 if ( strcmp(modName, inpModName) == 0 ) {
334 // We found correct module
335 mod = new Module(pmod, textId);
343 // check whether this subsection is in the correct module
344 if (mod && (iMod == pEntry->iMod) ) {
345 mod->pas = (AlignSymSubsection*)(pBase + pEntry->offset);
346 alignSubSec = pEntry;
351 pTypeBase = (TypesSubSection *) (pBase + pEntry->offset);
355 if(mod && (iMod == pEntry->iMod)){
356 lineData = (SrcModuleSubsection*)(pBase + pEntry->offset);
357 mod->psrc = lineData ;
361 // it is a subsection type we do not care about - skip it
367 return; //We could not find the input module
369 //if the debug section do not contain the line info section for
370 //the module we return witha warning.
372 CreateLineInfo((const char*)(mod->psrc),baseAddr,
375 cerr << "WARNING : CodeView::CreateTypeAndLineInfo"
376 << " can not create Line Information for : "
377 << inpModName << ".\n";
379 mod->syms.CreateTypeInfo( (const char *)mod->pas, alignSubSec->cb,
380 pTypeBase, inpMod,lineInformation);
382 #endif // BPATCH_LIBRARY
384 //---------------------------------------------------------------------------
385 // CodeView::Symbols methods
386 //---------------------------------------------------------------------------
390 CodeView::Symbols::Parse( const char* pSymBase, DWORD cb )
392 // scan the symbols linearly
393 SymRecord* curr = (SymRecord*)pSymBase;
394 while( ((char*)curr) < (pSymBase + cb) )
396 // handle the symbol record
397 switch( curr->index )
400 // add the entry to our list of functions
401 lprocs.push_back(( (SymRecordProc*)curr ));
405 // add the entry to our list of functions
406 gprocs.push_back(( (SymRecordProc*)curr ));
410 // add the entry to our list of variables
411 lvars.push_back(( (SymRecordData*)curr ));
415 // add the entry to our list of variables
416 gvars.push_back(( (SymRecordData*)curr ));
420 labels.push_back(( (SymRecordLabel*)curr ));
424 bprels.push_back(( (SymRecordBPRel*)curr ));
428 thunks.push_back(( (SymRecordThunk*)curr ));
432 // nothing to do for end markers
436 // skip padding records
440 pubs.push_back((SymRecordData*)curr);
444 // it is a record type that we do not care about
448 // advance to the next symbol
449 curr = (SymRecord*)(((char*)curr) + curr->length + sizeof(WORD));
456 CodeView::Symbols::operator=( const CodeView::Symbols& syms )
460 gprocs = syms.gprocs; // global functions
461 lprocs = syms.lprocs; // local functions
462 gvars = syms.gvars; // global variables
463 lvars = syms.lvars; // local variables
464 bprels = syms.bprels; // stack variables
465 labels = syms.labels; // labels
466 thunks = syms.thunks; // thunks (code outside of functions)
467 pubs = syms.pubs; // public (catch-all) symbols
472 #ifdef BPATCH_LIBRARY
474 // Creates type information for the symbols in the specified module
477 CodeView::Symbols::CreateTypeInfo( const char* pSymBase, DWORD cb,
478 TypesSubSection *pTypeBase, BPatch_module *mod ,
479 LineInformation* lineInformation)
481 char currFuncName[1024];
486 BPatch_function *fp = NULL;
487 BPatch_type *ptrType = NULL;
488 BPatch_localVar *locVar = NULL;
490 //Initialize required member variables
491 char *startAddr = ((char *)pTypeBase->offType) + pTypeBase->cType * sizeof(DWORD);
493 // scan the symbols linearly
494 SymRecord* curr = (SymRecord*)pSymBase;
495 while( ((char*)curr) < (pSymBase + cb) )
497 // handle the symbol record
498 switch( curr->index )
502 len = (int) ( (SymRecordProc*)curr )->name[0];
503 strncpy(currFuncName, &( (SymRecordProc*)curr )->name[1], len);
504 currFuncName[len] = '\0';
506 //Find function in the module
507 fp = mod->findFunction(currFuncName);
509 lineInformation->insertFunction(
510 string(currFuncName),
511 (Address)(fp->getBaseAddr()),
513 DWORD offset = pTypeBase->offType[((SymRecordProc*)curr )->procType - 0x1000];
514 TypeRec *trec = (TypeRec *)(startAddr + offset);
515 if (trec->leaf == LF_PROCEDURE)
516 fparam = ((ProcTypeRec *)trec)->parms;
517 else if (trec->leaf == LF_MFUNCTION) {
518 BPatch_type *thisType = ExploreType(mod,
519 ((MFuncTypeRec *)trec)->thisType,
520 pTypeBase, startAddr);
522 !strcmp(thisType->getName(), "void"))
523 fparam = ((MFuncTypeRec *)trec)->parms;
525 fparam = ((MFuncTypeRec *)trec)->parms + 1;
528 ptrType = ExploreType(mod, ((ProcTypeRec *)trec)->rvtype,
529 pTypeBase, startAddr);
531 fp->setReturnType(ptrType);
538 // add the entry to our list of variables
539 len = (int) ( (SymRecordData*)curr )->name[0];
540 strncpy(symName, &( (SymRecordData*)curr )->name[1], len);
542 ptrType = ExploreType(mod, ( (SymRecordData*)curr )->type,
543 pTypeBase, startAddr);
545 mod->moduleTypes->addGlobalVariable(symName, ptrType);
549 len = (int) ( (SymRecordBPRel*)curr )->name[0];
550 strncpy(symName, &( (SymRecordBPRel*)curr )->name[1], len);
552 if (fp && ( (SymRecordBPRel*)curr )->offset) {
553 ptrType = ExploreType(mod, ( (SymRecordBPRel*)curr )->type,
554 pTypeBase, startAddr);
556 locVar = new BPatch_localVar(symName, ptrType, -1,
557 ((SymRecordBPRel*)curr )->offset);
559 fp->funcParameters->addLocalVar(locVar);
560 fp->addParam(symName, ptrType, -1,
561 ((SymRecordBPRel*)curr )->offset);
565 fp->localVariables->addLocalVar(locVar);
576 if ( ((SymRecordCons *)curr)->value < LF_NUMERIC )
577 name = ((SymRecordCons *)curr)->name;
579 name = (char *)&((SymRecordCons *)curr)->value +
583 strncpy(symName, &name[1], len);
586 ptrType = ExploreType(mod, ( (SymRecordCons *)curr )->type,
587 pTypeBase, startAddr);
589 mod->moduleTypes->addGlobalVariable(symName, ptrType);
598 // it is a record type that we do not care about
602 // advance to the next symbol
603 curr = (SymRecord*)(((char*)curr) + curr->length + sizeof(WORD));
608 // Mapping from CodeView types to DyninstAPI types
612 CodeView::Symbols::CreatePrimitiveType(DWORD index)
614 BPatch_type *lastType;
617 case T_NOTYPE: //Regarded as void
619 lastType = new BPatch_type("void", -11, BPatch_built_inType, 0);
627 lastType = new BPatch_type("void", -11, BPatch_built_inType, 0);
628 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
632 lastType = new BPatch_type("char", -2, BPatch_built_inType, 1);
646 lastType = new BPatch_type("char", -2, BPatch_built_inType, 1);
647 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
650 lastType = new BPatch_type("unsigned char", -5, BPatch_built_inType, 1);
658 lastType = new BPatch_type("unsigned char", -5, BPatch_built_inType, 1);
659 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
663 lastType = new BPatch_type("short", -3, BPatch_built_inType, 2);
677 lastType = new BPatch_type("short", -3, BPatch_built_inType, 2);
678 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
682 lastType = new BPatch_type("unsigned short", -7, BPatch_built_inType, 2);
696 lastType = new BPatch_type("unsigned short", -7, BPatch_built_inType, 2);
697 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
700 lastType = new BPatch_type("int", -1, BPatch_built_inType, 4);
708 lastType = new BPatch_type("int", -1, BPatch_built_inType, 4);
709 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
712 lastType = new BPatch_type("unsigned int", -8, BPatch_built_inType, 4);
720 lastType = new BPatch_type("unsigned int", -8, BPatch_built_inType, 4);
721 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
724 lastType = new BPatch_type("long", -4, BPatch_built_inType, sizeof(long));
732 lastType = new BPatch_type("long", -4, BPatch_built_inType, sizeof(long));
733 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
736 lastType = new BPatch_type("unsigned long", -10, BPatch_built_inType,
737 sizeof(unsigned long));
745 lastType = new BPatch_type("unsigned long", -10, BPatch_built_inType,
746 sizeof(unsigned long));
747 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
750 lastType = new BPatch_type("float", -12, BPatch_built_inType,
759 lastType = new BPatch_type("float", -12, BPatch_built_inType,
761 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
764 lastType = new BPatch_type("double", -13, BPatch_built_inType,
773 lastType = new BPatch_type("double", -13, BPatch_built_inType,
775 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
779 lastType = new BPatch_type("long long", -32, BPatch_built_inType, 8);
793 lastType = new BPatch_type("long long", -32, BPatch_built_inType, 8);
794 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
797 lastType = new BPatch_type("long double", -14, BPatch_built_inType,
798 sizeof(long double));
806 lastType = new BPatch_type("long double", -14, BPatch_built_inType,
807 sizeof(long double));
808 lastType = new BPatch_type("", -1, BPatch_pointer, lastType);
817 BPatch_visibility AccessType(WORD attribute) {
818 switch(attribute & 0x3) {
820 return BPatch_private;
822 return BPatch_protected;
824 return BPatch_public;
827 return BPatch_visUnknown;
831 CodeView::Symbols::FindFields(BPatch_module *mod, BPatch_type *mainType, int count,
832 DWORD index, TypesSubSection *pTypeBase, char *startAddr)
834 BPatch_type *memberType = NULL;
835 char fname[1024], *name;
840 DWORD offset = pTypeBase->offType[index - 0x1000];
841 TypeRec *trec = (TypeRec *)(startAddr + offset);
843 if (trec->leaf != LF_FIELDLIST) {
844 printf("Invalid field list entry!\n");
848 // printf("Number of fields: %d\n", count);
850 unsigned char *ptr = ((unsigned char *)trec) + sizeof(TypeRec);
851 for(int i=0; i<count; ++i) {
852 switch( *((WORD *)ptr) ) {
854 if ( ((LFMember *)ptr)->offset < LF_NUMERIC ) {
855 foffset = ((LFMember *)ptr)->offset;
856 name = ((LFMember *)ptr)->name;
859 // Need to find offset
861 name = ( (char *) &((LFMember *)ptr)->offset) +
865 strncpy(fname, &name[1], (int)name[0]);
866 fname[(int)name[0]] = '\0';
867 memberType = ExploreType(mod, ((LFMember *)ptr)->type,
868 pTypeBase, startAddr);
869 if (memberType == NULL)
870 memberType = mod->moduleTypes->findType("void");
872 mainType->addField(fname, BPatch_scalar, memberType, foffset*8,
873 memberType->getSize(),
874 AccessType(((LFMember *)ptr)->attribute) );
876 // printf("Field %d is LF_MEMBER %s\n", i, fname);
878 // Move to the next record
879 ptr = ((unsigned char *)name) + (int)name[0] + 1;
883 if ( ((LFEnumerate *)ptr)->value < LF_NUMERIC ) {
884 fvalue = ((LFEnumerate *)ptr)->value;
885 name = ((LFEnumerate *)ptr)->name;
888 // Need to find value
890 name = ( (char *) &((LFEnumerate *)ptr)->value) +
894 strncpy(fname, &name[1], (int)name[0]);
895 fname[(int)name[0]] = '\0';
896 mainType->addField(name, BPatch_scalar, fvalue);
898 // printf("Field %d is LF_ENUMERATE %s\n", i, fname);
900 ptr = ((unsigned char *)name) + (int)name[0] + 1;
905 //Find base class type identifier
906 int baseID = ((LFBclass *)ptr)->type;
908 //Find offset of the base class
909 if ( ((LFBclass *)ptr)->offset < LF_NUMERIC ) {
910 foffset = ((LFBclass *)ptr)->offset;
911 ptr += sizeof(LFBclass);
914 //Need to calculate offset
916 ptr = (unsigned char *)&((LFBclass *)ptr)->offset +
921 BPatch_type *baseCl = mod->moduleTypes->findType(baseID);
922 if (baseCl && (baseCl->getDataClass() == BPatch_structure) ) {
924 //Get field descriptions of the base type
925 BPatch_Vector<BPatch_field *> *baseClFields =
926 baseCl->getComponents();
927 for(int fieldNum=0; fieldNum < baseClFields->size();
930 BPatch_field *field = (*baseClFields)[fieldNum];
932 if (field->getVisibility() == BPatch_private)
933 continue; //Can not add this member
935 mainType->addField(field->getName(),
936 field->getTypeDesc(),
938 foffset*8 + field->getOffset(),
939 field->getVisibility());
943 // printf("Field %d is LF_BCLASS\n", i);
949 // printf("LF_ONEMETHOD attribute %d\n", ((LFOnemethod *)ptr)->attribute );
950 if ( ((LFOnemethod *)ptr)->attribute & 0x10 ) {
951 //This is an introducing virtual method.
952 name = ((LFOnemethod *)ptr)->name + sizeof(DWORD);
955 name = ((LFOnemethod *)ptr)->name;
957 strncpy(fname, &name[1], (int)name[0]);
958 fname[(int)name[0]] = '\0';
959 memberType = ExploreType(mod, ((LFOnemethod *)ptr)->type,
960 pTypeBase, startAddr);
962 if (memberType == NULL)
963 memberType = mod->moduleTypes->findType("void");
965 mainType->addField(fname, BPatch_dataMethod, memberType, 0, 0);
967 // printf("Field %d is LF_ONEMETHOD %s\n", i, fname);
969 ptr = (unsigned char *)name + (int)name[0] + 1;
973 strncpy(fname, &((LFMethod *)ptr)->name[1],
974 (int)((LFMethod *)ptr)->name[0]);
975 fname[(int)((LFMethod *)ptr)->name[0]] = '\0';
976 memberType = mod->moduleTypes->findType("void");
977 mainType->addField(fname, BPatch_dataMethod, memberType, 0, 0);
978 ptr = (unsigned char *)((LFMethod *)ptr)->name +
979 (int)((LFMethod *)ptr)->name[0] + 1;
981 // printf("Field %d is LF_METHOD %s\n", i, fname);
986 //Do not know what to do! Just skip this
987 strncpy(fname, &((LFStmember *)ptr)->name[1],
988 (int)((LFStmember *)ptr)->name[0]);
989 fname[(int)((LFStmember *)ptr)->name[0]] = '\0';
991 // printf("Field %d is LF_STMEMBER %s\n", i, fname);
993 ptr = (unsigned char *)((LFStmember *)ptr)->name +
994 (int)((LFStmember *)ptr)->name[0] + 1;
998 // Do not know what to do! Just skip it
999 if ( ((LFVbclass *)ptr)->vbpoff < LF_NUMERIC )
1000 ptr = (unsigned char *)&((LFVbclass *)ptr)->vbpoff +
1003 ptr = (unsigned char *)&((LFVbclass *)ptr)->vbpoff +
1006 if ( *((WORD *)ptr) < LF_NUMERIC )
1007 ptr += sizeof(WORD);
1009 ptr += sizeof(DWORD);
1011 // printf("Field %d is LF_LF_VBCLASS or LF_IVBCLASS\n", i);
1015 // Do not know what to do! Just skip it.
1016 // printf("Field %d is LF_VFUNCTAB\n", i);
1018 ptr += sizeof(LFVfunctab);
1023 printf("LF_FRIENDFCN is not handled!\n");
1026 printf("LF_INDEX is not handled!\n");
1029 printf("LF_NESTTYPE is not handled!\n");
1032 printf("LF_FRIENDCLS is not handled!\n");
1035 printf("LF_VFUNCOFF is not handled!\n");
1038 printf("LF_NESTTYPEEX is not handled!\n");
1040 case LF_MEMBERMODIFY:
1041 printf("LF_MEMBERMODIFY is not handled!\n");
1044 // printf("Unknown leaf index in field %d %x\n", i, *((WORD *)ptr));
1048 //Check for padding bytes
1049 while (*ptr > LF_PAD0)
1050 ptr += (*ptr - LF_PAD0);
1055 CodeView::Symbols::ExploreType(BPatch_module *mod, DWORD index,
1056 TypesSubSection *pTypeBase, char *startAddr)
1058 BPatch_type *lastType, *newType = NULL;
1059 char typeName[1024];
1061 //First check whether or not this type was created before
1062 newType = mod->moduleTypes->findType(index);
1066 if (index < 0x1000) {
1067 // This is a primitive type
1068 newType = CreatePrimitiveType(index);
1069 //Add type definition
1071 newType->setID(index);
1072 mod->moduleTypes->addType(newType);
1078 //Handle non-primitive type
1079 DWORD offset = pTypeBase->offType[index - 0x1000];
1080 TypeRec *trec = (TypeRec *)(startAddr + offset);
1082 switch(trec->leaf) {
1084 newType = ExploreType(mod, ((LFModifier *)trec)->index,
1085 pTypeBase, startAddr);
1088 lastType = ExploreType(mod, ((LFPointer *)trec)->type,
1089 pTypeBase, startAddr);
1091 newType = new BPatch_type("", -1, BPatch_pointer, lastType);
1094 lastType = ExploreType(mod, ((LFArray *)trec)->elemtype,
1095 pTypeBase, startAddr);
1100 if ( ((LFArray *)trec)->length < LF_NUMERIC ) {
1101 arrLen = ((LFArray *)trec)->length;
1102 arrName = (char *) ((LFArray *)trec)->name;
1105 //Need to calculate arrLen
1107 arrName = ( (char *) &((LFArray *)trec)->length ) +
1110 strncpy(typeName, &arrName[1], (int)arrName[0]);
1111 typeName[(int)arrName[0]] = '\0';
1113 int high = arrLen / lastType->getSize();
1114 newType = new BPatch_type(typeName, -1, BPatch_array, lastType,
1123 if ( ((LFClass *)trec)->length < LF_NUMERIC ) {
1124 classLen = ((LFClass *)trec)->length;
1125 className = (char *) ((LFClass *)trec)->name;
1128 //Need to calculate classLen
1130 className = ( (char *) &((LFClass *)trec)->length ) +
1133 strncpy(typeName, &className[1], (int)className[0]);
1134 typeName[(int)className[0]] = '\0';
1136 if (trec->leaf == LF_CLASS)
1137 newType = new BPatch_type(typeName, -1, BPatch_dataTypeClass, classLen);
1139 newType = new BPatch_type(typeName, -1, BPatch_dataStructure,
1141 // printf("Name of the structure %s\n", typeName);
1142 FindFields(mod, newType, ((LFClass *)trec)->count,
1143 ((LFClass *)trec)->field, pTypeBase, startAddr);
1150 if ( ((LFUnion *)trec)->length < LF_NUMERIC ) {
1151 unionLen = ((LFUnion *)trec)->length;
1152 unionName = (char *) ((LFUnion *)trec)->name;
1155 //Need to calculate classLen
1157 unionName = ( (char *) &((LFUnion *)trec)->length ) +
1160 strncpy(typeName, &unionName[1], (int)unionName[0]);
1161 typeName[(int)unionName[0]] = '\0';
1163 newType = new BPatch_type(typeName, -1, BPatch_union, unionLen);
1164 FindFields(mod, newType, ((LFClass *)trec)->count,
1165 ((LFClass *)trec)->field, pTypeBase, startAddr);
1170 strncpy(typeName, &((LFEnum *)trec)->name[1],
1171 (int)((LFEnum *)trec)->name[0]);
1172 typeName[(int)((LFEnum *)trec)->name[0]] = '\0';
1174 newType = new BPatch_type(typeName, -1, BPatch_enumerated);
1175 FindFields(mod, newType, ((LFEnum *)trec)->count,
1176 ((LFEnum *)trec)->fList, pTypeBase, startAddr);
1186 newType->setID(index);
1187 mod->moduleTypes->addType(newType);
1190 #endif // BPATCH_LIBRARY
1192 //---------------------------------------------------------------------------
1193 // CodeView::Module methods
1194 //---------------------------------------------------------------------------
1196 // a zero-argument constructor is required by the vector class
1197 CodeView::Module::Module( void )
1207 CodeView::Module::Module( CodeView::ModuleSubsection* pModule,
1208 unsigned int textId )
1215 // A module may contribute code to several segments (sections)
1216 // in the image. Paradyn assumes that the .text section
1217 // is the only one that matters with respect to code, so
1218 // we provide the offset of the code from this module
1224 // search the module subsection's segInfo array to find
1225 // the offset for the code from this module in the .text section
1226 const CodeView::ModuleSubsection::SegInfo* pSects =
1227 (const CodeView::ModuleSubsection::SegInfo*)(((const char*)pmod)
1228 + sizeof(ModuleSubsection));
1229 for( i = 0; i < pmod->cSeg; i++ )
1231 if( pSects[i].seg == textId )
1233 offsetText = pSects[i].offset;
1234 cbText = pSects[i].cbSeg;
1237 // check whether there are other ranges that
1238 // this module contributes to in the text segment
1240 for( j = i + 1; j < pmod->cSeg; j++ )
1242 if( pSects[j].seg == textId )
1245 "warning: multiple contributions to text section"
1257 CodeView::Module::operator=( const CodeView::Module& mod )
1261 pmod = mod.pmod; // sstModule subsection
1262 pas = mod.pas; // sstAlignSym subsection
1263 psrc = mod.psrc; // sstSrcModule subsection
1264 syms = mod.syms; // symbols from the sstAlignSym subsection
1266 offsetText = mod.offsetText;
1267 cbText = mod.cbText;
1274 CodeView::Module::GetName( void ) const
1276 LPString lpsName( ((char*)pmod) +
1277 sizeof(ModuleSubsection) +
1278 pmod->cSeg * sizeof( ModuleSubsection::SegInfo ) );
1279 return (string)lpsName;
1283 // note that although the sstSrcModule subsection may
1284 // indicate more than one source file contributed to the code
1285 // in this module, we always only consider the first
1286 // (Paradyn is not designed to handle more than one source
1287 // file per module, and the first source file seems to be
1288 // the "main" source file for the module)
1290 CodeView::Module::GetSourceName( void ) const
1292 // verify that we have a source file information for this module
1298 // parse the sstSrcModule subsection to extract the first
1300 const char* curr = (const char*)psrc;
1303 // skip over the header...
1305 // skip over file and segment counts
1306 assert( psrc->cFile > 0 );
1307 curr += 2 * sizeof( WORD );
1309 // ...skip over the baseSrcFile table...
1310 curr += (psrc->cFile * sizeof( DWORD ));
1312 // ...skip over the start/end table...
1313 curr += (psrc->cSeg * 2 * sizeof( DWORD ));
1315 // ...skip over the seg table...
1316 curr += (psrc->cSeg * sizeof( WORD ));
1317 if( (psrc->cSeg % 2) != 0 )
1319 // skip alignment padding
1320 curr += sizeof(WORD);
1324 // we're now pointing at the information for the first source file
1326 SrcModuleSubsection::FileInfo* fi = (SrcModuleSubsection::FileInfo*)curr;
1327 curr += sizeof( WORD );
1330 curr += sizeof(WORD);
1332 // skip the line number/address mapping offset table
1333 curr += (fi->cSegFile * sizeof( DWORD ));
1335 // skip over the start/end offset table
1336 curr += (fi->cSegFile * 2 * sizeof( DWORD ));
1338 // we're now at the source file name
1339 // length in chars in the first byte, then the source file name chars
1340 LPString lpsName( curr );
1345 // A module may contribute code to several segments (sections)
1346 // in the image. Paradyn assumes that the .text section
1347 // is the only one that matters with respect to code, so
1348 // we provide the offset of the code from this module
1351 CodeView::Module::GetTextBounds( DWORD& offset, DWORD& cb ) const
1357 offset = offsetText;