1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_tools.hxx" 26 27 #include <string.h> 28 29 #include <tools/debug.hxx> 30 31 // ----------------------------------------------------------------------- 32 33 #if defined( DBG_UTIL ) && defined( WNT ) && defined( INTEL ) 34 35 struct ImpDbgStackTree 36 { 37 ImpDbgStackTree* pLeft_; 38 ImpDbgStackTree* pRight_; 39 ImpDbgStackTree* pCaller_; 40 ImpDbgStackTree* pSub_; 41 sal_uIntPtr nIP_; 42 sal_uIntPtr nBytesLeak_; 43 sal_uIntPtr nBytesPeak_; 44 sal_uIntPtr nBytes_; 45 sal_uIntPtr nCountLeak_; 46 sal_uIntPtr nCountPeak_; 47 sal_uIntPtr nCount_; 48 sal_uIntPtr nMax_; 49 sal_uIntPtr nMin_; 50 51 ImpDbgStackTree( ImpDbgStackTree* pSub, sal_uIntPtr nIP ); 52 ~ImpDbgStackTree(); 53 54 ImpDbgStackTree* Add( sal_uIntPtr nAlloc, sal_uIntPtr* pBP, sal_uIntPtr nIP ); 55 void Print( int nLevel, sal_uIntPtr nCount, sal_uIntPtr nCountLeak ); 56 void Print( int nLevel ); 57 }; 58 59 static ImpDbgStackTree* pImpDbgStackTreeRoot = NULL; 60 static sal_uIntPtr* pImpDbgStackTreeBP = NULL; 61 static sal_uIntPtr nImpDbgStackTreeMain = 0; 62 static int nImpDbgStackTreeSem = 0; 63 64 // ----------------------------------------------------------------------- 65 66 ImpDbgStackTree::ImpDbgStackTree( ImpDbgStackTree* pSub, sal_uIntPtr nIP ) 67 { 68 pSub_ = pSub; 69 nIP_ = nIP; 70 pLeft_ = pRight_ = pCaller_ = NULL; 71 nBytesLeak_ = nBytesPeak_ = nBytes_ = 0; 72 nCountLeak_ = nCountPeak_ = nCount_ = 0; 73 } 74 75 // ----------------------------------------------------------------------- 76 77 ImpDbgStackTree::~ImpDbgStackTree() 78 { 79 if ( pLeft_ ) 80 delete pLeft_; 81 if ( pRight_ ) 82 delete pRight_; 83 if ( pCaller_ ) 84 delete pCaller_; 85 } 86 87 // ----------------------------------------------------------------------- 88 89 void ImpDbgStackTree::Print( int nLevel, sal_uIntPtr nCount, sal_uIntPtr nCountLeak ) 90 { 91 if ( pLeft_ ) 92 pLeft_->Print( nLevel, nCount, nCountLeak ); 93 94 if ( nCount_ >= nCount && nCountLeak_ >= nCountLeak ) 95 { 96 if ( nMax_ == nMin_ ) 97 { 98 sal_uIntPtr nTemp = nCountLeak_ * nMin_; 99 DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu", 100 nLevel, ' ', nIP_, 101 nCount_, nCountPeak_, nCountLeak_, 102 nBytes_, nBytesPeak_, nTemp, 103 nMin_ ); 104 } 105 else 106 { 107 DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu-%lu", 108 nLevel, ' ', nIP_, 109 nCount_, nCountPeak_, nCountLeak_, 110 nBytes_, nBytesPeak_, nBytesLeak_, 111 nMin_, nMax_ ); 112 } 113 114 if ( pCaller_ ) 115 if( nLevel > 3 && nCountLeak ) 116 pCaller_->Print( nLevel + 1, nCount, 1 ); 117 else 118 pCaller_->Print( nLevel + 1, nCount, nCountLeak ); 119 } 120 121 if ( pRight_ ) 122 pRight_->Print( nLevel, nCount, nCountLeak ); 123 } 124 125 // ----------------------------------------------------------------------- 126 127 void ImpDbgStackTree::Print( int nLevel ) 128 { 129 if ( pSub_ ) 130 pSub_->Print( nLevel + 1 ); 131 DbgOutf( "%*c%08lx", nLevel, ' ',nIP_ ); 132 } 133 134 // ----------------------------------------------------------------------- 135 136 ImpDbgStackTree* ImpDbgStackTree::Add( sal_uIntPtr nAlloc, sal_uIntPtr *pBP, sal_uIntPtr nIP ) 137 { 138 if ( nIP < nIP_ ) 139 { 140 if ( !pLeft_ ) 141 pLeft_ = new ImpDbgStackTree( pSub_, nIP ); 142 return pLeft_->Add( nAlloc, pBP, nIP ); 143 } 144 if ( nIP > nIP_ ) 145 { 146 if ( !pRight_ ) 147 pRight_ = new ImpDbgStackTree( pSub_, nIP ); 148 return pRight_->Add( nAlloc, pBP, nIP ); 149 } 150 151 nCount_++; 152 nCountLeak_++; 153 if ( nCountLeak_ > nCountPeak_ ) 154 nCountPeak_ = nCountLeak_; 155 nBytes_ += nAlloc; 156 nBytesLeak_ += nAlloc; 157 if ( nBytesLeak_ > nBytesPeak_ ) 158 nBytesPeak_ = nBytesLeak_; 159 if ( nCount_ == 1 ) 160 nMax_ = nMin_ = nAlloc; 161 else if ( nMax_ < nAlloc ) 162 nMax_ = nAlloc; 163 else if ( nMin_ > nAlloc ) 164 nMin_ = nAlloc; 165 166 if ( !(pBP[0] & 3) && (sal_uIntPtr)pBP < pBP[0] && pBP[0] < (sal_uIntPtr)pImpDbgStackTreeBP ) 167 { 168 pBP = (sal_uIntPtr*)pBP[0]; 169 nIP = pBP[1]; 170 if ( 0x01100000 <= nIP && nIP < 0x20000000 && nIP != nImpDbgStackTreeMain ) 171 { 172 if ( !pCaller_ ) 173 pCaller_ = new ImpDbgStackTree( this, nIP ); 174 return pCaller_->Add( nAlloc, pBP, nIP ); 175 } 176 else 177 return this; 178 } 179 180 return this; 181 } 182 183 // ----------------------------------------------------------------------- 184 185 void DbgStartStackTree() 186 { 187 if ( !nImpDbgStackTreeMain ) 188 { 189 sal_uIntPtr* pBP; 190 __asm mov pBP, ebp; 191 192 pImpDbgStackTreeBP = (sal_uIntPtr*)pBP[0]; 193 nImpDbgStackTreeMain = pImpDbgStackTreeBP[1]; 194 } 195 } 196 197 // ----------------------------------------------------------------------- 198 199 void DbgEndStackTree() 200 { 201 if ( nImpDbgStackTreeMain ) 202 { 203 nImpDbgStackTreeMain = 0; 204 if ( pImpDbgStackTreeRoot ) 205 { 206 // Ausgaben ins File umleiten 207 DbgData* pData = DbgGetData(); 208 sal_uIntPtr nOldOut = pData->nTraceOut; 209 pData->nTraceOut = DBG_OUT_FILE; 210 211 DbgOutf( "Leak-Report" ); 212 DbgOutf( "===========" ); 213 DbgOutf( "Mem-StackTree:" ); 214 DbgOutf( "{" ); 215 pImpDbgStackTreeRoot->Print( 1, 1, 2 ); 216 DbgOutf( "}" ); 217 218 DbgOutf( "Alloc-Report" ); 219 DbgOutf( "===========" ); 220 DbgOutf( "Mem-StackTree:" ); 221 DbgOutf( "{" ); 222 pImpDbgStackTreeRoot->Print( 1, 1000, 0 ); // ??? 223 DbgOutf( "}" ); 224 225 pData->nTraceOut = nOldOut; 226 227 nImpDbgStackTreeSem++; 228 delete pImpDbgStackTreeRoot; 229 pImpDbgStackTreeRoot = NULL; 230 nImpDbgStackTreeSem--; 231 } 232 } 233 } 234 235 // ----------------------------------------------------------------------- 236 237 void* DbgGetStackTree( sal_uIntPtr nAlloc ) 238 { 239 ImpDbgStackTree* pReturn = NULL; 240 241 if ( nImpDbgStackTreeMain && !nImpDbgStackTreeSem ) 242 { 243 nImpDbgStackTreeSem++; 244 245 sal_uIntPtr* pBP; 246 __asm mov pBP, ebp; 247 248 sal_uIntPtr nIP = pBP[1]; 249 if ( !pImpDbgStackTreeRoot ) 250 pImpDbgStackTreeRoot = new ImpDbgStackTree( NULL, nIP ); 251 pReturn = pImpDbgStackTreeRoot->Add( nAlloc, pBP, nIP ); 252 nImpDbgStackTreeSem--; 253 } 254 255 return pReturn; 256 } 257 258 // ----------------------------------------------------------------------- 259 260 void DbgFreeStackTree( void* pVoid, sal_uIntPtr nAlloc ) 261 { 262 ImpDbgStackTree* p = (ImpDbgStackTree*)pVoid; 263 264 if ( p && nImpDbgStackTreeMain && !nImpDbgStackTreeSem ) 265 { 266 if ( nAlloc < p->nMin_ ) 267 nAlloc = p->nMin_; 268 269 p->nCountLeak_--; 270 p->nBytesLeak_ -= nAlloc; 271 272 if ( p->nMax_ && 0xFFFFFFFF / p->nMax_ > p->nCountLeak_ ) 273 { 274 if ( p->nBytesLeak_ > p->nMax_ * p->nCountLeak_ ) 275 { 276 nAlloc += p->nBytesLeak_ - p->nMax_ * p->nCountLeak_; 277 p->nBytesLeak_ = p->nMax_ * p->nCountLeak_; 278 } 279 } 280 281 if ( p->pSub_ ) 282 DbgFreeStackTree( (void*)(p->pSub_), nAlloc ); 283 } 284 } 285 286 // ----------------------------------------------------------------------- 287 288 void DbgPrintStackTree( void* pVoid ) 289 { 290 ImpDbgStackTree* p = (ImpDbgStackTree*)pVoid; 291 292 if ( p && nImpDbgStackTreeMain && !nImpDbgStackTreeSem ) 293 { 294 // Ausgaben ins File umleiten 295 DbgData* pData = DbgGetData(); 296 sal_uIntPtr nOldOut = pData->nTraceOut; 297 pData->nTraceOut = DBG_OUT_FILE; 298 299 DbgOutf( "Mem-StackTree:" ); 300 DbgOutf( "{" ); 301 p->Print( 1 ); 302 DbgOutf( "}" ); 303 304 pData->nTraceOut = nOldOut; 305 } 306 } 307 308 #else 309 310 void DbgStartStackTree() {} 311 void DbgEndStackTree() {} 312 void* DbgGetStackTree( sal_uIntPtr ) { return NULL; } 313 void DbgFreeStackTree( void*, sal_uIntPtr ) {} 314 void DbgPrintStackTree( void* ) {} 315 316 #endif 317