update dev300-m58
[ooovba.git] / sal / osl / unx / diagnose.c
blob555c70f53fc1e0b6ceea60ccb1fdc73f29b9c437
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: diagnose.c,v $
10 * $Revision: 1.26 $
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 #include "osl/diagnose.h"
32 #include "system.h"
35 #ifndef HAVE_DLFCN_H
37 #if defined(LINUX) || defined(SOLARIS)
38 #define HAVE_DLFCN_H
39 #endif /* LINUX || SOLARIS */
41 #endif /* HAVE_DLFCN_H */
44 #ifdef HAVE_DLFCN_H
46 #ifndef INCLUDED_DLFCN_H
47 #include <dlfcn.h>
48 #define INCLUDED_DLFCN_H
49 #endif
51 #endif /* HAVE_DLFCN_H */
52 #include "osl/thread.h"
54 #ifndef INCLUDED_PTHREAD_H
55 #include <pthread.h>
56 #define INCLUDED_PTHREAD_H
57 #endif
59 #ifndef INCLUDED_STDDEF_H
60 #include <stddef.h>
61 #define INCLUDED_STDDEF_H
62 #endif
64 /************************************************************************/
65 /* Internal data structures and functions */
66 /************************************************************************/
68 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
70 typedef pfunc_osl_printDebugMessage oslDebugMessageFunc;
71 static oslDebugMessageFunc volatile g_pDebugMessageFunc = 0;
73 typedef pfunc_osl_printDetailedDebugMessage oslDetailedDebugMessageFunc;
74 static oslDetailedDebugMessageFunc volatile g_pDetailedDebugMessageFunc = 0;
76 static void osl_diagnose_backtrace_Impl (
77 oslDebugMessageFunc f);
79 #define OSL_DIAGNOSE_OUTPUTMESSAGE(f, s) \
80 ((f != 0) ? (*(f))((s)) : (void)fprintf(stderr, "%s", (s)))
82 #if defined (LINUX) || defined (SOLARIS)
83 /************************************************************************/
84 /* osl_diagnose_frame_Impl */
85 /************************************************************************/
86 static void osl_diagnose_frame_Impl (
87 oslDebugMessageFunc f,
88 int depth,
89 void * pc)
91 const char *fname = 0, *sname = 0;
92 void *fbase = 0, *saddr = 0;
93 ptrdiff_t offset;
94 char szMessage[1024];
96 #ifdef INCLUDED_DLFCN_H
97 Dl_info dli;
98 if (dladdr (pc, &dli) != 0)
100 fname = dli.dli_fname;
101 fbase = dli.dli_fbase;
102 sname = dli.dli_sname;
103 saddr = dli.dli_saddr;
105 #endif /* INCLUDED_DLFCN_H */
107 if (saddr)
108 offset = (ptrdiff_t)(pc) - (ptrdiff_t)(saddr);
109 else if (fbase)
110 offset = (ptrdiff_t)(pc) - (ptrdiff_t)(fbase);
111 else
112 offset = (ptrdiff_t)(pc);
114 snprintf (szMessage, sizeof(szMessage),
115 "Backtrace: [%d] %s: %s+0x%" SAL_PRI_PTRDIFFT "x\n",
116 depth,
117 fname ? fname : "<unknown>",
118 sname ? sname : "???",
119 offset);
121 OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
123 #endif
125 /************************************************************************/
126 /* osl_diagnose_backtrace_Impl */
127 /************************************************************************/
128 #if defined(LINUX)
130 #include <execinfo.h>
132 #define FRAME_COUNT 64
133 #define FRAME_OFFSET 1
135 static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
137 void * ppFrames[FRAME_COUNT];
138 int i, n;
140 n = backtrace (ppFrames, FRAME_COUNT);
141 for (i = FRAME_OFFSET; i < n; i++)
143 osl_diagnose_frame_Impl (f, (i - FRAME_OFFSET), ppFrames[i]);
147 #elif defined(SOLARIS)
149 #include <pthread.h>
150 #include <setjmp.h>
151 #include <sys/frame.h>
153 #if defined(SPARC)
155 #if defined IS_LP64
157 #define FRAME_PTR_OFFSET 1
158 #define FRAME_OFFSET 0
159 #define STACK_BIAS 0x7ff
161 #else
163 #define FRAME_PTR_OFFSET 1
164 #define FRAME_OFFSET 0
165 #define STACK_BIAS 0
167 #endif
169 #elif defined(INTEL)
171 #define FRAME_PTR_OFFSET 3
172 #define FRAME_OFFSET 0
173 #define STACK_BIAS 0
175 #endif /* (SPARC || INTEL) */
177 static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
179 jmp_buf ctx;
180 long fpval;
181 struct frame * fp;
182 int i;
184 #if defined(SPARC)
185 asm("ta 3");
186 #endif /* SPARC */
187 setjmp (ctx);
189 fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
190 fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
192 for (i = 0; (i < FRAME_OFFSET) && (fp != 0); i++)
193 fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
195 for (i = 0; (fp != 0) && (fp->fr_savpc != 0); i++)
197 struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
198 osl_diagnose_frame_Impl (f, i, (void*)(fp->fr_savpc));
199 fp = (prev > fp) ? prev : 0;
203 #else /* (LINUX || SOLARIS) */
205 static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
207 /* not yet implemented */
210 #endif /* (LINUX || SOLARIS) */
212 /************************************************************************/
213 /* osl_assertFailedLine */
214 /************************************************************************/
215 sal_Bool SAL_CALL osl_assertFailedLine (
216 const sal_Char* pszFileName,
217 sal_Int32 nLine,
218 const sal_Char* pszMessage)
220 oslDebugMessageFunc f = g_pDebugMessageFunc;
221 char szMessage[1024];
223 /* If there's a callback for detailed messages, use it */
224 if ( g_pDetailedDebugMessageFunc != NULL )
226 g_pDetailedDebugMessageFunc( pszFileName, nLine, pszMessage );
227 return sal_False;
230 /* if SAL assertions are disabled in general, stop here */
231 if ( getenv("DISABLE_SAL_DBGBOX") )
232 return sal_False;
234 /* format message into buffer */
235 if (pszMessage != 0)
237 snprintf(szMessage, sizeof(szMessage),
238 "Error: File %s, Line %" SAL_PRIdINT32 ": %s\n",
239 pszFileName, nLine, pszMessage);
241 else
243 snprintf(szMessage, sizeof(szMessage),
244 "Error: File %s, Line %" SAL_PRIdINT32 "\n",
245 pszFileName, nLine);
248 /* acquire lock to serialize output message(s) */
249 pthread_mutex_lock(&g_mutex);
251 /* output message buffer */
252 OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
254 /* if SAL backtrace for assertions is disabled, skip here */
255 if ( !getenv("DISABLE_SAL_BACKTRACE") )
256 osl_diagnose_backtrace_Impl(f);
258 /* release lock and leave, w/o calling osl_breakDebug() */
259 pthread_mutex_unlock(&g_mutex);
260 return sal_False;
263 /************************************************************************/
264 /* osl_breakDebug */
265 /************************************************************************/
266 void SAL_CALL osl_breakDebug()
268 exit(0);
271 /************************************************************************/
272 /* osl_reportError */
273 /************************************************************************/
274 sal_Int32 SAL_CALL osl_reportError (
275 sal_uInt32 nType,
276 const sal_Char* pszMessage)
278 (void) nType; /* unused */
279 fputs(pszMessage, stderr);
280 return 0;
283 /************************************************************************/
284 /* osl_setDebugMessageFunc */
285 /************************************************************************/
286 oslDebugMessageFunc SAL_CALL osl_setDebugMessageFunc (
287 oslDebugMessageFunc pNewFunc)
289 oslDebugMessageFunc pOldFunc = g_pDebugMessageFunc;
290 g_pDebugMessageFunc = pNewFunc;
291 return pOldFunc;
294 /************************************************************************/
295 /* osl_setDetailedDebugMessageFunc */
296 /************************************************************************/
297 pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc (
298 pfunc_osl_printDetailedDebugMessage pNewFunc)
300 oslDetailedDebugMessageFunc pOldFunc = g_pDetailedDebugMessageFunc;
301 g_pDetailedDebugMessageFunc = pNewFunc;
302 return pOldFunc;
305 /************************************************************************/
306 /* osl_trace */
307 /************************************************************************/
308 /* comment this define to stop output thread identifier*/
309 #define OSL_TRACE_THREAD 1
310 void SAL_CALL osl_trace (
311 const sal_Char* lpszFormat, ...)
313 va_list args;
315 #if defined(OSL_PROFILING)
316 fprintf(stderr, "Time: %06lu : ", osl_getGlobalTimer() );
317 #else
318 #if defined(OSL_TRACE_THREAD)
319 fprintf(
320 stderr, "Thread: %6lu :",
321 SAL_INT_CAST(unsigned long, osl_getThreadIdentifier(NULL)));
322 #else
323 fprintf(stderr, "Trace Message: ");
324 #endif
325 #endif
327 va_start(args, lpszFormat);
328 vfprintf(stderr, lpszFormat, args);
329 va_end(args);
331 fprintf(stderr,"\n");
332 fflush(stderr);
335 /************************************************************************/