mirror of https://github.com/lianthony/NT4.0
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.
342 lines
7.4 KiB
342 lines
7.4 KiB
/***********************************************************************
|
|
* Microsoft (R) 32-Bit Incremental Linker
|
|
*
|
|
* Copyright (C) Microsoft Corp 1992-95. All rights reserved.
|
|
*
|
|
* File: dmalloc.cpp
|
|
*
|
|
* File Comments:
|
|
*
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include "link.h"
|
|
|
|
|
|
#if DBG
|
|
|
|
#include "dmalloc_.h" // private header file
|
|
|
|
#if defined(_M_MRX000) || defined(_M_ALPHA)
|
|
extern "C" void *_ReturnAddress(void);
|
|
|
|
#pragma intrinsic(_ReturnAddress)
|
|
#endif
|
|
|
|
DMPRE dmprePrototype = {0x12345678, 0, 0, 0, 0, 0, 0, 0x9abcdef0};
|
|
DMSUF dmsufPrototype = {0x0fedcba9, 0x87654321};
|
|
|
|
void (*pfnDmallocError)(char *szReason, void *pvBadBlock);
|
|
int fDmallocInitialized = 0, fDmallocUsed = 0;
|
|
int fSuppressDmallocChecking = 0;
|
|
|
|
DMPRE dmpreLinkedListAnchor;
|
|
|
|
#include "db.h" // pick up DBEXEC
|
|
|
|
unsigned long tMalloc = 0; // "time" value printed for logging
|
|
unsigned long TMallocInc()
|
|
{
|
|
return tMalloc++;
|
|
}
|
|
|
|
|
|
void
|
|
InitDmallocPfn(void (*pfnError)(char *szReason, void *pvBadBlock))
|
|
{
|
|
if (fDmallocUsed && !fDmallocInitialized) {
|
|
(*pfnError)("can't initialize ... dmalloc already used", 0);
|
|
} else {
|
|
fDmallocInitialized = 1;
|
|
pfnDmallocError = pfnError;
|
|
dmpreLinkedListAnchor.pdmpreNext = &dmpreLinkedListAnchor;
|
|
dmpreLinkedListAnchor.pdmprePrev = &dmpreLinkedListAnchor;
|
|
}
|
|
}
|
|
|
|
|
|
void *
|
|
__cdecl D_malloc(size_t cb)
|
|
{
|
|
DMPRE *pdmpre;
|
|
void *pvReturn;
|
|
|
|
void *ReturnAddress = (void *)
|
|
#if defined(_M_MRX000) || defined(_M_ALPHA)
|
|
_ReturnAddress();
|
|
#else
|
|
*((long *)&cb - 1);
|
|
#endif
|
|
|
|
fDmallocUsed = 1;
|
|
if (!fDmallocInitialized) {
|
|
pvReturn = malloc(cb);
|
|
} else {
|
|
CheckDmallocHeap();
|
|
|
|
pdmpre = (DMPRE *) malloc(sizeof(DMPRE) + cb + sizeof(DMSUF));
|
|
if (pdmpre == NULL) {
|
|
return(NULL);
|
|
}
|
|
|
|
InitBlockPdmpre(pdmpre, cb);
|
|
|
|
pvReturn = PvUserFromPdmpre(pdmpre);
|
|
}
|
|
|
|
DBEXEC(DB_MALLOC,
|
|
dbprintf("mem: %8ld + %8x %2u\n",
|
|
ReturnAddress,
|
|
pvReturn,
|
|
cb));
|
|
|
|
TMallocInc();
|
|
|
|
return pvReturn;
|
|
}
|
|
|
|
void *
|
|
__cdecl D_calloc(size_t cElement, size_t cbElement)
|
|
{
|
|
void *pv;
|
|
|
|
void *ReturnAddress = (void *)
|
|
#if defined(_M_MRX000) || defined(_M_ALPHA)
|
|
_ReturnAddress();
|
|
#else
|
|
*((long *)&cElement - 1);
|
|
#endif
|
|
|
|
fDmallocUsed = 1;
|
|
|
|
if (!fDmallocInitialized) {
|
|
pv = calloc(cElement, cbElement);
|
|
|
|
DBEXEC(DB_MALLOC,
|
|
dbprintf("mem: %8ld + %8x %2u\n",
|
|
ReturnAddress,
|
|
pv,
|
|
cElement * cbElement));
|
|
|
|
TMallocInc();
|
|
} else {
|
|
CheckDmallocHeap();
|
|
|
|
pv = D_malloc(cElement * cbElement);
|
|
|
|
if (pv == 0) {
|
|
return(0);
|
|
}
|
|
|
|
memset(pv, 0, cElement * cbElement);
|
|
}
|
|
|
|
return(pv);
|
|
}
|
|
|
|
void * __cdecl D_realloc(void *pv, size_t cb)
|
|
{
|
|
DMPRE *pdmpre;
|
|
DMSUF *pdmsuf;
|
|
void *pvOld = pv;
|
|
|
|
void *ReturnAddress = (void *)
|
|
#if defined(_M_MRX000) || defined(_M_ALPHA)
|
|
_ReturnAddress();
|
|
#else
|
|
*((long *)&pv - 1);
|
|
#endif
|
|
|
|
fDmallocUsed = 1;
|
|
if (!fDmallocInitialized) {
|
|
pv = realloc(pv, cb);
|
|
} else {
|
|
if (pv == 0) {
|
|
return D_malloc(cb);
|
|
}
|
|
|
|
CheckDmallocHeap();
|
|
|
|
pdmpre = PdmpreFromPvUser(pv);
|
|
pdmsuf = (DMSUF *)((char *)pv + cb);
|
|
CheckBlockPdmpre(pdmpre);
|
|
ClearBlockPdmpre(pdmpre);
|
|
|
|
pdmpre = (DMPRE *) realloc(pdmpre, cb + sizeof(DMPRE) + sizeof(DMSUF));
|
|
|
|
if (pdmpre == 0) {
|
|
return 0;
|
|
}
|
|
|
|
InitBlockPdmpre(pdmpre, cb);
|
|
|
|
pv = PvUserFromPdmpre(pdmpre);
|
|
}
|
|
|
|
DBEXEC(DB_MALLOC,
|
|
dbprintf("mem: %8ld R %8x %2u %8x\n",
|
|
ReturnAddress,
|
|
pvOld,
|
|
cb,
|
|
pv));
|
|
|
|
TMallocInc();
|
|
|
|
return(pv);
|
|
}
|
|
|
|
void __cdecl D_free(void *pv)
|
|
{
|
|
|
|
void *ReturnAddress = (void *)
|
|
#if defined(_M_MRX000) || defined(_M_ALPHA)
|
|
_ReturnAddress();
|
|
#else
|
|
*((long *)&pv - 1);
|
|
#endif
|
|
|
|
if (pv == 0) {
|
|
return;
|
|
}
|
|
|
|
DBEXEC(DB_MALLOC,
|
|
dbprintf("mem: %8ld - %8x\n",
|
|
ReturnAddress,
|
|
pv));
|
|
|
|
TMallocInc();
|
|
|
|
fDmallocUsed = 1;
|
|
|
|
if (!fDmallocInitialized) {
|
|
free(pv);
|
|
return;
|
|
}
|
|
|
|
CheckDmallocHeap();
|
|
|
|
CheckBlockPdmpre(PdmpreFromPvUser(pv));
|
|
ClearBlockPdmpre(PdmpreFromPvUser(pv));
|
|
|
|
free(PdmpreFromPvUser(pv));
|
|
}
|
|
|
|
|
|
char *
|
|
__cdecl D_strdup(const char *szIn)
|
|
{
|
|
size_t cb = strlen(szIn) + 1;
|
|
char *szOut = (char *) D_malloc(cb);
|
|
|
|
strcpy(szOut, szIn);
|
|
return szOut;
|
|
}
|
|
|
|
|
|
void
|
|
InitBlockPdmpre(DMPRE *pdmpre, size_t cbUser)
|
|
{
|
|
DMSUF *pdmsuf = (DMSUF *)((char *)PvUserFromPdmpre(pdmpre) + cbUser);
|
|
|
|
memcpy(pdmpre, &dmprePrototype, sizeof(DMPRE));
|
|
memcpy(pdmsuf, &dmsufPrototype, sizeof(DMSUF));
|
|
|
|
pdmpre->cbUser = cbUser;
|
|
pdmpre->ulNotCbUser = ~cbUser;
|
|
|
|
pdmpre->pdmpreCur = pdmpre;
|
|
|
|
pdmpre->pdmpreNext = dmpreLinkedListAnchor.pdmpreNext;
|
|
dmpreLinkedListAnchor.pdmpreNext->pdmprePrev = pdmpre;
|
|
UpdateLinksPdmpre(dmpreLinkedListAnchor.pdmpreNext);
|
|
|
|
pdmpre->pdmprePrev = &dmpreLinkedListAnchor;
|
|
dmpreLinkedListAnchor.pdmpreNext = pdmpre;
|
|
|
|
UpdateLinksPdmpre(pdmpre);
|
|
}
|
|
|
|
|
|
void
|
|
CheckBlockPdmpre(DMPRE *pdmpre)
|
|
{
|
|
DMPRE dmpreT;
|
|
DMSUF *pdmsuf, dmsufT;
|
|
void *pvUser;
|
|
|
|
pvUser = PvUserFromPdmpre(pdmpre);
|
|
|
|
if (pdmpre->cbUser != ~pdmpre->ulNotCbUser) {
|
|
(*pfnDmallocError)("dmalloc: block prefix (size) corrupted", pvUser);
|
|
return;
|
|
}
|
|
|
|
pdmsuf = (DMSUF *)((char *) pvUser + pdmpre->cbUser);
|
|
|
|
memcpy(&dmpreT, pdmpre, sizeof(DMPRE));
|
|
dmpreT.cbUser = dmpreT.ulNotCbUser = 0;
|
|
dmpreT.pdmpreNext = dmpreT.pdmprePrev = dmpreT.pdmpreCur = 0;
|
|
dmpreT.ulChecksum = 0;
|
|
|
|
if (memcmp(&dmpreT, &dmprePrototype, sizeof(DMPRE)) != 0) {
|
|
(*pfnDmallocError)("dmalloc: block prefix corrupted", pvUser);
|
|
return;
|
|
}
|
|
|
|
memcpy(&dmsufT, pdmsuf, sizeof(DMSUF));
|
|
if (memcmp(&dmsufT, &dmsufPrototype, sizeof(DMSUF)) != 0) {
|
|
(*pfnDmallocError)("dmalloc: block suffix corrupted", pvUser);
|
|
return;
|
|
}
|
|
|
|
if (pdmpre->ulChecksum !=
|
|
~((unsigned long) pdmpre->pdmpreNext ^
|
|
(unsigned long) pdmpre->pdmprePrev ^
|
|
(unsigned long) pdmpre->pdmpreCur)) {
|
|
(*pfnDmallocError)("dmalloc: block prefix links corrupted", pvUser);
|
|
return;
|
|
}
|
|
|
|
// Things look OK.
|
|
}
|
|
|
|
void
|
|
ClearBlockPdmpre(DMPRE *pdmpre)
|
|
{
|
|
DMSUF *pdmsuf = (DMSUF *)((char *)pdmpre + sizeof(DMPRE) + pdmpre->cbUser);
|
|
|
|
// Unhook it from the list.
|
|
//
|
|
pdmpre->pdmprePrev->pdmpreNext = pdmpre->pdmpreNext;
|
|
UpdateLinksPdmpre(pdmpre->pdmprePrev);
|
|
pdmpre->pdmpreNext->pdmprePrev = pdmpre->pdmprePrev;
|
|
UpdateLinksPdmpre(pdmpre->pdmpreNext);
|
|
|
|
memset(pdmpre, 0xbd, sizeof(DMPRE));
|
|
memset(pdmsuf, 0xbd, sizeof(DMSUF));
|
|
}
|
|
|
|
void
|
|
CheckDmallocHeap()
|
|
{
|
|
DMPRE *pdmpre;
|
|
|
|
if (fSuppressDmallocChecking) {
|
|
return;
|
|
}
|
|
|
|
pdmpre = &dmpreLinkedListAnchor;
|
|
while ((pdmpre = pdmpre->pdmpreNext) != &dmpreLinkedListAnchor) {
|
|
CheckBlockPdmpre(pdmpre);
|
|
}
|
|
}
|
|
|
|
void
|
|
UpdateLinksPdmpre(DMPRE *pdmpre)
|
|
{
|
|
pdmpre->ulChecksum = ~((unsigned long) pdmpre->pdmpreNext ^
|
|
(unsigned long) pdmpre->pdmprePrev ^
|
|
(unsigned long) pdmpre->pdmpreCur);
|
|
}
|
|
|
|
#endif // DBG
|