1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
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.
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).
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.
27 ************************************************************************/
29 #include "osl/diagnose.h"
34 #if defined(LINUX) || defined(SOLARIS)
36 #endif /* LINUX || SOLARIS */
38 #endif /* HAVE_DLFCN_H */
43 #ifndef INCLUDED_DLFCN_H
45 #define INCLUDED_DLFCN_H
48 #endif /* HAVE_DLFCN_H */
50 #ifndef INCLUDED_PTHREAD_H
52 #define INCLUDED_PTHREAD_H
55 #ifndef INCLUDED_STDDEF_H
57 #define INCLUDED_STDDEF_H
60 /************************************************************************/
61 /* Internal data structures and functions */
62 /************************************************************************/
64 static pthread_mutex_t g_mutex
= PTHREAD_MUTEX_INITIALIZER
;
66 typedef pfunc_osl_printDebugMessage oslDebugMessageFunc
;
67 static oslDebugMessageFunc
volatile g_pDebugMessageFunc
= 0;
69 typedef pfunc_osl_printDetailedDebugMessage oslDetailedDebugMessageFunc
;
70 static oslDetailedDebugMessageFunc
volatile g_pDetailedDebugMessageFunc
= 0;
72 static void osl_diagnose_backtrace_Impl (
73 oslDebugMessageFunc f
);
75 #define OSL_DIAGNOSE_OUTPUTMESSAGE(f, s) \
76 ((f != 0) ? (*(f))((s)) : (void)fprintf(stderr, "%s", (s)))
78 #if defined (LINUX) || defined (SOLARIS)
79 /************************************************************************/
80 /* osl_diagnose_frame_Impl */
81 /************************************************************************/
82 static void osl_diagnose_frame_Impl (
83 oslDebugMessageFunc f
,
87 const char *fname
= 0, *sname
= 0;
88 void *fbase
= 0, *saddr
= 0;
92 #ifdef INCLUDED_DLFCN_H
94 if (dladdr (pc
, &dli
) != 0)
96 fname
= dli
.dli_fname
;
97 fbase
= dli
.dli_fbase
;
98 sname
= dli
.dli_sname
;
99 saddr
= dli
.dli_saddr
;
101 #endif /* INCLUDED_DLFCN_H */
104 offset
= (ptrdiff_t)(pc
) - (ptrdiff_t)(saddr
);
106 offset
= (ptrdiff_t)(pc
) - (ptrdiff_t)(fbase
);
108 offset
= (ptrdiff_t)(pc
);
110 snprintf (szMessage
, sizeof(szMessage
),
111 "Backtrace: [%d] %s: %s+0x%" SAL_PRI_PTRDIFFT
"x\n",
113 fname
? fname
: "<unknown>",
114 sname
? sname
: "???",
117 OSL_DIAGNOSE_OUTPUTMESSAGE(f
, szMessage
);
121 /************************************************************************/
122 /* osl_diagnose_backtrace_Impl */
123 /************************************************************************/
126 #include <execinfo.h>
128 #define FRAME_COUNT 64
129 #define FRAME_OFFSET 1
131 static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f
)
133 void * ppFrames
[FRAME_COUNT
];
136 n
= backtrace (ppFrames
, FRAME_COUNT
);
137 for (i
= FRAME_OFFSET
; i
< n
; i
++)
139 osl_diagnose_frame_Impl (f
, (i
- FRAME_OFFSET
), ppFrames
[i
]);
143 #elif defined(SOLARIS)
147 #include <sys/frame.h>
153 #define FRAME_PTR_OFFSET 1
154 #define FRAME_OFFSET 0
155 #define STACK_BIAS 0x7ff
159 #define FRAME_PTR_OFFSET 1
160 #define FRAME_OFFSET 0
167 #define FRAME_PTR_OFFSET 3
168 #define FRAME_OFFSET 0
171 #endif /* (SPARC || INTEL) */
173 static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f
)
185 fpval
= ((long*)(ctx
))[FRAME_PTR_OFFSET
];
186 fp
= (struct frame
*)((char*)(fpval
) + STACK_BIAS
);
188 for (i
= 0; (i
< FRAME_OFFSET
) && (fp
!= 0); i
++)
189 fp
= (struct frame
*)((char*)(fp
->fr_savfp
) + STACK_BIAS
);
191 for (i
= 0; (fp
!= 0) && (fp
->fr_savpc
!= 0); i
++)
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;
199 #else /* (LINUX || SOLARIS) */
201 static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f
)
204 /* not yet implemented */
207 #endif /* (LINUX || SOLARIS) */
209 /************************************************************************/
210 /* osl_assertFailedLine */
211 /************************************************************************/
212 sal_Bool SAL_CALL
osl_assertFailedLine (
213 const sal_Char
* pszFileName
,
215 const sal_Char
* pszMessage
)
217 oslDebugMessageFunc f
= g_pDebugMessageFunc
;
218 char szMessage
[1024];
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 char const * env
= getenv( "SAL_DIAGNOSE_ABORT" );
223 char const * envBacktrace
= getenv( "SAL_DIAGNOSE_BACKTRACE" );
224 sal_Bool
const doAbort
= ( ( env
!= NULL
) && ( *env
!= '\0' ) && ( f
== NULL
) );
226 /* If there's a callback for detailed messages, use it */
227 if ( g_pDetailedDebugMessageFunc
!= NULL
)
229 g_pDetailedDebugMessageFunc( pszFileName
, nLine
, pszMessage
);
233 /* if SAL assertions are disabled in general, stop here */
234 if ( getenv("DISABLE_SAL_DBGBOX") )
237 /* format message into buffer */
240 snprintf(szMessage
, sizeof(szMessage
),
241 "Error: File %s, Line %" SAL_PRIdINT32
": %s\n",
242 pszFileName
, nLine
, pszMessage
);
246 snprintf(szMessage
, sizeof(szMessage
),
247 "Error: File %s, Line %" SAL_PRIdINT32
"\n",
251 /* acquire lock to serialize output message(s) */
252 pthread_mutex_lock(&g_mutex
);
254 /* output message buffer */
255 OSL_DIAGNOSE_OUTPUTMESSAGE(f
, szMessage
);
257 /* should we output backtrace? */
258 if( envBacktrace
!= NULL
&& *envBacktrace
!= '\0' )
259 osl_diagnose_backtrace_Impl(f
);
261 /* release lock and leave */
262 pthread_mutex_unlock(&g_mutex
);
267 /************************************************************************/
269 /************************************************************************/
270 void SAL_CALL
osl_breakDebug()
275 /************************************************************************/
276 /* osl_reportError */
277 /************************************************************************/
278 sal_Int32 SAL_CALL
osl_reportError (
280 const sal_Char
* pszMessage
)
282 (void) nType
; /* unused */
283 fputs(pszMessage
, stderr
);
287 /************************************************************************/
288 /* osl_setDebugMessageFunc */
289 /************************************************************************/
290 oslDebugMessageFunc SAL_CALL
osl_setDebugMessageFunc (
291 oslDebugMessageFunc pNewFunc
)
293 oslDebugMessageFunc pOldFunc
= g_pDebugMessageFunc
;
294 g_pDebugMessageFunc
= pNewFunc
;
298 /************************************************************************/
299 /* osl_setDetailedDebugMessageFunc */
300 /************************************************************************/
301 pfunc_osl_printDetailedDebugMessage SAL_CALL
osl_setDetailedDebugMessageFunc (
302 pfunc_osl_printDetailedDebugMessage pNewFunc
)
304 oslDetailedDebugMessageFunc pOldFunc
= g_pDetailedDebugMessageFunc
;
305 g_pDetailedDebugMessageFunc
= pNewFunc
;
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */