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 : #include <pthread.h>
42 : #include <stddef.h>
43 :
44 : /************************************************************************/
45 : /* Internal data structures and functions */
46 : /************************************************************************/
47 :
48 : static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
49 :
50 : typedef pfunc_osl_printDebugMessage oslDebugMessageFunc;
51 : static oslDebugMessageFunc volatile g_pDebugMessageFunc = 0;
52 :
53 : typedef pfunc_osl_printDetailedDebugMessage oslDetailedDebugMessageFunc;
54 : static oslDetailedDebugMessageFunc volatile g_pDetailedDebugMessageFunc = 0;
55 :
56 : static void osl_diagnose_backtrace_Impl (
57 : oslDebugMessageFunc f);
58 :
59 : #define OSL_DIAGNOSE_OUTPUTMESSAGE(f, s) \
60 : ((f != 0) ? (*(f))((s)) : (void)fprintf(stderr, "%s", (s)))
61 :
62 : #if defined (LINUX) || defined (SOLARIS)
63 : /************************************************************************/
64 : /* osl_diagnose_frame_Impl */
65 : /************************************************************************/
66 0 : static void osl_diagnose_frame_Impl (
67 : oslDebugMessageFunc f,
68 : int depth,
69 : void * pc)
70 : {
71 0 : const char *fname = 0, *sname = 0;
72 0 : void *fbase = 0, *saddr = 0;
73 : ptrdiff_t offset;
74 : char szMessage[1024];
75 :
76 : #ifdef INCLUDED_DLFCN_H
77 : Dl_info dli;
78 0 : if (dladdr (pc, &dli) != 0)
79 : {
80 0 : fname = dli.dli_fname;
81 0 : fbase = dli.dli_fbase;
82 0 : sname = dli.dli_sname;
83 0 : saddr = dli.dli_saddr;
84 : }
85 : #endif /* INCLUDED_DLFCN_H */
86 :
87 0 : if (saddr)
88 0 : offset = (ptrdiff_t)(pc) - (ptrdiff_t)(saddr);
89 0 : else if (fbase)
90 0 : offset = (ptrdiff_t)(pc) - (ptrdiff_t)(fbase);
91 : else
92 0 : offset = (ptrdiff_t)(pc);
93 :
94 : snprintf (szMessage, sizeof(szMessage),
95 : "Backtrace: [%d] %s: %s+0x%" SAL_PRI_PTRDIFFT "x\n",
96 : depth,
97 : fname ? fname : "<unknown>",
98 : sname ? sname : "???",
99 0 : offset);
100 :
101 0 : OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
102 0 : }
103 : #endif
104 :
105 : /************************************************************************/
106 : /* osl_diagnose_backtrace_Impl */
107 : /************************************************************************/
108 : #if defined(LINUX)
109 :
110 : #include <execinfo.h>
111 :
112 : #define FRAME_COUNT 64
113 : #define FRAME_OFFSET 1
114 :
115 0 : static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
116 : {
117 : void * ppFrames[FRAME_COUNT];
118 : int i, n;
119 :
120 0 : n = backtrace (ppFrames, FRAME_COUNT);
121 0 : for (i = FRAME_OFFSET; i < n; i++)
122 : {
123 0 : osl_diagnose_frame_Impl (f, (i - FRAME_OFFSET), ppFrames[i]);
124 : }
125 0 : }
126 :
127 : #elif defined(SOLARIS)
128 :
129 : #include <pthread.h>
130 : #include <setjmp.h>
131 : #include <sys/frame.h>
132 :
133 : #if defined(SPARC)
134 :
135 : #if defined IS_LP64
136 :
137 : #define FRAME_PTR_OFFSET 1
138 : #define FRAME_OFFSET 0
139 : #define STACK_BIAS 0x7ff
140 :
141 : #else
142 :
143 : #define FRAME_PTR_OFFSET 1
144 : #define FRAME_OFFSET 0
145 : #define STACK_BIAS 0
146 :
147 : #endif
148 :
149 : #elif defined(INTEL)
150 :
151 : #define FRAME_PTR_OFFSET 3
152 : #define FRAME_OFFSET 0
153 : #define STACK_BIAS 0
154 :
155 : #endif /* (SPARC || INTEL) */
156 :
157 : static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
158 : {
159 : jmp_buf ctx;
160 : long fpval;
161 : struct frame * fp;
162 : int i;
163 :
164 : #if defined(SPARC)
165 : asm("ta 3");
166 : #endif /* SPARC */
167 : setjmp (ctx);
168 :
169 : fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
170 : fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
171 :
172 : for (i = 0; (i < FRAME_OFFSET) && (fp != 0); i++)
173 : fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
174 :
175 : for (i = 0; (fp != 0) && (fp->fr_savpc != 0); i++)
176 : {
177 : struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
178 : osl_diagnose_frame_Impl (f, i, (void*)(fp->fr_savpc));
179 : fp = (prev > fp) ? prev : 0;
180 : }
181 : }
182 :
183 : #else /* (LINUX || SOLARIS) */
184 :
185 : static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
186 : {
187 : (void) f;
188 : /* not yet implemented */
189 : }
190 :
191 : #endif /* (LINUX || SOLARIS) */
192 :
193 : /************************************************************************/
194 : /* osl_assertFailedLine */
195 : /************************************************************************/
196 :
197 : namespace {
198 :
199 : // getenv is not thread safe, so minimize use of result:
200 0 : bool isEnv(char const * name) {
201 0 : char * p = getenv(name);
202 0 : return p != NULL && *p != '\0';
203 : }
204 :
205 : }
206 :
207 0 : sal_Bool SAL_CALL osl_assertFailedLine (
208 : const sal_Char* pszFileName,
209 : sal_Int32 nLine,
210 : const sal_Char* pszMessage)
211 : {
212 0 : oslDebugMessageFunc f = g_pDebugMessageFunc;
213 : char szMessage[1024];
214 :
215 : // after reporting the assertion, abort if told so by SAL_DIAGNOSE_ABORT, but *not* if
216 : // assertions are routed to some external instance
217 0 : static bool envAbort = isEnv( "SAL_DIAGNOSE_ABORT" );
218 0 : static bool envBacktrace = isEnv( "SAL_DIAGNOSE_BACKTRACE" );
219 0 : sal_Bool const doAbort = envAbort && f == NULL;
220 :
221 : /* If there's a callback for detailed messages, use it */
222 0 : if ( g_pDetailedDebugMessageFunc != NULL )
223 : {
224 0 : g_pDetailedDebugMessageFunc( pszFileName, nLine, pszMessage );
225 0 : return sal_False;
226 : }
227 :
228 : /* format message into buffer */
229 0 : if (pszMessage != 0)
230 : {
231 : snprintf(szMessage, sizeof(szMessage),
232 : "Error: File %s, Line %" SAL_PRIdINT32 ": %s\n",
233 0 : pszFileName, nLine, pszMessage);
234 : }
235 : else
236 : {
237 : snprintf(szMessage, sizeof(szMessage),
238 : "Error: File %s, Line %" SAL_PRIdINT32 "\n",
239 0 : pszFileName, nLine);
240 : }
241 :
242 : /* acquire lock to serialize output message(s) */
243 0 : pthread_mutex_lock(&g_mutex);
244 :
245 : /* output message buffer */
246 0 : OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
247 :
248 : /* should we output backtrace? */
249 0 : if( envBacktrace )
250 0 : osl_diagnose_backtrace_Impl(f);
251 :
252 : /* release lock and leave */
253 0 : pthread_mutex_unlock(&g_mutex);
254 :
255 0 : return doAbort;
256 : }
257 :
258 : /************************************************************************/
259 : /* osl_breakDebug */
260 : /************************************************************************/
261 0 : void SAL_CALL osl_breakDebug()
262 : {
263 0 : abort();
264 : }
265 :
266 : /************************************************************************/
267 : /* osl_reportError */
268 : /************************************************************************/
269 0 : sal_Int32 SAL_CALL osl_reportError (
270 : sal_uInt32 nType,
271 : const sal_Char* pszMessage)
272 : {
273 : (void) nType; /* unused */
274 0 : fputs(pszMessage, stderr);
275 0 : return 0;
276 : }
277 :
278 : /************************************************************************/
279 : /* osl_setDebugMessageFunc */
280 : /************************************************************************/
281 0 : oslDebugMessageFunc SAL_CALL osl_setDebugMessageFunc (
282 : oslDebugMessageFunc pNewFunc)
283 : {
284 0 : oslDebugMessageFunc pOldFunc = g_pDebugMessageFunc;
285 0 : g_pDebugMessageFunc = pNewFunc;
286 0 : return pOldFunc;
287 : }
288 :
289 : /************************************************************************/
290 : /* osl_setDetailedDebugMessageFunc */
291 : /************************************************************************/
292 0 : pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc (
293 : pfunc_osl_printDetailedDebugMessage pNewFunc)
294 : {
295 0 : oslDetailedDebugMessageFunc pOldFunc = g_pDetailedDebugMessageFunc;
296 0 : g_pDetailedDebugMessageFunc = pNewFunc;
297 0 : return pOldFunc;
298 : }
299 :
300 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|