Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "osl/diagnose.h"
30 : : #include "system.h"
31 : :
32 : : #ifndef HAVE_DLFCN_H
33 : :
34 : : #if defined(LINUX) || defined(SOLARIS)
35 : : #define HAVE_DLFCN_H
36 : : #endif /* LINUX || SOLARIS */
37 : :
38 : : #endif /* HAVE_DLFCN_H */
39 : :
40 : :
41 : : #ifdef HAVE_DLFCN_H
42 : :
43 : : #ifndef INCLUDED_DLFCN_H
44 : : #include <dlfcn.h>
45 : : #define INCLUDED_DLFCN_H
46 : : #endif
47 : :
48 : : #endif /* HAVE_DLFCN_H */
49 : :
50 : : #ifndef INCLUDED_PTHREAD_H
51 : : #include <pthread.h>
52 : : #define INCLUDED_PTHREAD_H
53 : : #endif
54 : :
55 : : #ifndef INCLUDED_STDDEF_H
56 : : #include <stddef.h>
57 : : #define INCLUDED_STDDEF_H
58 : : #endif
59 : :
60 : : /************************************************************************/
61 : : /* Internal data structures and functions */
62 : : /************************************************************************/
63 : :
64 : : static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
65 : :
66 : : typedef pfunc_osl_printDebugMessage oslDebugMessageFunc;
67 : : static oslDebugMessageFunc volatile g_pDebugMessageFunc = 0;
68 : :
69 : : typedef pfunc_osl_printDetailedDebugMessage oslDetailedDebugMessageFunc;
70 : : static oslDetailedDebugMessageFunc volatile g_pDetailedDebugMessageFunc = 0;
71 : :
72 : : static void osl_diagnose_backtrace_Impl (
73 : : oslDebugMessageFunc f);
74 : :
75 : : #define OSL_DIAGNOSE_OUTPUTMESSAGE(f, s) \
76 : : ((f != 0) ? (*(f))((s)) : (void)fprintf(stderr, "%s", (s)))
77 : :
78 : : #if defined (LINUX) || defined (SOLARIS)
79 : : /************************************************************************/
80 : : /* osl_diagnose_frame_Impl */
81 : : /************************************************************************/
82 : 0 : static void osl_diagnose_frame_Impl (
83 : : oslDebugMessageFunc f,
84 : : int depth,
85 : : void * pc)
86 : : {
87 : 0 : const char *fname = 0, *sname = 0;
88 : 0 : void *fbase = 0, *saddr = 0;
89 : : ptrdiff_t offset;
90 : : char szMessage[1024];
91 : :
92 : : #ifdef INCLUDED_DLFCN_H
93 : : Dl_info dli;
94 [ # # ]: 0 : if (dladdr (pc, &dli) != 0)
95 : : {
96 : 0 : fname = dli.dli_fname;
97 : 0 : fbase = dli.dli_fbase;
98 : 0 : sname = dli.dli_sname;
99 : 0 : saddr = dli.dli_saddr;
100 : : }
101 : : #endif /* INCLUDED_DLFCN_H */
102 : :
103 [ # # ]: 0 : if (saddr)
104 : 0 : offset = (ptrdiff_t)(pc) - (ptrdiff_t)(saddr);
105 [ # # ]: 0 : else if (fbase)
106 : 0 : offset = (ptrdiff_t)(pc) - (ptrdiff_t)(fbase);
107 : : else
108 : 0 : offset = (ptrdiff_t)(pc);
109 : :
110 [ # # ][ # # ]: 0 : snprintf (szMessage, sizeof(szMessage),
111 : : "Backtrace: [%d] %s: %s+0x%" SAL_PRI_PTRDIFFT "x\n",
112 : : depth,
113 : : fname ? fname : "<unknown>",
114 : : sname ? sname : "???",
115 : : offset);
116 : :
117 [ # # ]: 0 : OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
118 : 0 : }
119 : : #endif
120 : :
121 : : /************************************************************************/
122 : : /* osl_diagnose_backtrace_Impl */
123 : : /************************************************************************/
124 : : #if defined(LINUX)
125 : :
126 : : #include <execinfo.h>
127 : :
128 : : #define FRAME_COUNT 64
129 : : #define FRAME_OFFSET 1
130 : :
131 : 0 : static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
132 : : {
133 : : void * ppFrames[FRAME_COUNT];
134 : : int i, n;
135 : :
136 : 0 : n = backtrace (ppFrames, FRAME_COUNT);
137 [ # # ]: 0 : for (i = FRAME_OFFSET; i < n; i++)
138 : : {
139 : 0 : osl_diagnose_frame_Impl (f, (i - FRAME_OFFSET), ppFrames[i]);
140 : : }
141 : 0 : }
142 : :
143 : : #elif defined(SOLARIS)
144 : :
145 : : #include <pthread.h>
146 : : #include <setjmp.h>
147 : : #include <sys/frame.h>
148 : :
149 : : #if defined(SPARC)
150 : :
151 : : #if defined IS_LP64
152 : :
153 : : #define FRAME_PTR_OFFSET 1
154 : : #define FRAME_OFFSET 0
155 : : #define STACK_BIAS 0x7ff
156 : :
157 : : #else
158 : :
159 : : #define FRAME_PTR_OFFSET 1
160 : : #define FRAME_OFFSET 0
161 : : #define STACK_BIAS 0
162 : :
163 : : #endif
164 : :
165 : : #elif defined(INTEL)
166 : :
167 : : #define FRAME_PTR_OFFSET 3
168 : : #define FRAME_OFFSET 0
169 : : #define STACK_BIAS 0
170 : :
171 : : #endif /* (SPARC || INTEL) */
172 : :
173 : : static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
174 : : {
175 : : jmp_buf ctx;
176 : : long fpval;
177 : : struct frame * fp;
178 : : int i;
179 : :
180 : : #if defined(SPARC)
181 : : asm("ta 3");
182 : : #endif /* SPARC */
183 : : setjmp (ctx);
184 : :
185 : : fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
186 : : fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
187 : :
188 : : for (i = 0; (i < FRAME_OFFSET) && (fp != 0); i++)
189 : : fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
190 : :
191 : : for (i = 0; (fp != 0) && (fp->fr_savpc != 0); i++)
192 : : {
193 : : struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
194 : : osl_diagnose_frame_Impl (f, i, (void*)(fp->fr_savpc));
195 : : fp = (prev > fp) ? prev : 0;
196 : : }
197 : : }
198 : :
199 : : #else /* (LINUX || SOLARIS) */
200 : :
201 : : static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
202 : : {
203 : : (void) f;
204 : : /* not yet implemented */
205 : : }
206 : :
207 : : #endif /* (LINUX || SOLARIS) */
208 : :
209 : : /************************************************************************/
210 : : /* osl_assertFailedLine */
211 : : /************************************************************************/
212 : 0 : sal_Bool SAL_CALL osl_assertFailedLine (
213 : : const sal_Char* pszFileName,
214 : : sal_Int32 nLine,
215 : : const sal_Char* pszMessage)
216 : : {
217 : 0 : oslDebugMessageFunc f = g_pDebugMessageFunc;
218 : : char szMessage[1024];
219 : :
220 : : // after reporting the assertion, abort if told so by SAL_DIAGNOSE_ABORT, but *not* if
221 : : // assertions are routed to some external instance
222 : 0 : char const * env = getenv( "SAL_DIAGNOSE_ABORT" );
223 : 0 : char const * envBacktrace = getenv( "SAL_DIAGNOSE_BACKTRACE" );
224 [ # # ][ # # ]: 0 : sal_Bool const doAbort = ( ( env != NULL ) && ( *env != '\0' ) && ( f == NULL ) );
[ # # ]
225 : :
226 : : /* If there's a callback for detailed messages, use it */
227 [ # # ]: 0 : if ( g_pDetailedDebugMessageFunc != NULL )
228 : : {
229 : 0 : g_pDetailedDebugMessageFunc( pszFileName, nLine, pszMessage );
230 : 0 : return sal_False;
231 : : }
232 : :
233 : : /* format message into buffer */
234 [ # # ]: 0 : if (pszMessage != 0)
235 : : {
236 : 0 : snprintf(szMessage, sizeof(szMessage),
237 : : "Error: File %s, Line %" SAL_PRIdINT32 ": %s\n",
238 : : pszFileName, nLine, pszMessage);
239 : : }
240 : : else
241 : : {
242 : 0 : snprintf(szMessage, sizeof(szMessage),
243 : : "Error: File %s, Line %" SAL_PRIdINT32 "\n",
244 : : pszFileName, nLine);
245 : : }
246 : :
247 : : /* acquire lock to serialize output message(s) */
248 : 0 : pthread_mutex_lock(&g_mutex);
249 : :
250 : : /* output message buffer */
251 [ # # ]: 0 : OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
252 : :
253 : : /* should we output backtrace? */
254 [ # # ][ # # ]: 0 : if( envBacktrace != NULL && *envBacktrace != '\0' )
255 : 0 : osl_diagnose_backtrace_Impl(f);
256 : :
257 : : /* release lock and leave */
258 : 0 : pthread_mutex_unlock(&g_mutex);
259 : :
260 : 0 : return doAbort;
261 : : }
262 : :
263 : : /************************************************************************/
264 : : /* osl_breakDebug */
265 : : /************************************************************************/
266 : 0 : void SAL_CALL osl_breakDebug()
267 : : {
268 : 0 : abort();
269 : : }
270 : :
271 : : /************************************************************************/
272 : : /* osl_reportError */
273 : : /************************************************************************/
274 : 0 : sal_Int32 SAL_CALL osl_reportError (
275 : : sal_uInt32 nType,
276 : : const sal_Char* pszMessage)
277 : : {
278 : : (void) nType; /* unused */
279 : 0 : fputs(pszMessage, stderr);
280 : 0 : return 0;
281 : : }
282 : :
283 : : /************************************************************************/
284 : : /* osl_setDebugMessageFunc */
285 : : /************************************************************************/
286 : 0 : oslDebugMessageFunc SAL_CALL osl_setDebugMessageFunc (
287 : : oslDebugMessageFunc pNewFunc)
288 : : {
289 : 0 : oslDebugMessageFunc pOldFunc = g_pDebugMessageFunc;
290 : 0 : g_pDebugMessageFunc = pNewFunc;
291 : 0 : return pOldFunc;
292 : : }
293 : :
294 : : /************************************************************************/
295 : : /* osl_setDetailedDebugMessageFunc */
296 : : /************************************************************************/
297 : 0 : pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc (
298 : : pfunc_osl_printDetailedDebugMessage pNewFunc)
299 : : {
300 : 0 : oslDetailedDebugMessageFunc pOldFunc = g_pDetailedDebugMessageFunc;
301 : 0 : g_pDetailedDebugMessageFunc = pNewFunc;
302 : 0 : return pOldFunc;
303 : : }
304 : :
305 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|