xref: /AOO41X/main/tools/source/debug/stcktree.cxx (revision 89b56da77b74925c286b3e777681ba8dda16bf41)
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 
ImpDbgStackTree(ImpDbgStackTree * pSub,sal_uIntPtr nIP)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 
~ImpDbgStackTree()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 
Print(int nLevel,sal_uIntPtr nCount,sal_uIntPtr nCountLeak)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 
Print(int nLevel)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 
Add(sal_uIntPtr nAlloc,sal_uIntPtr * pBP,sal_uIntPtr nIP)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 
DbgStartStackTree()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 
DbgEndStackTree()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 
DbgGetStackTree(sal_uIntPtr nAlloc)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 
DbgFreeStackTree(void * pVoid,sal_uIntPtr nAlloc)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 
DbgPrintStackTree(void * pVoid)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 
DbgStartStackTree()310 void DbgStartStackTree() {}
DbgEndStackTree()311 void DbgEndStackTree() {}
DbgGetStackTree(sal_uIntPtr)312 void* DbgGetStackTree( sal_uIntPtr ) { return NULL; }
DbgFreeStackTree(void *,sal_uIntPtr)313 void DbgFreeStackTree( void*, sal_uIntPtr ) {}
DbgPrintStackTree(void *)314 void DbgPrintStackTree( void* ) {}
315 
316 #endif
317