aarch64: rcpc3: Add +rcpc3 architectural feature support flag
[platform/upstream/binutils.git] / libbacktrace / fileline.c
1 /* fileline.c -- Get file and line number information in a backtrace.
2    Copyright (C) 2012-2021 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Google.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
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
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY 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 #include "backtrace.h"
51 #include "internal.h"
52
53 #ifndef HAVE_GETEXECNAME
54 #define getexecname() NULL
55 #endif
56
57 #if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)
58
59 #define sysctl_exec_name1(state, error_callback, data) NULL
60 #define sysctl_exec_name2(state, error_callback, data) NULL
61
62 #else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
63
64 static char *
65 sysctl_exec_name (struct backtrace_state *state,
66                   int mib0, int mib1, int mib2, int mib3,
67                   backtrace_error_callback error_callback, void *data)
68 {
69   int mib[4];
70   size_t len;
71   char *name;
72   size_t rlen;
73
74   mib[0] = mib0;
75   mib[1] = mib1;
76   mib[2] = mib2;
77   mib[3] = mib3;
78
79   if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)
80     return NULL;
81   name = (char *) backtrace_alloc (state, len, error_callback, data);
82   if (name == NULL)
83     return NULL;
84   rlen = len;
85   if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)
86     {
87       backtrace_free (state, name, len, error_callback, data);
88       return NULL;
89     }
90   return name;
91 }
92
93 #ifdef HAVE_KERN_PROC_ARGS
94
95 static char *
96 sysctl_exec_name1 (struct backtrace_state *state,
97                    backtrace_error_callback error_callback, void *data)
98 {
99   /* This variant is used on NetBSD.  */
100   return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,
101                            KERN_PROC_PATHNAME, error_callback, data);
102 }
103
104 #else
105
106 #define sysctl_exec_name1(state, error_callback, data) NULL
107
108 #endif
109
110 #ifdef HAVE_KERN_PROC
111
112 static char *
113 sysctl_exec_name2 (struct backtrace_state *state,
114                    backtrace_error_callback error_callback, void *data)
115 {
116   /* This variant is used on FreeBSD.  */
117   return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
118                            error_callback, data);
119 }
120
121 #else
122
123 #define sysctl_exec_name2(state, error_callback, data) NULL
124
125 #endif
126
127 #endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
128
129 #ifdef HAVE_MACH_O_DYLD_H
130
131 static char *
132 macho_get_executable_path (struct backtrace_state *state,
133                            backtrace_error_callback error_callback, void *data)
134 {
135   uint32_t len;
136   char *name;
137
138   len = 0;
139   if (_NSGetExecutablePath (NULL, &len) == 0)
140     return NULL;
141   name = (char *) backtrace_alloc (state, len, error_callback, data);
142   if (name == NULL)
143     return NULL;
144   if (_NSGetExecutablePath (name, &len) != 0)
145     {
146       backtrace_free (state, name, len, error_callback, data);
147       return NULL;
148     }
149   return name;
150 }
151
152 #else /* !defined (HAVE_MACH_O_DYLD_H) */
153
154 #define macho_get_executable_path(state, error_callback, data) NULL
155
156 #endif /* !defined (HAVE_MACH_O_DYLD_H) */
157
158 /* Initialize the fileline information from the executable.  Returns 1
159    on success, 0 on failure.  */
160
161 static int
162 fileline_initialize (struct backtrace_state *state,
163                      backtrace_error_callback error_callback, void *data)
164 {
165   int failed;
166   fileline fileline_fn;
167   int pass;
168   int called_error_callback;
169   int descriptor;
170   const char *filename;
171   char buf[64];
172
173   if (!state->threaded)
174     failed = state->fileline_initialization_failed;
175   else
176     failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
177
178   if (failed)
179     {
180       error_callback (data, "failed to read executable information", -1);
181       return 0;
182     }
183
184   if (!state->threaded)
185     fileline_fn = state->fileline_fn;
186   else
187     fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
188   if (fileline_fn != NULL)
189     return 1;
190
191   /* We have not initialized the information.  Do it now.  */
192
193   descriptor = -1;
194   called_error_callback = 0;
195   for (pass = 0; pass < 8; ++pass)
196     {
197       int does_not_exist;
198
199       switch (pass)
200         {
201         case 0:
202           filename = state->filename;
203           break;
204         case 1:
205           filename = getexecname ();
206           break;
207         case 2:
208           filename = "/proc/self/exe";
209           break;
210         case 3:
211           filename = "/proc/curproc/file";
212           break;
213         case 4:
214           snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",
215                     (long) getpid ());
216           filename = buf;
217           break;
218         case 5:
219           filename = sysctl_exec_name1 (state, error_callback, data);
220           break;
221         case 6:
222           filename = sysctl_exec_name2 (state, error_callback, data);
223           break;
224         case 7:
225           filename = macho_get_executable_path (state, error_callback, data);
226           break;
227         default:
228           abort ();
229         }
230
231       if (filename == NULL)
232         continue;
233
234       descriptor = backtrace_open (filename, error_callback, data,
235                                    &does_not_exist);
236       if (descriptor < 0 && !does_not_exist)
237         {
238           called_error_callback = 1;
239           break;
240         }
241       if (descriptor >= 0)
242         break;
243     }
244
245   if (descriptor < 0)
246     {
247       if (!called_error_callback)
248         {
249           if (state->filename != NULL)
250             error_callback (data, state->filename, ENOENT);
251           else
252             error_callback (data,
253                             "libbacktrace could not find executable to open",
254                             0);
255         }
256       failed = 1;
257     }
258
259   if (!failed)
260     {
261       if (!backtrace_initialize (state, filename, descriptor, error_callback,
262                                  data, &fileline_fn))
263         failed = 1;
264     }
265
266   if (failed)
267     {
268       if (!state->threaded)
269         state->fileline_initialization_failed = 1;
270       else
271         backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
272       return 0;
273     }
274
275   if (!state->threaded)
276     state->fileline_fn = fileline_fn;
277   else
278     {
279       backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
280
281       /* Note that if two threads initialize at once, one of the data
282          sets may be leaked.  */
283     }
284
285   return 1;
286 }
287
288 /* Given a PC, find the file name, line number, and function name.  */
289
290 int
291 backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
292                   backtrace_full_callback callback,
293                   backtrace_error_callback error_callback, void *data)
294 {
295   if (!fileline_initialize (state, error_callback, data))
296     return 0;
297
298   if (state->fileline_initialization_failed)
299     return 0;
300
301   return state->fileline_fn (state, pc, callback, error_callback, data);
302 }
303
304 /* Given a PC, find the symbol for it, and its value.  */
305
306 int
307 backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
308                    backtrace_syminfo_callback callback,
309                    backtrace_error_callback error_callback, void *data)
310 {
311   if (!fileline_initialize (state, error_callback, data))
312     return 0;
313
314   if (state->fileline_initialization_failed)
315     return 0;
316
317   state->syminfo_fn (state, pc, callback, error_callback, data);
318   return 1;
319 }
320
321 /* A backtrace_syminfo_callback that can call into a
322    backtrace_full_callback, used when we have a symbol table but no
323    debug info.  */
324
325 void
326 backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
327                                     const char *symname,
328                                     uintptr_t symval ATTRIBUTE_UNUSED,
329                                     uintptr_t symsize ATTRIBUTE_UNUSED)
330 {
331   struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
332
333   bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname);
334 }
335
336 /* An error callback that corresponds to
337    backtrace_syminfo_to_full_callback.  */
338
339 void
340 backtrace_syminfo_to_full_error_callback (void *data, const char *msg,
341                                           int errnum)
342 {
343   struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
344
345   bdata->full_error_callback (bdata->full_data, msg, errnum);
346 }