From d2251150c76d9c2b139c3cc86aeaedd99ba2d03d Mon Sep 17 00:00:00 2001 From: sagitario Date: Fri, 19 Jun 2009 11:03:14 +0000 Subject: v0.9: * fixed line number info at the end of a segment or when switching to another file because of inline expansion * fixed line numbers > 32767 and sections with 0 line number entries --- CHANGES | 7 +++ INSTALL | 13 +++--- README | 2 +- TODO | 2 - VERSION | 2 +- src/cv2pdb.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/cv2pdb.h | 9 ++++ 7 files changed, 158 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index f687c0a..ee1beda 100644 --- a/CHANGES +++ b/CHANGES @@ -57,3 +57,10 @@ Version history to arrays with less than 1024 entries * renamed data pointer member of dynamic arrays to "ptr" to be consistent with the array property in D. + +2009-06-19 Version 0.9 + + * fixed line number info at the end of a segment or when switching to another file + because of inline expansion + * fixed line numbers > 32767 and sections with 0 line number entries + diff --git a/INSTALL b/INSTALL index 4b82dbd..76bafeb 100644 --- a/INSTALL +++ b/INSTALL @@ -34,11 +34,7 @@ navigating to the file extensions option page (found in Tools -> Options with editor "Microsoft Visual C++". This will also enable display of variables in the "Auto" watch window. -4. the file dviewhelper.dll must be copied into a directory where -the debugger can find it. This can be any directory accessible through your -PATH variable or \Common7\IDE. - -5. You should also add the contents of the file autoexp.snippet to the +4. You should also add the contents of the file autoexp.snippet to the [AutoExpand] and [Visualizer] sections of the file autoexp.dat found in \Common7\Packages\Debugger. Please note that in a standard installation of Visual Studio, the @@ -48,6 +44,13 @@ for the section [hresult]. These lines will enable a convenient display of strings, dynamic arrays, associative arrays, object types and null references. +5. The file dviewhelper.dll must be copied into a directory where +the debugger can find it. This can be any directory accessible through your +PATH variable or \Common7\IDE. Alternatively, +the full path can be specified in the corresponding entries in the +[AutoExpand] section of autoexp.dat. + + Building from source -------------------- The source package comes with a Visual Studio 2008 project and solution diff --git a/README b/README index 96934c7..f9851f8 100644 --- a/README +++ b/README @@ -19,7 +19,7 @@ Features * generates generic debug info for dynamic arrays, associative arrays and delegates * autoexp.dat allows convenient display of dynamic and associative arrays in watch windows * demangles function names for convenient display of callstack -* also works for the Digital Mars C/C++ compiler DMC +* also works debugging executables built with the Digital Mars C/C++ compiler DMC License information ------------------- diff --git a/TODO b/TODO index e217f00..7af7a31 100644 --- a/TODO +++ b/TODO @@ -21,7 +21,5 @@ in the future, but not all have a known solution. * type display of delegate does not have arguments * assoc_array.length cannot be displayed (it is assoc_array.a->nodes) * enum values not displayed -* does not work with debug version of phobos * map dchar to something displayable * workaround for ulong (written by DMD as int[]) -* last code bytes in module not included in last source line diff --git a/VERSION b/VERSION index d5d64b1..67c2297 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = 0.8 +VERSION = 0.9 diff --git a/src/cv2pdb.cpp b/src/cv2pdb.cpp index 48d42b9..4db93b1 100644 --- a/src/cv2pdb.cpp +++ b/src/cv2pdb.cpp @@ -15,11 +15,12 @@ static const int kIncomplete = 0x80; CV2PDB::CV2PDB(PEImage& image) : img(image), pdb(0), dbi(0), libraries(0), rsds(0), modules(0), globmod(0) -, segMap(0), segMapDesc(0), globalTypeHeader(0) +, segMap(0), segMapDesc(0), segFrame2Index(0), globalTypeHeader(0) , globalTypes(0), cbGlobalTypes(0), allocGlobalTypes(0) , userTypes(0), cbUserTypes(0), allocUserTypes(0) , globalSymbols(0), cbGlobalSymbols(0), staticSymbols(0), cbStaticSymbols(0) , udtSymbols(0), cbUdtSymbols(0), allocUdtSymbols(0) +, srcLineStart(0), srcLineSections(0) , pointerTypes(0) , Dversion(2) { @@ -66,6 +67,15 @@ bool CV2PDB::cleanup(bool commit) free(udtSymbols); delete [] pointerTypes; + for(int i = 0; i < srcLineSections; i++) + delete [] srcLineStart[i]; + delete [] srcLineStart; + srcLineStart = 0; + srcLineSections = 0; + + delete [] segFrame2Index; + segFrame2Index = 0; + globalTypes = 0; cbGlobalTypes = 0; allocGlobalTypes = 0; @@ -230,12 +240,20 @@ bool CV2PDB::initSegMap() case sstSegMap: segMap = img.CVP(entry->lfo); segMapDesc = img.CVP(entry->lfo + sizeof(OMFSegMap)); + int maxframe = -1; for (int s = 0; s < segMap->cSeg; s++) { int rc = dbi->AddSec(segMapDesc[s].frame, segMapDesc[s].flags, segMapDesc[s].offset, segMapDesc[s].cbSeg); if (rc <= 0) return setError("cannot add section"); + if (segMapDesc[s].frame > maxframe) + maxframe = segMapDesc[s].frame; } + + segFrame2Index = new int[maxframe + 1]; + memset(segFrame2Index, -1, (maxframe + 1) * sizeof(*segFrame2Index)); + for (int s = 0; s < segMap->cSeg; s++) + segFrame2Index[segMapDesc[s].frame] = s; break; } } @@ -1835,6 +1853,110 @@ bool CV2PDB::addTypes() return true; } +bool CV2PDB::markSrcLineInBitmap(int segIndex, int adr) +{ + if (segIndex < 0 || segIndex >= segMap->cSeg) + return setError("invalid segment info in line number info"); + + int off = adr - segMapDesc[segIndex].offset; + if (off < 0 || off >= (int) segMapDesc[segIndex].cbSeg) + return setError("invalid segment offset in line number info"); + + srcLineStart[segIndex][off] = true; + return true; +} + +bool CV2PDB::createSrcLineBitmap() +{ + if (srcLineStart) + return true; + if (!segMap || !segMapDesc || !segFrame2Index) + return false; + + srcLineSections = segMap->cSeg; + srcLineStart = new char*[srcLineSections]; + memset(srcLineStart, 0, srcLineSections * sizeof (*srcLineStart)); + + for (int s = 0; s < segMap->cSeg; s++) + { + srcLineStart[s] = new char[segMapDesc[s].cbSeg]; + memset(srcLineStart[s], 0, segMapDesc[s].cbSeg); + } + + for (int m = 0; m < countEntries; m++) + { + OMFDirEntry* entry = img.getCVEntry(m); + if(entry->SubSection == sstSrcModule) + { + // mark the beginning of each line + OMFSourceModule* sourceModule = img.CVP(entry->lfo); + int* segStartEnd = img.CVP(entry->lfo + 4 + 4 * sourceModule->cFile); + short* seg = img.CVP(entry->lfo + 4 + 4 * sourceModule->cFile + 8 * sourceModule->cSeg); + + for (int f = 0; f < sourceModule->cFile; f++) + { + int cvoff = entry->lfo + sourceModule->baseSrcFile[f]; + OMFSourceFile* sourceFile = img.CVP (cvoff); + int* lnSegStartEnd = img.CVP(cvoff + 4 + 4 * sourceFile->cSeg); + + for (int s = 0; s < sourceFile->cSeg; s++) + { + int lnoff = entry->lfo + sourceFile->baseSrcLn[s]; + OMFSourceLine* sourceLine = img.CVP (lnoff); + short* lineNo = img.CVP (lnoff + 4 + 4 * sourceLine->cLnOff); + + int cnt = sourceLine->cLnOff; + int segIndex = segFrame2Index[sourceLine->Seg]; + + // also mark the start of the line info segment + if (!markSrcLineInBitmap(segIndex, lnSegStartEnd[2*s])) + return false; + + for (int ln = 0; ln < cnt; ln++) + if (!markSrcLineInBitmap(segIndex, sourceLine->offset[ln])) + return false; + } + } + } + if (entry->SubSection == sstModule) + { + // mark the beginning of each section + OMFModule* module = img.CVP(entry->lfo); + OMFSegDesc* segDesc = img.CVP(entry->lfo + sizeof(OMFModule)); + + for (int s = 0; s < module->cSeg; s++) + { + int seg = segDesc[s].Seg; + int segIndex = seg >= 0 && seg < segMap->cSeg ? segFrame2Index[seg] : -1; + if (!markSrcLineInBitmap(segIndex, segDesc[s].Off)) + return false; + } + } + } + + return true; +} + +int CV2PDB::getNextSrcLine(int seg, unsigned int off) +{ + if (!createSrcLineBitmap()) + return -1; + + int s = segFrame2Index[seg]; + if (s < 0) + return -1; + + off -= segMapDesc[s].offset; + if (off < 0 || off >= segMapDesc[s].cbSeg) + return 0; + + for (off++; off < segMapDesc[s].cbSeg; off++) + if (srcLineStart[s][off]) + break; + + return off + segMapDesc[s].offset; +} + bool CV2PDB::addSrcLines() { for (int m = 0; m < countEntries; m++) @@ -1862,11 +1984,16 @@ bool CV2PDB::addSrcLines() { int lnoff = entry->lfo + sourceFile->baseSrcLn[s]; OMFSourceLine* sourceLine = img.CVP (lnoff); - short* lineNo = img.CVP (lnoff + 4 + 4 * sourceLine->cLnOff); + unsigned short* lineNo = img.CVP (lnoff + 4 + 4 * sourceLine->cLnOff); - int segoff = lnSegStartEnd[2*s]; - int seglength = lnSegStartEnd[2*s + 1] - segoff; + int seg = sourceLine->Seg; int cnt = sourceLine->cLnOff; + if(cnt <= 0) + continue; + int segoff = lnSegStartEnd[2*s]; + // lnSegStartEnd[2*s + 1] only spans until the first byte of the last source line + int segend = getNextSrcLine(seg, sourceLine->offset[cnt-1]); + int seglength = (segend >= 0 ? segend - 1 - segoff : lnSegStartEnd[2*s + 1] - segoff); mspdb::LineInfoEntry* lineInfo = new mspdb::LineInfoEntry[cnt]; for (int ln = 0; ln < cnt; ln++) @@ -1874,7 +2001,7 @@ bool CV2PDB::addSrcLines() lineInfo[ln].offset = sourceLine->offset[ln] - segoff; lineInfo[ln].line = lineNo[ln] - lineNo[0]; } - int rc = mod->AddLines(name, sourceLine->Seg, segoff, seglength, segoff, lineNo[0], + int rc = mod->AddLines(name, seg, segoff, seglength, segoff, lineNo[0], (unsigned char*) lineInfo, cnt * sizeof(*lineInfo)); if (rc <= 0) return setError("cannot add line number info to module"); diff --git a/src/cv2pdb.h b/src/cv2pdb.h index 005b5c7..06f953a 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -100,6 +100,10 @@ public: bool addSymbols(int iMod, BYTE* symbols, int cb, bool addGlobals); bool addSymbols(); + bool markSrcLineInBitmap(int segIndex, int adr); + bool createSrcLineBitmap(); + int getNextSrcLine(int seg, unsigned int off); + bool writeImage(const char* opath); mspdb::Mod* globalMod(); @@ -121,6 +125,8 @@ public: OMFSegMap* segMap; OMFSegMapDesc* segMapDesc; + int* segFrame2Index; + OMFGlobalTypes* globalTypeHeader; unsigned char* globalTypes; @@ -150,6 +156,9 @@ public: bool v3; const char* lastError; + int srcLineSections; + char** srcLineStart; // array of bitmaps per segment, indicating whether src line start is available for corresponding address + double Dversion; }; -- cgit v0.12