1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: stcktree.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
36 #include <tools/debug.hxx>
38 // -----------------------------------------------------------------------
40 #if defined( DBG_UTIL ) && defined( WNT ) && defined( INTEL )
42 struct ImpDbgStackTree
44 ImpDbgStackTree
* pLeft_
;
45 ImpDbgStackTree
* pRight_
;
46 ImpDbgStackTree
* pCaller_
;
47 ImpDbgStackTree
* pSub_
;
58 ImpDbgStackTree( ImpDbgStackTree
* pSub
, ULONG nIP
);
61 ImpDbgStackTree
* Add( ULONG nAlloc
, ULONG
* pBP
, ULONG nIP
);
62 void Print( int nLevel
, ULONG nCount
, ULONG nCountLeak
);
63 void Print( int nLevel
);
66 static ImpDbgStackTree
* pImpDbgStackTreeRoot
= NULL
;
67 static ULONG
* pImpDbgStackTreeBP
= NULL
;
68 static ULONG nImpDbgStackTreeMain
= 0;
69 static int nImpDbgStackTreeSem
= 0;
71 // -----------------------------------------------------------------------
73 ImpDbgStackTree::ImpDbgStackTree( ImpDbgStackTree
* pSub
, ULONG nIP
)
77 pLeft_
= pRight_
= pCaller_
= NULL
;
78 nBytesLeak_
= nBytesPeak_
= nBytes_
= 0;
79 nCountLeak_
= nCountPeak_
= nCount_
= 0;
82 // -----------------------------------------------------------------------
84 ImpDbgStackTree::~ImpDbgStackTree()
94 // -----------------------------------------------------------------------
96 void ImpDbgStackTree::Print( int nLevel
, ULONG nCount
, ULONG nCountLeak
)
99 pLeft_
->Print( nLevel
, nCount
, nCountLeak
);
101 if ( nCount_
>= nCount
&& nCountLeak_
>= nCountLeak
)
103 if ( nMax_
== nMin_
)
105 ULONG nTemp
= nCountLeak_
* nMin_
;
106 DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu",
108 nCount_
, nCountPeak_
, nCountLeak_
,
109 nBytes_
, nBytesPeak_
, nTemp
,
114 DbgOutf( "%*c%08lx Count=%lu/%lu/%lu Bytes=%lu/%lu/%lu Size=%lu-%lu",
116 nCount_
, nCountPeak_
, nCountLeak_
,
117 nBytes_
, nBytesPeak_
, nBytesLeak_
,
122 if( nLevel
> 3 && nCountLeak
)
123 pCaller_
->Print( nLevel
+ 1, nCount
, 1 );
125 pCaller_
->Print( nLevel
+ 1, nCount
, nCountLeak
);
129 pRight_
->Print( nLevel
, nCount
, nCountLeak
);
132 // -----------------------------------------------------------------------
134 void ImpDbgStackTree::Print( int nLevel
)
137 pSub_
->Print( nLevel
+ 1 );
138 DbgOutf( "%*c%08lx", nLevel
, ' ',nIP_
);
141 // -----------------------------------------------------------------------
143 ImpDbgStackTree
* ImpDbgStackTree::Add( ULONG nAlloc
, ULONG
*pBP
, ULONG nIP
)
148 pLeft_
= new ImpDbgStackTree( pSub_
, nIP
);
149 return pLeft_
->Add( nAlloc
, pBP
, nIP
);
154 pRight_
= new ImpDbgStackTree( pSub_
, nIP
);
155 return pRight_
->Add( nAlloc
, pBP
, nIP
);
160 if ( nCountLeak_
> nCountPeak_
)
161 nCountPeak_
= nCountLeak_
;
163 nBytesLeak_
+= nAlloc
;
164 if ( nBytesLeak_
> nBytesPeak_
)
165 nBytesPeak_
= nBytesLeak_
;
167 nMax_
= nMin_
= nAlloc
;
168 else if ( nMax_
< nAlloc
)
170 else if ( nMin_
> nAlloc
)
173 if ( !(pBP
[0] & 3) && (ULONG
)pBP
< pBP
[0] && pBP
[0] < (ULONG
)pImpDbgStackTreeBP
)
175 pBP
= (ULONG
*)pBP
[0];
177 if ( 0x01100000 <= nIP
&& nIP
< 0x20000000 && nIP
!= nImpDbgStackTreeMain
)
180 pCaller_
= new ImpDbgStackTree( this, nIP
);
181 return pCaller_
->Add( nAlloc
, pBP
, nIP
);
190 // -----------------------------------------------------------------------
192 void DbgStartStackTree()
194 if ( !nImpDbgStackTreeMain
)
199 pImpDbgStackTreeBP
= (ULONG
*)pBP
[0];
200 nImpDbgStackTreeMain
= pImpDbgStackTreeBP
[1];
204 // -----------------------------------------------------------------------
206 void DbgEndStackTree()
208 if ( nImpDbgStackTreeMain
)
210 nImpDbgStackTreeMain
= 0;
211 if ( pImpDbgStackTreeRoot
)
213 // Ausgaben ins File umleiten
214 DbgData
* pData
= DbgGetData();
215 ULONG nOldOut
= pData
->nTraceOut
;
216 pData
->nTraceOut
= DBG_OUT_FILE
;
218 DbgOutf( "Leak-Report" );
219 DbgOutf( "===========" );
220 DbgOutf( "Mem-StackTree:" );
222 pImpDbgStackTreeRoot
->Print( 1, 1, 2 );
225 DbgOutf( "Alloc-Report" );
226 DbgOutf( "===========" );
227 DbgOutf( "Mem-StackTree:" );
229 pImpDbgStackTreeRoot
->Print( 1, 1000, 0 ); // ???
232 pData
->nTraceOut
= nOldOut
;
234 nImpDbgStackTreeSem
++;
235 delete pImpDbgStackTreeRoot
;
236 pImpDbgStackTreeRoot
= NULL
;
237 nImpDbgStackTreeSem
--;
242 // -----------------------------------------------------------------------
244 void* DbgGetStackTree( ULONG nAlloc
)
246 ImpDbgStackTree
* pReturn
= NULL
;
248 if ( nImpDbgStackTreeMain
&& !nImpDbgStackTreeSem
)
250 nImpDbgStackTreeSem
++;
256 if ( !pImpDbgStackTreeRoot
)
257 pImpDbgStackTreeRoot
= new ImpDbgStackTree( NULL
, nIP
);
258 pReturn
= pImpDbgStackTreeRoot
->Add( nAlloc
, pBP
, nIP
);
259 nImpDbgStackTreeSem
--;
265 // -----------------------------------------------------------------------
267 void DbgFreeStackTree( void* pVoid
, ULONG nAlloc
)
269 ImpDbgStackTree
* p
= (ImpDbgStackTree
*)pVoid
;
271 if ( p
&& nImpDbgStackTreeMain
&& !nImpDbgStackTreeSem
)
273 if ( nAlloc
< p
->nMin_
)
277 p
->nBytesLeak_
-= nAlloc
;
279 if ( p
->nMax_
&& 0xFFFFFFFF / p
->nMax_
> p
->nCountLeak_
)
281 if ( p
->nBytesLeak_
> p
->nMax_
* p
->nCountLeak_
)
283 nAlloc
+= p
->nBytesLeak_
- p
->nMax_
* p
->nCountLeak_
;
284 p
->nBytesLeak_
= p
->nMax_
* p
->nCountLeak_
;
289 DbgFreeStackTree( (void*)(p
->pSub_
), nAlloc
);
293 // -----------------------------------------------------------------------
295 void DbgPrintStackTree( void* pVoid
)
297 ImpDbgStackTree
* p
= (ImpDbgStackTree
*)pVoid
;
299 if ( p
&& nImpDbgStackTreeMain
&& !nImpDbgStackTreeSem
)
301 // Ausgaben ins File umleiten
302 DbgData
* pData
= DbgGetData();
303 ULONG nOldOut
= pData
->nTraceOut
;
304 pData
->nTraceOut
= DBG_OUT_FILE
;
306 DbgOutf( "Mem-StackTree:" );
311 pData
->nTraceOut
= nOldOut
;
317 void DbgStartStackTree() {}
318 void DbgEndStackTree() {}
319 void* DbgGetStackTree( ULONG
) { return NULL
; }
320 void DbgFreeStackTree( void*, ULONG
) {}
321 void DbgPrintStackTree( void* ) {}