Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

762 lines
19 KiB

/***********************************************************************
* Microsoft (R) 32-Bit Incremental Linker
*
* Copyright (C) Microsoft Corp 1992-95. All rights reserved.
*
* File: dbiapi.cpp
*
* File Comments:
*
* Implementation of DB Info API
*
***********************************************************************/
#include "link.h"
#include "dbiapi_.h"
// Open Temporary Mod structure
LMod *
ModOpenTemp()
{
LMod *pMod = (LMod *) PvAlloc(sizeof(LMod));
pMod->pfteFirst = NULL;
pMod->pSstMod = ModOpenSSTMod(); // SST Module structure
return pMod;
}
// Close Temporary Mod structure
void ModCloseTemp(LMod *pMod)
{
if (pMod) { // if the Mod exists
ModCloseSSTMod(pMod->pSstMod); // free SSTModule buffer
FreePv(pMod);
}
}
void FreeLineNumInfo(LMod *pMod)
{
ModCloseTemp(pMod);
}
// very funky #define - not needed
#define MODFILESEGINFO(_Mod) ( ((pSSTSrcFile)(_Mod->pSrcFiles->val1))->pSstFileSegInfo )
// Allocate and initialize a SST Module structure
pSSTMod
ModOpenSSTMod()
{
pSSTMod pSstMod = (pSSTMod) PvAlloc(sizeof(SSTMod));
pSstMod->SstModHeader.cfiles = 0; // count of files
pSstMod->SstModHeader.cSeg = 0; // count of contributing segments
pSstMod->pSrcFiles = NULL; // pointer to source file linked list
pSstMod->pMemStruct = NULL; // pointer to memory allocating structure
pSstMod->pSegTemp = NULL;
return pSstMod;
}
void
ModCloseSSTMod(pSSTMod pSstMod)
{
FreeMemStruct(pSstMod); // free all allocated memory
pSstMod->pSrcFiles = NULL; // Set to NULL so that if we try to access pSstMod, we know it's invalid
FreePv(pSstMod);
}
char *
SstFileSzDup(const char *szfilename, size_t cb)
{
char *szfilenew = (char *) GetMem(cb +2);
strcpy(szfilenew, szfilename);
return szfilenew;
}
#define STREQ(_s1,_s2) ( 0 == strcmp(_s1,_s2))
// A nice way of allocating memory - independent of type
#define ALLOCNEW( sizetype) ( (sizetype *) GetMem(sizeof(sizetype)))
// Find a pointer to the source file linked list structure - add it if it isn't there
pSSTSrcFile
ModAddSrcFile(
pSSTMod pSstMod,
const char *szFilename)
{
pSSTSrcFile pSrcfile;
pSSTSrcFile pSrcFiles = pSstMod->pSrcFiles;
size_t cb;
if (pSrcFiles == NULL) {
// This is the first source file
pSstMod->pSrcFiles = pSrcfile = ALLOCNEW(SSTSrcFile);
} else {
for (;;) {
if STREQ(szFilename, pSrcFiles->SstFileInfo.Name) {// check to see if the file is in the list
return pSrcFiles; // return file if it is
}
if (pSrcFiles->next == NULL) { // stop if last file
break;
}
pSrcFiles = pSrcFiles->next;
}
pSrcFiles->next = pSrcfile = ALLOCNEW(SSTSrcFile);
}
pSstMod->SstModHeader.cfiles++; // increment # of files
pSrcfile->SstFileInfo.cSeg = 0; // # of segments initialized to zero
cb = strlen(szFilename);
pSrcfile->SstFileInfo.cbName = (WORD) cb; // store file length
pSrcfile->SstFileInfo.Name = SstFileSzDup(szFilename, cb);
pSrcfile->pSstFileSegInfo = NULL; // No segment info yet
pSrcfile->next = NULL;
return(pSrcfile);
}
// Find the segment structure within the source file structure - add it if it is not there
pSSTFileSegInfo
ModAddFileSegInfo(
pSSTSrcFile pSstSrcFile,
ISEG iseg,
DWORD offMin,
DWORD offMax)
{
pSSTFileSegInfo pSegInfo;
pSSTFileSegInfo pFileSegInfo = pSstSrcFile->pSstFileSegInfo;
if (pFileSegInfo == NULL) {
// No file segments allocated yet
pSstSrcFile->pSstFileSegInfo = pSegInfo = ALLOCNEW(SSTFileSegInfo);
} else {
for (;;) {
if (iseg == pFileSegInfo->iseg) {
// Check if this range immediately preceeds the new range.
// It is sufficient that the existing range is within four
// bytes of the new range to account for alignment padding
// UNDONE: The four byte value doesn't work well for code
// UNDONE: compiled with -G5 for x86 or for most of the RISC
// UNDONE: platforms which use 16 byte section alignment.
if ((pFileSegInfo->offMax < offMin) &&
((pFileSegInfo->offMax + 4) >= offMin)) {
// Merge by updating the end of the existing range
pFileSegInfo->offMax = offMax;
return(pFileSegInfo);
}
}
if (pFileSegInfo->next == NULL) {
break;
}
pFileSegInfo = pFileSegInfo->next;
}
pFileSegInfo->next = pSegInfo = ALLOCNEW(SSTFileSegInfo);
}
pSstSrcFile->SstFileInfo.cSeg++;
pSegInfo->pllistTail = NULL;
pSegInfo->cPair = 0;
pSegInfo->iseg = iseg;
pSegInfo->offMin = offMin;
pSegInfo->offMax = offMax;
pSegInfo->next = NULL;
return pSegInfo;
}
// Add linenumber information to the record
PLLIST
ModAddLineNumbers(
pSSTFileSegInfo pSstSegInfo,
LINE lineStart,
LINE line,
DWORD off)
{
PLLIST pllist = ALLOCNEW(LLIST);
pllist->pllistPrev = pSstSegInfo->pllistTail;
pllist->off = off;
pllist->line = (LINE) ((line == 0x7fff) ? lineStart : (lineStart + line));
pSstSegInfo->cPair++;
pSstSegInfo->pllistTail = pllist;
return(pllist);
}
void
ModAddLinesInfo(
const char *szSrc,
DWORD offMin,
DWORD offMax,
LINE lineStart,
PIMAGE_LINENUMBER plnumCoff,
DWORD cb,
PCON pcon)
// szSrc the source file name
// iseg segment index
// offMin starting offset
// offMax ending offset
// lineStart starting line number
// plnumCoff pointer to linenumber coff info ??
// cb byte count
{
unsigned cline;
unsigned i;
pSSTFileSegInfo pSegInfo;
pSSTSrcFile pSrcFile;
DWORD add_offset;
LMod *pmod = PmodPCON(pcon)->pModDebugInfoApi;
ISEG iseg = PsecPCON(pcon)->isec;
pSSTMod pSstMod = pmod->pSstMod;
assert(cb % sizeof(IMAGE_LINENUMBER) == 0);
cline = cb / sizeof(IMAGE_LINENUMBER);
// Set the memory pointer for allocating memory
ModSetMemPtr(pSstMod);
// Find Source file in list - Add source file to list if it isn't there
pSrcFile = ModAddSrcFile(pSstMod, szSrc);
add_offset = pcon->rva - PsecPCON(pcon)->rva - RvaSrcPCON(pcon);
if (plnumCoff[0].Linenumber != 0) {
// This is not the beginning of a function
offMin = plnumCoff[0].Type.VirtualAddress + add_offset;
}
// See if segment # is in source file list; it not, add it.
pSegInfo = ModAddFileSegInfo(pSrcFile, iseg, offMin, offMax);
ModAddLineNumbers(pSegInfo, lineStart, plnumCoff[0].Linenumber, offMin);
for (i = 1; i < cline; i++) {
ModAddLineNumbers(pSegInfo,
lineStart,
plnumCoff[i].Linenumber,
plnumCoff[i].Type.VirtualAddress + add_offset);
}
}
#if 0
// This routine checks the format - for debugging purposes only
void checkval(char *pb)
{
struct _tm{
WORD cf;
WORD cs;
DWORD bs;
DWORD st;
DWORD end;
WORD sg;
} *ptm;
struct _ftm{
WORD cs;
WORD pd;
DWORD bs[3];
DWORD st[6];
WORD cb;
char Name[10];
} *ftm;
struct _stm{
WORD sg;
WORD cp;
DWORD of[7];
WORD ln[7];
} *stm;
char *bptr ;
char *sptr;
int i,j,k;
DWORD offset;
WORD ln;
ptm = (struct _tm *)(bptr = pb);
printf("Files: %d Seg: %d \n",ptm->cf,ptm->cs);
for (i = 0; i < ptm->cf; i++) { /* for each file */
bptr = pb + 4 + ( i * 4);
offset = *( (int *)bptr);
ftm = (struct _ftm *)(bptr = pb + offset); // bptr points to file record
printf(" Cseg: %d Name: %s size: %d \n",ftm->cs,((char *)bptr + ftm->cs*12 + 5),
*((char *)bptr + ftm->cs*12 + 4) );
sptr = bptr + 4;
for (j = 0; j < ftm->cs; j++) { /* for each segment */
bptr = sptr ;
sptr += 4;
offset = *( (int *)bptr);
stm = (struct _stm *)(bptr = pb + offset);
printf(" Seg: %x cPair: %d\n",stm->sg,stm->cp);
bptr += 4;
for (k = 0; k < stm->cp; k++) {
offset = *(( DWORD *)(bptr + k *4)) ;
ln = *((WORD *)(bptr + ( 4 * stm->cp) + (2 * k)));
printf(" offset:%x linenum: %d \n",offset,ln);
}
}
}
}
#endif
DWORD
ModQueryCbSstSrcModule(
LMod* pmod)
{
pSSTMod pSstMod;
DWORD cb;
pSSTSrcFile pSrcFile;
if ((pmod == NULL) || (pmod->pSstMod->pSrcFiles == NULL)) {
// No linenum structure or the information is invalid
return(0);
}
pSstMod = pmod->pSstMod;
CollectAndSortSegments(pSstMod); // Get contributing segment information
cb = sizeof(WORD) + sizeof(WORD); // space for cfiles & cSeg
cb += pSstMod->SstModHeader.cfiles * sizeof(DWORD);
cb += pSstMod->SstModHeader.cSeg * (2 * sizeof(DWORD) + sizeof(WORD));
if NOTEVEN(pSstMod->SstModHeader.cSeg) { // if odd number of segments
cb += sizeof(WORD); // add padding to mantain alignment
}
pSrcFile = pSstMod->pSrcFiles;
while (pSrcFile) { // for each source file, write it's base offset
cb += CalculateFileSize(pSrcFile);
pSrcFile = pSrcFile->next;
}
return(cb);
}
void
ModQuerySstSrcModule(
LMod* pmod,
BYTE *pBuf,
DWORD cb)
{
pSSTMod pSstMod;
BYTE *pb;
DWORD offset;
pSSTSrcFile pSrcFile;
pSSTFileSegInfo pSeg;
int cSeg;
assert(pmod != NULL);
assert(pmod->pSstMod->pSrcFiles != NULL);
assert(pBuf != NULL);
pSstMod = pmod->pSstMod;
pb = pBuf;
// Emit Header information
*(WORD *) pb = (WORD) pSstMod->SstModHeader.cfiles; // write # of files
pb += sizeof(WORD);
cSeg = pSstMod->SstModHeader.cSeg;
*(WORD *) pb = (WORD) cSeg; // write # of segments
pb += sizeof(WORD);
// Emit base src file offsets
offset = sizeof(WORD) + sizeof(WORD);
offset += pSstMod->SstModHeader.cfiles * sizeof(DWORD);
offset += pSstMod->SstModHeader.cSeg * (2 * sizeof(DWORD) + sizeof(WORD));
if NOTEVEN(cSeg) { // if odd
offset += sizeof(WORD); // padding to mantain alignment
}
pSrcFile = pSstMod->pSrcFiles;
while (pSrcFile) { // for each source file, write it's base offset
*(DWORD *) pb = offset;
pb += sizeof(DWORD);
offset += CalculateFileSize(pSrcFile);
pSrcFile = pSrcFile->next;
}
assert(offset == (DWORD) cb);
pSeg = pSstMod->pSegTemp;
while (pSeg) { // For each segment
*(DWORD *) pb = pSeg->offMin; // Start of segment offset
pb += sizeof(DWORD);
*(DWORD *) pb = pSeg->offMax; // End of segment offset
pb += sizeof(DWORD);
pSeg = pSeg->next;
}
pSeg = pSstMod->pSegTemp;
while (pSeg) { // For each segment
*(WORD *) pb = pSeg->iseg; // Segment index
pb += sizeof(WORD);
pSeg = pSeg->next;
}
if NOTEVEN(cSeg) { // if odd # of segments
pb += sizeof(WORD); // add padding for alignment
}
// We now have the module header written
// now emit each Src File
pSrcFile = pSstMod->pSrcFiles;
while (pSrcFile) {
EmitSrcFile(pSrcFile, pb, (DWORD) (pb - pBuf));
pb += pSrcFile->SstFileInfo.size;
pSrcFile = pSrcFile->next;
}
// REVIEW: place under -db control
// checkval(pBuf); // for debugging only
}
// calculate the size of the data for the file pointed to; return it's size
CalculateFileSize(
pSSTSrcFile pSrcFile)
{
int i;
int size,segsize;
pSSTFileSegInfo pSegInfo;
// NOTE!!! cbNamw is currently 1 byte - the documentation says 2 bytes
size = 2 * sizeof(WORD) + sizeof(BYTE); // space for cSeg , pad and cbname
i = pSrcFile->SstFileInfo.cSeg;
size += i * 4; // space for baseSrcLn
size += i * 8; // space for start/end
size += pSrcFile->SstFileInfo.cbName;
i = WRDALIGN( pSrcFile->SstFileInfo.cbName + 1) ; // determine if the name+ 1 is word aligned
size += i;
// we now have the space required for the file table
// now need to calculate space for the line number table
pSegInfo = pSrcFile->pSstFileSegInfo;
while (pSegInfo != NULL) {
segsize = 4;
i = pSegInfo->cPair;
segsize += i * 4; // space for offset;
segsize += i * 2; // space for linenumber
if NOTEVEN(i) // mantain alignment
segsize += 2;
pSegInfo->size = segsize;
pSegInfo = pSegInfo->next;
size += segsize;
}
pSrcFile->SstFileInfo.size = size;
return size;
}
// Allocate new space for a structure for segment information
pSSTFileSegInfo
GetNewSegInfoPtr(
void)
{
pSSTFileSegInfo pSeg = ALLOCNEW(SSTFileSegInfo);
pSeg->next = NULL;
pSeg->iseg = (WORD) UNSET;
pSeg->offMin = (DWORD) UNSET;
pSeg->offMax = 0;
pSeg->size=0;
return pSeg;
}
void
CollectAndSortSegments(
pSSTMod pSstMod)
{
pSSTFileSegInfo pSegNew;
pSSTFileSegInfo pSegOld;
pSSTSrcFile pFile;
ModSetMemPtr(pSstMod);
if (pSstMod->pSegTemp != NULL) {
// We have already done this in a previous call
return;
}
pSstMod->pSegTemp = pSegNew = GetNewSegInfoPtr();
pSstMod->SstModHeader.cSeg = 0;
pFile = pSstMod->pSrcFiles;
while (pFile != NULL) {
pSSTFileSegInfo pSegInfo = pFile->pSstFileSegInfo;
while (pSegInfo != NULL) {
// Loop through the segment information in the file
WORD iseg = pSegInfo->iseg; // check to see if the sement is already stored
DWORD min = pSegInfo->offMin;
DWORD max = pSegInfo->offMax;
BOOL Found = FALSE;
iseg = pSegInfo->iseg; // check to see if the sement is already stored
min = pSegInfo->offMin;
max = pSegInfo->offMax;
pSegNew = pSstMod->pSegTemp; // pSegTemp is a temporary list of segments associated with a Mod
Found = FALSE;
while (pSegNew != NULL) {
if (iseg == pSegNew->iseg) {
// Found the segment
if ((min < pSegNew->offMin) && ((min+4) >= pSegNew->offMin)) {
pSegNew->offMin = min;
Found = TRUE;
break;
}
if ((max > pSegNew->offMax) && ((max-4) <= pSegNew->offMax)) {
pSegNew->offMax = max;
Found = TRUE;
break;
}
}
pSegOld = pSegNew;
pSegNew = pSegNew->next;
}
if (!Found) {
// We have not found the segment
// pSegOld points to last one, pSegNew points to NULL
pSstMod->SstModHeader.cSeg++;
if (pSegOld->iseg == (WORD) UNSET) {
// 1st node - uninitialized
pSegNew = pSegOld;
} else {
pSegNew = pSegOld->next = GetNewSegInfoPtr();
}
pSegNew->iseg = iseg;
pSegNew->offMin = min;
pSegNew->offMax = max;
}
pSegInfo = pSegInfo ->next;
}
pFile = pFile->next;
}
}
void
EmitSrcFile(
pSSTSrcFile pSstSrcFile,
BYTE *pb,
DWORD offset)
{
pSSTFileSegInfo pSegInfo;
*(WORD *) pb = pSstSrcFile->SstFileInfo.cSeg; // emit # of Segments
pb += sizeof(WORD);
*(WORD *) pb = 0; // emit pad
pb += sizeof(WORD);
offset += sizeof(WORD) + sizeof(WORD);
offset += pSstSrcFile->SstFileInfo.cSeg * 12;
offset += sizeof(BYTE) + pSstSrcFile->SstFileInfo.cbName;
offset += WRDALIGN(pSstSrcFile->SstFileInfo.cbName + 1);
pSegInfo = pSstSrcFile->pSstFileSegInfo;
while (pSegInfo) {
// emit addresses for baseSrcLine
*(DWORD *) pb = offset;
pb += sizeof(DWORD);
offset += pSegInfo->size;
pSegInfo = pSegInfo->next;
}
pSegInfo = pSstSrcFile->pSstFileSegInfo;
while (pSegInfo) {
// emit start/ end offsets of each segment for line number info
*(DWORD *) pb = pSegInfo->offMin; // Start of segment offset
pb += sizeof(DWORD);
*(DWORD *) pb = pSegInfo->offMax; // End of segment offset
pb += sizeof(DWORD);
pSegInfo = pSegInfo->next;
}
*pb++ = (BYTE) pSstSrcFile->SstFileInfo.cbName;
memcpy(pb, pSstSrcFile->SstFileInfo.Name, pSstSrcFile->SstFileInfo.cbName);
pb += pSstSrcFile->SstFileInfo.cbName;
memset(pb, 0, WRDALIGN(pSstSrcFile->SstFileInfo.cbName + 1));
pb += WRDALIGN(pSstSrcFile->SstFileInfo.cbName + 1);
// We now have the file table written
// now emit each segment
pSegInfo = pSstSrcFile->pSstFileSegInfo;
while (pSegInfo) {
EmitSegInfo(pSegInfo, pb);
pb += pSegInfo->size;
pSegInfo = pSegInfo->next;
}
}
void
EmitSegInfo(
pSSTFileSegInfo pSegInfo,
BYTE *pb)
{
PLLIST pllist;
DWORD *pdw;
WORD *pw;
*(WORD *) pb = pSegInfo->iseg;
pb += sizeof(WORD);
*(WORD *) pb = pSegInfo->cPair;
pb += sizeof(WORD);
pllist = pSegInfo->pllistTail;
pb += sizeof(DWORD) * pSegInfo->cPair;
pdw = (DWORD *) pb;
while (pllist) {
*--pdw = pllist->off;
pllist = pllist->pllistPrev;
}
pllist = pSegInfo->pllistTail;
pb += sizeof(WORD) * pSegInfo->cPair;
pw = (WORD *) pb;
while (pllist) {
*--pw = (WORD) pllist->line;
pllist = pllist->pllistPrev;
}
if NOTEVEN(pSegInfo->cPair) { // if the # if cPair is not even, emit an extra word
*(WORD *) pb = 0;
}
}
/* Memory Management routines */
pMEMStruct pCurrentMemStruct;
#define ALLOCSIZE 1024
#define MBUFSIZE ( ALLOCSIZE - sizeof(MEMStruct))
void
ModSetMemPtr(
pSSTMod pSstMod)
{
pMEMStruct ptr = pSstMod->pMemStruct;
if (ptr == NULL) {
ptr = pSstMod->pMemStruct = ModGetNewMemStruct();
}
pCurrentMemStruct = ptr;
while (pCurrentMemStruct->next != NULL) {
pCurrentMemStruct = pCurrentMemStruct->next;
}
}
pMEMStruct
ModGetNewMemStruct(
void)
{
pMEMStruct ptr;
ptr = (pMEMStruct) PvAlloc(ALLOCSIZE);
ptr->next = NULL;
ptr->MemPtr = (void *) (ptr+1);
ptr->cb = 0;
return ptr;
}
void
FreeMemStruct(
pSSTMod pSstMod)
{
pMEMStruct ptr = pSstMod->pMemStruct;
while (ptr) {
pMEMStruct oldptr;
oldptr = ptr;
ptr = ptr->next;
FreePv(oldptr);
}
}
void *
GetMem(size_t cb)
{
void *pv;
size_t cbRound;
cbRound = cb + WRDALIGN(cb); // make sure that we allocate 32-bit aligned memory
assert (cbRound < MBUFSIZE);
if ((pCurrentMemStruct->cb + cbRound) > MBUFSIZE) {
pv = ModGetNewMemStruct();
pCurrentMemStruct->next = (pMEMStruct) pv;
pCurrentMemStruct = (pMEMStruct) pv;
}
pv = ((char *) pCurrentMemStruct->MemPtr) + pCurrentMemStruct->cb;
pCurrentMemStruct->cb += cbRound;
return(pv);
}