////////////////////////////////////////////////////////////////////////////// // MLI: Mod linenumber information API implementation // // Contributed by Amit Mital of VCE, 8/3/93, subsequently C++ized and // modified to use DBI buffers and heaps. (Actually, Jan apologizes for // largely rewriting, but it seemed the best way to learn the code.) #include "pdbimpl.h" #include "dbiimpl.h" inline int adjustLineNumber(LINE lineStart, DWORD line) { return (line == 0x7fff) ? lineStart : (lineStart + line); } BOOL MLI::AddLines(SZ_CONST szSrc, ISECT isect, OFF offCon, CB cbCon, OFF doff, LINE lineStart, IMAGE_LINENUMBER *plnumCoff, CB cb) // szSrc the source file name // isect section index // offMin starting offset // offMax ending offset // lineStart starting line number // plnumCoff pointer to linenumber coff info ?? // cb byte count { assert(cb % sizeof(IMAGE_LINENUMBER) == 0); int clnum = cb / sizeof(IMAGE_LINENUMBER); pSrcFile pSrcFile = AddSrcFile(szSrc); if (!pSrcFile) return FALSE; OFF offMac = offCon + cbCon; // If this contribution does not start a function (linenumber != 0), // offCon is passed in the first lnum entry. if (plnumCoff[0].Linenumber) offCon = plnumCoff[0].Type.VirtualAddress + doff; pSectInfo pSectInfo = pSrcFile->AddSectInfo(isect, offCon, offMac, pool); if (!pSectInfo) return FALSE; if (!pSectInfo->AddLineNumbers(adjustLineNumber(lineStart, plnumCoff[0].Linenumber), offCon, pool)) return FALSE; for (IMAGE_LINENUMBER* pln = &plnumCoff[1]; pln < &plnumCoff[clnum]; pln++) if (!pSectInfo->AddLineNumbers(adjustLineNumber(lineStart, pln->Linenumber), pln->Type.VirtualAddress + doff, pool)) return FALSE; return TRUE; } // Find a pointer to the source file linked list structure - add it if it isn't there pSrcFile MLI::AddSrcFile(SZ_CONST szFile) { for (pSrcFile* ppFile = &pSrcFiles; *ppFile; ppFile = &(*ppFile)->pNext) if (strcmp((*ppFile)->szFile, szFile) == 0) return *ppFile; SZ szName = szCopyPool(szFile, pool); if (!szName || !(*ppFile = new (pool) SrcFile(szName))) return 0; cfiles++; return *ppFile; } // Find the section structure within the source file structure - add it if it is not there pSectInfo SrcFile::AddSectInfo(ISECT isect, OFF offMin, OFF offMax, POOL& pool) { for (pSectInfo* ppSI = &pSectInfos; *ppSI; ppSI = &(*ppSI)->pNext) { if ((*ppSI)->isect == isect && (*ppSI)->offMax + 1 == offMin) { // see if the new start is close enough to the old end (*ppSI)->offMax = offMax; return *ppSI; } } if (!(*ppSI = new (pool) SectInfo(isect, offMin, offMax))) return 0; csect++; return *ppSI; } // Add linenumber information to the record BOOL SectInfo::AddLineNumbers(int linenumber, int offset, POOL& pool) { if (!(*ppTail = new (pool) Lines(offset, linenumber))) return FALSE; ppTail = &(*ppTail)->pNext; cPair++; return TRUE; } BOOL MLI::Emit(Buffer& buffer) { if (!CollectSections()) return FALSE; // emit header information if (!buffer.AppendFmt("ss", cfiles, csect)) return FALSE; // emit base src file offsets OFF off = cbAlign(2*sizeof(USHORT) + cfiles*sizeof(ULONG) + csect*(2*sizeof(ULONG) + sizeof(USHORT))); OFF offFiles = off; for (pSrcFile pFile = pSrcFiles; pFile; pFile = pFile->pNext) { if (!buffer.AppendFmt("l", off)) return FALSE; off += pFile->Size(); } // emit section info for (pSectInfo pSI = pSectInfos; pSI; pSI = pSI->pNext) if (!buffer.AppendFmt("ll", pSI->offMin, pSI->offMax)) return FALSE; for (pSI = pSectInfos; pSI; pSI = pSI->pNext) if (!buffer.AppendFmt("s", pSI->isect)) return FALSE; if (!buffer.AppendFmt("f", (int)dcbAlign(buffer.Size()))) return FALSE; // emit each source file's info off = offFiles; for (pFile = pSrcFiles; pFile; pFile = pFile->pNext) { if (!pFile->Emit(buffer, off)) return FALSE; off += pFile->Size(); } return TRUE; } // Given the module's per-file, per-section information, collect // section information across files, into a flattened, per-module // per-section information summary. // BOOL MLI::CollectSections() { pSectInfo* ppsiTail = &pSectInfos; for (pSrcFile pFile = pSrcFiles; pFile; pFile = pFile->pNext) { for (pSectInfo psiFile = pFile->pSectInfos; psiFile; psiFile = psiFile->pNext) { // search the module's section infos for existing info on this section for (pSectInfo psi = pSectInfos; psi; psi = psi->pNext) if (psi->isect == psiFile->isect) { // found: update extent of section psi->offMin = __min(psi->offMin, psiFile->offMin); psi->offMax = __max(psi->offMax, psiFile->offMax); goto nextSIFile; } // not found: add new section info to module's section info if (!(*ppsiTail = new (pool) SectInfo(psiFile->isect, psiFile->offMin, psiFile->offMax))) return FALSE; ++csect; ppsiTail = &(*ppsiTail)->pNext; nextSIFile:; } } return TRUE; } // calculate the size of the data for the file pointed to; return it's size OFF SrcFile::Size() { // check memoization if (size) return size; // header size size = 2*sizeof(USHORT); // csect, pad size += cbName + 1 + dcbAlign(cbName + 1); // cbname // file table size size += csect * 3*sizeof(ULONG); // baseSrcLn, start, end // line table size for (pSectInfo pSI = pSectInfos; pSI; pSI = pSI->pNext) { pSI->size = sizeof(ULONG); pSI->size += pSI->cPair * (sizeof(ULONG) + sizeof(USHORT)); // offset, line number if (pSI->cPair & 1) pSI->size += sizeof(USHORT); // maintain alignment size += pSI->size; } return size; } BOOL SrcFile::Emit(Buffer& buffer, OFF off) const { if (!buffer.AppendFmt("ss", csect, (USHORT)0 /*pad*/)) return FALSE; off += csect*3*sizeof(ULONG); // space for baseSrcLine offset and start/end off += 2*sizeof(USHORT) + cbName + 1 + dcbAlign(cbName + 1); for (pSectInfo pSI = pSectInfos; pSI; pSI = pSI->pNext) { if (!buffer.AppendFmt("l", off)) return FALSE; off += pSI->size; } for (pSI = pSectInfos; pSI; pSI = pSI->pNext) if (!buffer.AppendFmt("ll", pSI->offMin, pSI->offMax)) return FALSE; if (!buffer.AppendFmt("bzf", (BYTE)cbName, szFile, (int)dcbAlign(cbName + 1))) return FALSE; for (pSI = pSectInfos; pSI; pSI = pSI->pNext) if (!pSI->Emit(buffer)) return FALSE; return TRUE; } BOOL SectInfo::Emit(Buffer& buffer) const { if (!buffer.AppendFmt("ss", isect, cPair)) return FALSE; for (pLines plines = pHead; plines; plines = plines->pNext) if (!buffer.AppendFmt("l", plines->off)) return FALSE; for (plines = pHead; plines; plines = plines->pNext) if (!buffer.AppendFmt("s", plines->line)) return FALSE; if (cPair & 1) if (!buffer.AppendFmt("s", 0)) \ return FALSE; return TRUE; } BOOL MLI::EmitFileInfo(Mod1* pmod1) { if (!pmod1->initFileInfo(cfiles)) return FALSE; int ifile = 0; for (pSrcFile pFile = pSrcFiles; pFile; pFile = pFile->pNext) if (!pmod1->addFileInfo(ifile++, pFile->szFile)) return FALSE; return TRUE; } BOOL MLI::Dump(const Buffer& buffer) const { PB pb = buffer.Start(); struct FSB { short cFile; short cSeg; long baseSrcFile[]; }; FSB* pfsb = (FSB*)pb; pb += sizeof(FSB) + sizeof(long)*pfsb->cFile; struct SE { long start, end; }; SE* pse = (SE*)pb; pb += sizeof(SE)*pfsb->cSeg; short* seg = (short*)pb; pb += sizeof(short)*pfsb->cSeg; printf("HDR: cFile=%u cSeg=%u\n", pfsb->cFile, pfsb->cSeg); for (int ifile = 0; ifile < pfsb->cFile; ifile++) printf("baseSrcFile[%d]=%04lx\n", ifile, pfsb->baseSrcFile[ifile]); for (int iseg = 0; iseg < pfsb->cSeg; iseg++) printf("%d: start=%04lx end=%04lx seg=%02x\n", iseg, pse[iseg].start, pse[iseg].end, seg[iseg]); for (ifile = 0; ifile < pfsb->cFile; ifile++) { PB pb = buffer.Start() + pfsb->baseSrcFile[ifile]; struct SPB { short cSeg; short pad; long baseSrcLn[]; }; SPB* pspb = (SPB*)pb; pb += sizeof SPB + sizeof(long)*pspb->cSeg; SE* pse = (SE*)pb; pb += sizeof(SE)*pspb->cSeg; unsigned char cbName = *pb++; unsigned char* Name = pb; printf(" file[%d]: cSeg=%u pad=%02x cbName=%u, Name=%s\n", ifile, pspb->cSeg, pspb->pad, cbName, Name); for (int iseg = 0; iseg < pspb->cSeg; iseg++) printf(" %d: baseSrcLn=%04lx start=%04lx end=%04lx\n", iseg, pspb->baseSrcLn[iseg], pse[iseg].start, pse[iseg].end); for (iseg = 0; iseg < pspb->cSeg; iseg++) { PB pb = buffer.Start() + pspb->baseSrcLn[iseg]; struct SPO { short Seg; short cPair; long offset[]; }; SPO* pspo = (SPO*)pb; pb += sizeof(SPO) + sizeof(long)*pspo->cPair; short* linenumber = (short*)pb; printf(" seg[%d]: Seg=%02x cPair=%u\n", iseg, pspo->Seg, pspo->cPair); printf(" "); for (int ipair = 0; ipair < pspo->cPair; ipair++) { printf(" %4u:%04lx", linenumber[ipair], pspo->offset[ipair]); if (ipair < pspo->cPair - 1 && (ipair & 3) == 3) printf("\n "); } printf("\n"); } } fflush(stdout); return TRUE; }