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