xref: /AOO41X/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