]> git.ipfire.org Git - thirdparty/gcc.git/blame - libbacktrace/fileline.c
tree-optimization/95495 - use SLP_TREE_REPRESENTATIVE in assertion
[thirdparty/gcc.git] / libbacktrace / fileline.c
CommitLineData
eff02e4f 1/* fileline.c -- Get file and line number information in a backtrace.
8d9254fc 2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
eff02e4f
ILT
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
84ebf639 10 notice, this list of conditions and the following disclaimer.
eff02e4f
ILT
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
84ebf639
CL
15 distribution.
16
eff02e4f
ILT
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>
33521509 37#include <errno.h>
eff02e4f 38#include <fcntl.h>
c0558468 39#include <stdlib.h>
b3530b94 40#include <unistd.h>
eff02e4f 41
26135684
ILT
42#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)
43#include <sys/sysctl.h>
44#endif
45
eff02e4f
ILT
46#include "backtrace.h"
47#include "internal.h"
48
33521509
ILT
49#ifndef HAVE_GETEXECNAME
50#define getexecname() NULL
51#endif
52
26135684
ILT
53#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)
54
55#define sysctl_exec_name1(state, error_callback, data) NULL
56#define sysctl_exec_name2(state, error_callback, data) NULL
57
58#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
59
60static char *
61sysctl_exec_name (struct backtrace_state *state,
62 int mib0, int mib1, int mib2, int mib3,
63 backtrace_error_callback error_callback, void *data)
64{
65 int mib[4];
66 size_t len;
67 char *name;
68 size_t rlen;
69
70 mib[0] = mib0;
71 mib[1] = mib1;
72 mib[2] = mib2;
73 mib[3] = mib3;
74
75 if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)
76 return NULL;
77 name = (char *) backtrace_alloc (state, len, error_callback, data);
78 if (name == NULL)
79 return NULL;
80 rlen = len;
81 if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)
82 {
83 backtrace_free (state, name, len, error_callback, data);
84 return NULL;
85 }
86 return name;
87}
88
89#ifdef HAVE_KERN_PROC_ARGS
90
91static char *
92sysctl_exec_name1 (struct backtrace_state *state,
93 backtrace_error_callback error_callback, void *data)
94{
95 /* This variant is used on NetBSD. */
96 return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,
97 KERN_PROC_PATHNAME, error_callback, data);
98}
99
100#else
101
102#define sysctl_exec_name1(state, error_callback, data) NULL
103
104#endif
105
106#ifdef HAVE_KERN_PROC
107
108static char *
109sysctl_exec_name2 (struct backtrace_state *state,
110 backtrace_error_callback error_callback, void *data)
111{
112 /* This variant is used on FreeBSD. */
113 return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
114 error_callback, data);
115}
116
117#else
118
119#define sysctl_exec_name2(state, error_callback, data) NULL
120
121#endif
122
123#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
124
eff02e4f
ILT
125/* Initialize the fileline information from the executable. Returns 1
126 on success, 0 on failure. */
127
128static int
129fileline_initialize (struct backtrace_state *state,
130 backtrace_error_callback error_callback, void *data)
131{
132 int failed;
133 fileline fileline_fn;
33521509
ILT
134 int pass;
135 int called_error_callback;
eff02e4f 136 int descriptor;
9283471b 137 const char *filename;
b3530b94 138 char buf[64];
eff02e4f 139
49579c7e
ILT
140 if (!state->threaded)
141 failed = state->fileline_initialization_failed;
142 else
143 failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
eff02e4f
ILT
144
145 if (failed)
146 {
8a447b3d 147 error_callback (data, "failed to read executable information", -1);
eff02e4f
ILT
148 return 0;
149 }
150
49579c7e
ILT
151 if (!state->threaded)
152 fileline_fn = state->fileline_fn;
153 else
154 fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
eff02e4f
ILT
155 if (fileline_fn != NULL)
156 return 1;
157
158 /* We have not initialized the information. Do it now. */
159
33521509
ILT
160 descriptor = -1;
161 called_error_callback = 0;
26135684 162 for (pass = 0; pass < 7; ++pass)
33521509 163 {
33521509
ILT
164 int does_not_exist;
165
166 switch (pass)
167 {
168 case 0:
169 filename = state->filename;
170 break;
171 case 1:
172 filename = getexecname ();
173 break;
174 case 2:
175 filename = "/proc/self/exe";
176 break;
177 case 3:
178 filename = "/proc/curproc/file";
179 break;
b3530b94 180 case 4:
cf311b03
RO
181 snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",
182 (long) getpid ());
b3530b94
TR
183 filename = buf;
184 break;
26135684
ILT
185 case 5:
186 filename = sysctl_exec_name1 (state, error_callback, data);
187 break;
188 case 6:
189 filename = sysctl_exec_name2 (state, error_callback, data);
190 break;
33521509
ILT
191 default:
192 abort ();
193 }
194
195 if (filename == NULL)
196 continue;
197
198 descriptor = backtrace_open (filename, error_callback, data,
199 &does_not_exist);
200 if (descriptor < 0 && !does_not_exist)
201 {
202 called_error_callback = 1;
203 break;
204 }
205 if (descriptor >= 0)
206 break;
207 }
208
eff02e4f 209 if (descriptor < 0)
33521509
ILT
210 {
211 if (!called_error_callback)
212 {
213 if (state->filename != NULL)
214 error_callback (data, state->filename, ENOENT);
215 else
216 error_callback (data,
217 "libbacktrace could not find executable to open",
218 0);
219 }
220 failed = 1;
221 }
eff02e4f
ILT
222
223 if (!failed)
224 {
9283471b
ILT
225 if (!backtrace_initialize (state, filename, descriptor, error_callback,
226 data, &fileline_fn))
eff02e4f
ILT
227 failed = 1;
228 }
229
230 if (failed)
231 {
232 if (!state->threaded)
233 state->fileline_initialization_failed = 1;
234 else
49579c7e 235 backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
eff02e4f
ILT
236 return 0;
237 }
238
239 if (!state->threaded)
240 state->fileline_fn = fileline_fn;
241 else
242 {
49579c7e
ILT
243 backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
244
245 /* Note that if two threads initialize at once, one of the data
246 sets may be leaked. */
eff02e4f
ILT
247 }
248
249 return 1;
250}
251
252/* Given a PC, find the file name, line number, and function name. */
253
254int
255backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
256 backtrace_full_callback callback,
257 backtrace_error_callback error_callback, void *data)
258{
259 if (!fileline_initialize (state, error_callback, data))
260 return 0;
261
262 if (state->fileline_initialization_failed)
263 return 0;
264
265 return state->fileline_fn (state, pc, callback, error_callback, data);
266}
267
268/* Given a PC, find the symbol for it, and its value. */
269
270int
271backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
272 backtrace_syminfo_callback callback,
273 backtrace_error_callback error_callback, void *data)
274{
275 if (!fileline_initialize (state, error_callback, data))
276 return 0;
277
278 if (state->fileline_initialization_failed)
279 return 0;
280
281 state->syminfo_fn (state, pc, callback, error_callback, data);
282 return 1;
283}