The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
fileline.c
Go to the documentation of this file.
1/* fileline.c -- Get file and line number information in a backtrace.
2 Copyright (C) 2012-2024 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 (2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 (3) The name of the author may not be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33#include "config.h"
34
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <stdlib.h>
40#include <unistd.h>
41
42#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)
43#include <sys/sysctl.h>
44#endif
45
46#ifdef HAVE_MACH_O_DYLD_H
47#include <mach-o/dyld.h>
48#endif
49
50#ifdef __hpux__
51#include <dl.h>
52#endif
53
54#ifdef HAVE_WINDOWS_H
55#ifndef WIN32_LEAN_AND_MEAN
56#define WIN32_LEAN_AND_MEAN
57#endif
58
59#ifndef NOMINMAX
60#define NOMINMAX
61#endif
62
63#include <windows.h>
64#endif
65
66#include "backtrace.h"
67#include "internal.h"
68
69#ifndef HAVE_GETEXECNAME
70#define getexecname() NULL
71#endif
72
73#ifdef __hpux__
74static char *
77{
78 struct shl_descriptor *desc;
79 size_t len = sizeof (struct shl_descriptor);
80
82 if (desc == NULL)
83 return NULL;
84
85 if (shl_get_r (0, desc) == -1)
86 {
88 return NULL;
89 }
90
91 return desc->filename;
92}
93
94#else
95
96#define hpux_get_executable_path(state, error_callback, data) NULL
97
98#endif
99
100#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)
101
102#define sysctl_exec_name1(state, error_callback, data) NULL
103#define sysctl_exec_name2(state, error_callback, data) NULL
104
105#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
106
107static char *
108sysctl_exec_name (struct backtrace_state *state,
109 int mib0, int mib1, int mib2, int mib3,
111{
112 int mib[4];
113 size_t len;
114 char *name;
115 size_t rlen;
116
117 mib[0] = mib0;
118 mib[1] = mib1;
119 mib[2] = mib2;
120 mib[3] = mib3;
121
122 if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)
123 return NULL;
124 name = (char *) backtrace_alloc (state, len, error_callback, data);
125 if (name == NULL)
126 return NULL;
127 rlen = len;
128 if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)
129 {
131 return NULL;
132 }
133 return name;
134}
135
136#ifdef HAVE_KERN_PROC_ARGS
137
138static char *
141{
142 /* This variant is used on NetBSD. */
143 return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,
144 KERN_PROC_PATHNAME, error_callback, data);
145}
146
147#else
148
149#define sysctl_exec_name1(state, error_callback, data) NULL
150
151#endif
152
153#ifdef HAVE_KERN_PROC
154
155static char *
158{
159 /* This variant is used on FreeBSD. */
160 return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
162}
163
164#else
165
166#define sysctl_exec_name2(state, error_callback, data) NULL
167
168#endif
169
170#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
171
172#ifdef HAVE_MACH_O_DYLD_H
173
174static char *
177{
178 uint32_t len;
179 char *name;
180
181 len = 0;
182 if (_NSGetExecutablePath (NULL, &len) == 0)
183 return NULL;
184 name = (char *) backtrace_alloc (state, len, error_callback, data);
185 if (name == NULL)
186 return NULL;
187 if (_NSGetExecutablePath (name, &len) != 0)
188 {
190 return NULL;
191 }
192 return name;
193}
194
195#else /* !defined (HAVE_MACH_O_DYLD_H) */
196
197#define macho_get_executable_path(state, error_callback, data) NULL
198
199#endif /* !defined (HAVE_MACH_O_DYLD_H) */
200
201#if HAVE_DECL__PGMPTR
202
203#define windows_executable_filename() _pgmptr
204
205#else /* !HAVE_DECL__PGMPTR */
206
207#define windows_executable_filename() NULL
208
209#endif /* !HAVE_DECL__PGMPTR */
210
211#ifdef HAVE_WINDOWS_H
212
213#define FILENAME_BUF_SIZE (MAX_PATH)
214
215static char *
217 void *data)
218{
219 size_t got;
220 int error;
221
222 got = GetModuleFileNameA (NULL, buf, FILENAME_BUF_SIZE - 1);
223 error = GetLastError ();
224 if (got == 0
225 || (got == FILENAME_BUF_SIZE - 1 && error == ERROR_INSUFFICIENT_BUFFER))
226 {
228 "could not get the filename of the current executable",
229 error);
230 return NULL;
231 }
232 return buf;
233}
234
235#else /* !defined (HAVE_WINDOWS_H) */
236
237#define windows_get_executable_path(buf, error_callback, data) NULL
238#define FILENAME_BUF_SIZE 64
239
240#endif /* !defined (HAVE_WINDOWS_H) */
241
242/* Initialize the fileline information from the executable. Returns 1
243 on success, 0 on failure. */
244
245static int
248{
249 int failed;
250 fileline fileline_fn;
251 int pass;
252 int called_error_callback;
253 int descriptor;
254 const char *filename;
255 char buf[FILENAME_BUF_SIZE];
256
257 if (!state->threaded)
258 failed = state->fileline_initialization_failed;
259 else
260 failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
261
262 if (failed)
263 {
264 error_callback (data, "failed to read executable information", -1);
265 return 0;
266 }
267
268 if (!state->threaded)
269 fileline_fn = state->fileline_fn;
270 else
271 fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
272 if (fileline_fn != NULL)
273 return 1;
274
275 /* We have not initialized the information. Do it now. */
276
277 descriptor = -1;
278 called_error_callback = 0;
279 for (pass = 0; pass < 11; ++pass)
280 {
281 int does_not_exist;
282
283 switch (pass)
284 {
285 case 0:
286 filename = state->filename;
287 break;
288 case 1:
289 filename = getexecname ();
290 break;
291 case 2:
292 /* Test this before /proc/self/exe, as the latter exists but points
293 to the wine binary (and thus doesn't work). */
294 filename = windows_executable_filename ();
295 break;
296 case 3:
297 filename = "/proc/self/exe";
298 break;
299 case 4:
300 filename = "/proc/curproc/file";
301 break;
302 case 5:
303 snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",
304 (long) getpid ());
305 filename = buf;
306 break;
307 case 6:
309 break;
310 case 7:
312 break;
313 case 8:
315 break;
316 case 9:
318 break;
319 case 10:
321 break;
322 default:
323 abort ();
324 }
325
326 if (filename == NULL)
327 continue;
328
329 descriptor = backtrace_open (filename, error_callback, data,
330 &does_not_exist);
331 if (descriptor < 0 && !does_not_exist)
332 {
333 called_error_callback = 1;
334 break;
335 }
336 if (descriptor >= 0)
337 break;
338 }
339
340 if (descriptor < 0)
341 {
342 if (!called_error_callback)
343 {
344 if (state->filename != NULL)
345 error_callback (data, state->filename, ENOENT);
346 else
348 "libbacktrace could not find executable to open",
349 0);
350 }
351 failed = 1;
352 }
353
354 if (!failed)
355 {
356 if (!backtrace_initialize (state, filename, descriptor, error_callback,
357 data, &fileline_fn))
358 failed = 1;
359 }
360
361 if (failed)
362 {
363 if (!state->threaded)
364 state->fileline_initialization_failed = 1;
365 else
366 backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
367 return 0;
368 }
369
370 if (!state->threaded)
371 state->fileline_fn = fileline_fn;
372 else
373 {
374 backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
375
376 /* Note that if two threads initialize at once, one of the data
377 sets may be leaked. */
378 }
379
380 return 1;
381}
382
383/* Given a PC, find the file name, line number, and function name. */
384
385int
389{
391 return 0;
392
393 if (state->fileline_initialization_failed)
394 return 0;
395
396 return state->fileline_fn (state, pc, callback, error_callback, data);
397}
398
399/* Given a PC, find the symbol for it, and its value. */
400
401int
405{
407 return 0;
408
409 if (state->fileline_initialization_failed)
410 return 0;
411
412 state->syminfo_fn (state, pc, callback, error_callback, data);
413 return 1;
414}
415
416/* A backtrace_syminfo_callback that can call into a
417 backtrace_full_callback, used when we have a symbol table but no
418 debug info. */
419
420void
422 const char *symname,
423 uintptr_t symval ATTRIBUTE_UNUSED,
424 uintptr_t symsize ATTRIBUTE_UNUSED)
425{
427
428 bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname);
429}
430
431/* An error callback that corresponds to
432 backtrace_syminfo_to_full_callback. */
433
434void
436 int errnum)
437{
439
440 bdata->full_error_callback (bdata->full_data, msg, errnum);
441}
log_entry msg
Definition acutest.h:794
void * backtrace_alloc(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data)
Definition alloc.c:51
void backtrace_free(struct backtrace_state *state ATTRIBUTE_UNUSED, void *p, size_t size ATTRIBUTE_UNUSED, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
Definition alloc.c:69
void(* backtrace_syminfo_callback)(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
Definition backtrace.h:165
void(* backtrace_error_callback)(void *data, const char *msg, int errnum)
Definition backtrace.h:66
int(* backtrace_full_callback)(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
Definition backtrace.h:100
static void error_callback(void *data, const char *msg, int errnum)
Definition print.c:53
Wrappers around dlopen.
int backtrace_initialize(struct backtrace_state *state, const char *filename, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
Definition elf.c:7410
static int fileline_initialize(struct backtrace_state *state, backtrace_error_callback error_callback, void *data)
Definition fileline.c:246
void backtrace_syminfo_to_full_callback(void *data, uintptr_t pc, const char *symname, uintptr_t symval ATTRIBUTE_UNUSED, uintptr_t symsize ATTRIBUTE_UNUSED)
Definition fileline.c:421
#define windows_executable_filename()
Definition fileline.c:207
#define windows_get_executable_path(buf, error_callback, data)
Definition fileline.c:237
void backtrace_syminfo_to_full_error_callback(void *data, const char *msg, int errnum)
Definition fileline.c:435
#define FILENAME_BUF_SIZE
Definition fileline.c:238
#define sysctl_exec_name2(state, error_callback, data)
Definition fileline.c:103
#define getexecname()
Definition fileline.c:70
#define sysctl_exec_name1(state, error_callback, data)
Definition fileline.c:102
int backtrace_syminfo(struct backtrace_state *state, uintptr_t pc, backtrace_syminfo_callback callback, backtrace_error_callback error_callback, void *data)
Definition fileline.c:402
#define macho_get_executable_path(state, error_callback, data)
Definition fileline.c:197
#define hpux_get_executable_path(state, error_callback, data)
Definition fileline.c:96
int backtrace_pcinfo(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
Definition fileline.c:386
#define ATTRIBUTE_UNUSED
Definition filenames.h:42
#define backtrace_atomic_load_pointer(p)
Definition internal.h:115
int(* fileline)(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
Definition internal.h:127
#define backtrace_atomic_load_int(p)
Definition internal.h:116
#define backtrace_atomic_store_pointer(p, v)
Definition internal.h:117
#define backtrace_atomic_store_int(p, v)
Definition internal.h:119
int backtrace_open(const char *filename, backtrace_error_callback error_callback, void *data, int *does_not_exist)
Definition posix.c:59
unsigned int uint32_t
static char const * mib
Definition radict.c:55
static char const * name
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
void * state
Definition testlib.c:46
Functions to help with cleanup.
static fr_slen_t data
Definition value.h:1340