1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_tools.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <string.h> 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include <tools/debug.hxx> 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir // ----------------------------------------------------------------------- 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir #if defined( DBG_UTIL ) && defined( WNT ) && defined( INTEL ) 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir struct ImpDbgStackTree 40*cdf0e10cSrcweir { 41*cdf0e10cSrcweir ImpDbgStackTree* pLeft_; 42*cdf0e10cSrcweir ImpDbgStackTree* pRight_; 43*cdf0e10cSrcweir ImpDbgStackTree* pCaller_; 44*cdf0e10cSrcweir ImpDbgStackTree* pSub_; 45*cdf0e10cSrcweir sal_uIntPtr nIP_; 46*cdf0e10cSrcweir sal_uIntPtr nBytesLeak_; 47*cdf0e10cSrcweir sal_uIntPtr nBytesPeak_; 48*cdf0e10cSrcweir sal_uIntPtr nBytes_; 49*cdf0e10cSrcweir sal_uIntPtr nCountLeak_; 50*cdf0e10cSrcweir sal_uIntPtr nCountPeak_; 51*cdf0e10cSrcweir sal_uIntPtr nCount_; 52*cdf0e10cSrcweir sal_uIntPtr nMax_; 53*cdf0e10cSrcweir sal_uIntPtr nMin_; 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir ImpDbgStackTree( ImpDbgStackTree* pSub, sal_uIntPtr nIP ); 56*cdf0e10cSrcweir ~ImpDbgStackTree(); 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir ImpDbgStackTree* Add( sal_uIntPtr nAlloc, sal_uIntPtr* pBP, sal_uIntPtr nIP ); 59*cdf0e10cSrcweir void Print( int nLevel, sal_uIntPtr nCount, sal_uIntPtr nCountLeak ); 60*cdf0e10cSrcweir void Print( int nLevel ); 61*cdf0e10cSrcweir }; 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir static ImpDbgStackTree* pImpDbgStackTreeRoot = NULL; 64*cdf0e10cSrcweir static sal_uIntPtr* pImpDbgStackTreeBP = NULL; 65*cdf0e10cSrcweir static sal_uIntPtr nImpDbgStackTreeMain = 0; 66*cdf0e10cSrcweir static int nImpDbgStackTreeSem = 0; 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir // ----------------------------------------------------------------------- 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir ImpDbgStackTree::ImpDbgStackTree( ImpDbgStackTree* pSub, sal_uIntPtr nIP ) 71*cdf0e10cSrcweir { 72*cdf0e10cSrcweir pSub_ = pSub; 73*cdf0e10cSrcweir nIP_ = nIP; 74*cdf0e10cSrcweir pLeft_ = pRight_ = pCaller_ = NULL; 75*cdf0e10cSrcweir nBytesLeak_ = nBytesPeak_ = nBytes_ = 0; 76*cdf0e10cSrcweir nCountLeak_ = nCountPeak_ = nCount_ = 0; 77*cdf0e10cSrcweir } 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir // ----------------------------------------------------------------------- 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir ImpDbgStackTree::~ImpDbgStackTree() 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir if ( pLeft_ ) 84*cdf0e10cSrcweir delete pLeft_; 85*cdf0e10cSrcweir if ( pRight_ ) 86*cdf0e10cSrcweir delete pRight_; 87*cdf0e10cSrcweir if ( pCaller_ ) 88*cdf0e10cSrcweir delete pCaller_; 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir // ----------------------------------------------------------------------- 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir void ImpDbgStackTree::Print( int nLevel, sal_uIntPtr nCount, sal_uIntPtr nCountLeak ) 94*cdf0e10cSrcweir { 95*cdf0e10cSrcweir if ( pLeft_ ) 96*cdf0e10cSrcweir pLeft_->Print( nLevel, nCount, nCountLeak ); 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir if ( nCount_ >= nCount && nCountLeak_ >= nCountLeak ) 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir if ( nMax_ == nMin_ ) 101*cdf0e10cSrcweir { 102*cdf0e10cSrcweir sal_uIntPtr nTemp = nCountLeak_ * nMin_; 103*cdf0e10cSrcweir DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu", 104*cdf0e10cSrcweir nLevel, ' ', nIP_, 105*cdf0e10cSrcweir nCount_, nCountPeak_, nCountLeak_, 106*cdf0e10cSrcweir nBytes_, nBytesPeak_, nTemp, 107*cdf0e10cSrcweir nMin_ ); 108*cdf0e10cSrcweir } 109*cdf0e10cSrcweir else 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu-%lu", 112*cdf0e10cSrcweir nLevel, ' ', nIP_, 113*cdf0e10cSrcweir nCount_, nCountPeak_, nCountLeak_, 114*cdf0e10cSrcweir nBytes_, nBytesPeak_, nBytesLeak_, 115*cdf0e10cSrcweir nMin_, nMax_ ); 116*cdf0e10cSrcweir } 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir if ( pCaller_ ) 119*cdf0e10cSrcweir if( nLevel > 3 && nCountLeak ) 120*cdf0e10cSrcweir pCaller_->Print( nLevel + 1, nCount, 1 ); 121*cdf0e10cSrcweir else 122*cdf0e10cSrcweir pCaller_->Print( nLevel + 1, nCount, nCountLeak ); 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir if ( pRight_ ) 126*cdf0e10cSrcweir pRight_->Print( nLevel, nCount, nCountLeak ); 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir // ----------------------------------------------------------------------- 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir void ImpDbgStackTree::Print( int nLevel ) 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir if ( pSub_ ) 134*cdf0e10cSrcweir pSub_->Print( nLevel + 1 ); 135*cdf0e10cSrcweir DbgOutf( "%*c%08lx", nLevel, ' ',nIP_ ); 136*cdf0e10cSrcweir } 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir // ----------------------------------------------------------------------- 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir ImpDbgStackTree* ImpDbgStackTree::Add( sal_uIntPtr nAlloc, sal_uIntPtr *pBP, sal_uIntPtr nIP ) 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir if ( nIP < nIP_ ) 143*cdf0e10cSrcweir { 144*cdf0e10cSrcweir if ( !pLeft_ ) 145*cdf0e10cSrcweir pLeft_ = new ImpDbgStackTree( pSub_, nIP ); 146*cdf0e10cSrcweir return pLeft_->Add( nAlloc, pBP, nIP ); 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir if ( nIP > nIP_ ) 149*cdf0e10cSrcweir { 150*cdf0e10cSrcweir if ( !pRight_ ) 151*cdf0e10cSrcweir pRight_ = new ImpDbgStackTree( pSub_, nIP ); 152*cdf0e10cSrcweir return pRight_->Add( nAlloc, pBP, nIP ); 153*cdf0e10cSrcweir } 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir nCount_++; 156*cdf0e10cSrcweir nCountLeak_++; 157*cdf0e10cSrcweir if ( nCountLeak_ > nCountPeak_ ) 158*cdf0e10cSrcweir nCountPeak_ = nCountLeak_; 159*cdf0e10cSrcweir nBytes_ += nAlloc; 160*cdf0e10cSrcweir nBytesLeak_ += nAlloc; 161*cdf0e10cSrcweir if ( nBytesLeak_ > nBytesPeak_ ) 162*cdf0e10cSrcweir nBytesPeak_ = nBytesLeak_; 163*cdf0e10cSrcweir if ( nCount_ == 1 ) 164*cdf0e10cSrcweir nMax_ = nMin_ = nAlloc; 165*cdf0e10cSrcweir else if ( nMax_ < nAlloc ) 166*cdf0e10cSrcweir nMax_ = nAlloc; 167*cdf0e10cSrcweir else if ( nMin_ > nAlloc ) 168*cdf0e10cSrcweir nMin_ = nAlloc; 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir if ( !(pBP[0] & 3) && (sal_uIntPtr)pBP < pBP[0] && pBP[0] < (sal_uIntPtr)pImpDbgStackTreeBP ) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir pBP = (sal_uIntPtr*)pBP[0]; 173*cdf0e10cSrcweir nIP = pBP[1]; 174*cdf0e10cSrcweir if ( 0x01100000 <= nIP && nIP < 0x20000000 && nIP != nImpDbgStackTreeMain ) 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir if ( !pCaller_ ) 177*cdf0e10cSrcweir pCaller_ = new ImpDbgStackTree( this, nIP ); 178*cdf0e10cSrcweir return pCaller_->Add( nAlloc, pBP, nIP ); 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir else 181*cdf0e10cSrcweir return this; 182*cdf0e10cSrcweir } 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir return this; 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir // ----------------------------------------------------------------------- 188*cdf0e10cSrcweir 189*cdf0e10cSrcweir void DbgStartStackTree() 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir if ( !nImpDbgStackTreeMain ) 192*cdf0e10cSrcweir { 193*cdf0e10cSrcweir sal_uIntPtr* pBP; 194*cdf0e10cSrcweir __asm mov pBP, ebp; 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir pImpDbgStackTreeBP = (sal_uIntPtr*)pBP[0]; 197*cdf0e10cSrcweir nImpDbgStackTreeMain = pImpDbgStackTreeBP[1]; 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir // ----------------------------------------------------------------------- 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir void DbgEndStackTree() 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir if ( nImpDbgStackTreeMain ) 206*cdf0e10cSrcweir { 207*cdf0e10cSrcweir nImpDbgStackTreeMain = 0; 208*cdf0e10cSrcweir if ( pImpDbgStackTreeRoot ) 209*cdf0e10cSrcweir { 210*cdf0e10cSrcweir // Ausgaben ins File umleiten 211*cdf0e10cSrcweir DbgData* pData = DbgGetData(); 212*cdf0e10cSrcweir sal_uIntPtr nOldOut = pData->nTraceOut; 213*cdf0e10cSrcweir pData->nTraceOut = DBG_OUT_FILE; 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir DbgOutf( "Leak-Report" ); 216*cdf0e10cSrcweir DbgOutf( "===========" ); 217*cdf0e10cSrcweir DbgOutf( "Mem-StackTree:" ); 218*cdf0e10cSrcweir DbgOutf( "{" ); 219*cdf0e10cSrcweir pImpDbgStackTreeRoot->Print( 1, 1, 2 ); 220*cdf0e10cSrcweir DbgOutf( "}" ); 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir DbgOutf( "Alloc-Report" ); 223*cdf0e10cSrcweir DbgOutf( "===========" ); 224*cdf0e10cSrcweir DbgOutf( "Mem-StackTree:" ); 225*cdf0e10cSrcweir DbgOutf( "{" ); 226*cdf0e10cSrcweir pImpDbgStackTreeRoot->Print( 1, 1000, 0 ); // ??? 227*cdf0e10cSrcweir DbgOutf( "}" ); 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir pData->nTraceOut = nOldOut; 230*cdf0e10cSrcweir 231*cdf0e10cSrcweir nImpDbgStackTreeSem++; 232*cdf0e10cSrcweir delete pImpDbgStackTreeRoot; 233*cdf0e10cSrcweir pImpDbgStackTreeRoot = NULL; 234*cdf0e10cSrcweir nImpDbgStackTreeSem--; 235*cdf0e10cSrcweir } 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir // ----------------------------------------------------------------------- 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir void* DbgGetStackTree( sal_uIntPtr nAlloc ) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir ImpDbgStackTree* pReturn = NULL; 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir if ( nImpDbgStackTreeMain && !nImpDbgStackTreeSem ) 246*cdf0e10cSrcweir { 247*cdf0e10cSrcweir nImpDbgStackTreeSem++; 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir sal_uIntPtr* pBP; 250*cdf0e10cSrcweir __asm mov pBP, ebp; 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir sal_uIntPtr nIP = pBP[1]; 253*cdf0e10cSrcweir if ( !pImpDbgStackTreeRoot ) 254*cdf0e10cSrcweir pImpDbgStackTreeRoot = new ImpDbgStackTree( NULL, nIP ); 255*cdf0e10cSrcweir pReturn = pImpDbgStackTreeRoot->Add( nAlloc, pBP, nIP ); 256*cdf0e10cSrcweir nImpDbgStackTreeSem--; 257*cdf0e10cSrcweir } 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir return pReturn; 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir // ----------------------------------------------------------------------- 263*cdf0e10cSrcweir 264*cdf0e10cSrcweir void DbgFreeStackTree( void* pVoid, sal_uIntPtr nAlloc ) 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir ImpDbgStackTree* p = (ImpDbgStackTree*)pVoid; 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir if ( p && nImpDbgStackTreeMain && !nImpDbgStackTreeSem ) 269*cdf0e10cSrcweir { 270*cdf0e10cSrcweir if ( nAlloc < p->nMin_ ) 271*cdf0e10cSrcweir nAlloc = p->nMin_; 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir p->nCountLeak_--; 274*cdf0e10cSrcweir p->nBytesLeak_ -= nAlloc; 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir if ( p->nMax_ && 0xFFFFFFFF / p->nMax_ > p->nCountLeak_ ) 277*cdf0e10cSrcweir { 278*cdf0e10cSrcweir if ( p->nBytesLeak_ > p->nMax_ * p->nCountLeak_ ) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir nAlloc += p->nBytesLeak_ - p->nMax_ * p->nCountLeak_; 281*cdf0e10cSrcweir p->nBytesLeak_ = p->nMax_ * p->nCountLeak_; 282*cdf0e10cSrcweir } 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir 285*cdf0e10cSrcweir if ( p->pSub_ ) 286*cdf0e10cSrcweir DbgFreeStackTree( (void*)(p->pSub_), nAlloc ); 287*cdf0e10cSrcweir } 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir // ----------------------------------------------------------------------- 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir void DbgPrintStackTree( void* pVoid ) 293*cdf0e10cSrcweir { 294*cdf0e10cSrcweir ImpDbgStackTree* p = (ImpDbgStackTree*)pVoid; 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir if ( p && nImpDbgStackTreeMain && !nImpDbgStackTreeSem ) 297*cdf0e10cSrcweir { 298*cdf0e10cSrcweir // Ausgaben ins File umleiten 299*cdf0e10cSrcweir DbgData* pData = DbgGetData(); 300*cdf0e10cSrcweir sal_uIntPtr nOldOut = pData->nTraceOut; 301*cdf0e10cSrcweir pData->nTraceOut = DBG_OUT_FILE; 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir DbgOutf( "Mem-StackTree:" ); 304*cdf0e10cSrcweir DbgOutf( "{" ); 305*cdf0e10cSrcweir p->Print( 1 ); 306*cdf0e10cSrcweir DbgOutf( "}" ); 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir pData->nTraceOut = nOldOut; 309*cdf0e10cSrcweir } 310*cdf0e10cSrcweir } 311*cdf0e10cSrcweir 312*cdf0e10cSrcweir #else 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir void DbgStartStackTree() {} 315*cdf0e10cSrcweir void DbgEndStackTree() {} 316*cdf0e10cSrcweir void* DbgGetStackTree( sal_uIntPtr ) { return NULL; } 317*cdf0e10cSrcweir void DbgFreeStackTree( void*, sal_uIntPtr ) {} 318*cdf0e10cSrcweir void DbgPrintStackTree( void* ) {} 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir #endif 321