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