annotate libbacktrace/fileline.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* fileline.c -- Get file and line number information in a backtrace.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Written by Ian Lance Taylor, Google.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 Redistribution and use in source and binary forms, with or without
kono
parents:
diff changeset
6 modification, are permitted provided that the following conditions are
kono
parents:
diff changeset
7 met:
kono
parents:
diff changeset
8
kono
parents:
diff changeset
9 (1) Redistributions of source code must retain the above copyright
kono
parents:
diff changeset
10 notice, this list of conditions and the following disclaimer.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 (2) Redistributions in binary form must reproduce the above copyright
kono
parents:
diff changeset
13 notice, this list of conditions and the following disclaimer in
kono
parents:
diff changeset
14 the documentation and/or other materials provided with the
kono
parents:
diff changeset
15 distribution.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 (3) The name of the author may not be used to
kono
parents:
diff changeset
18 endorse or promote products derived from this software without
kono
parents:
diff changeset
19 specific prior written permission.
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
kono
parents:
diff changeset
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
kono
parents:
diff changeset
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
kono
parents:
diff changeset
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
kono
parents:
diff changeset
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
kono
parents:
diff changeset
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
kono
parents:
diff changeset
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
kono
parents:
diff changeset
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
kono
parents:
diff changeset
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
kono
parents:
diff changeset
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
kono
parents:
diff changeset
31 POSSIBILITY OF SUCH DAMAGE. */
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 #include "config.h"
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 #include <sys/types.h>
kono
parents:
diff changeset
36 #include <sys/stat.h>
kono
parents:
diff changeset
37 #include <errno.h>
kono
parents:
diff changeset
38 #include <fcntl.h>
kono
parents:
diff changeset
39 #include <stdlib.h>
kono
parents:
diff changeset
40 #include <unistd.h>
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 #include "backtrace.h"
kono
parents:
diff changeset
43 #include "internal.h"
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 #ifndef HAVE_GETEXECNAME
kono
parents:
diff changeset
46 #define getexecname() NULL
kono
parents:
diff changeset
47 #endif
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 /* Initialize the fileline information from the executable. Returns 1
kono
parents:
diff changeset
50 on success, 0 on failure. */
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 static int
kono
parents:
diff changeset
53 fileline_initialize (struct backtrace_state *state,
kono
parents:
diff changeset
54 backtrace_error_callback error_callback, void *data)
kono
parents:
diff changeset
55 {
kono
parents:
diff changeset
56 int failed;
kono
parents:
diff changeset
57 fileline fileline_fn;
kono
parents:
diff changeset
58 int pass;
kono
parents:
diff changeset
59 int called_error_callback;
kono
parents:
diff changeset
60 int descriptor;
kono
parents:
diff changeset
61 const char *filename;
kono
parents:
diff changeset
62 char buf[64];
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 if (!state->threaded)
kono
parents:
diff changeset
65 failed = state->fileline_initialization_failed;
kono
parents:
diff changeset
66 else
kono
parents:
diff changeset
67 failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 if (failed)
kono
parents:
diff changeset
70 {
kono
parents:
diff changeset
71 error_callback (data, "failed to read executable information", -1);
kono
parents:
diff changeset
72 return 0;
kono
parents:
diff changeset
73 }
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 if (!state->threaded)
kono
parents:
diff changeset
76 fileline_fn = state->fileline_fn;
kono
parents:
diff changeset
77 else
kono
parents:
diff changeset
78 fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
kono
parents:
diff changeset
79 if (fileline_fn != NULL)
kono
parents:
diff changeset
80 return 1;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 /* We have not initialized the information. Do it now. */
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 descriptor = -1;
kono
parents:
diff changeset
85 called_error_callback = 0;
kono
parents:
diff changeset
86 for (pass = 0; pass < 5; ++pass)
kono
parents:
diff changeset
87 {
kono
parents:
diff changeset
88 int does_not_exist;
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 switch (pass)
kono
parents:
diff changeset
91 {
kono
parents:
diff changeset
92 case 0:
kono
parents:
diff changeset
93 filename = state->filename;
kono
parents:
diff changeset
94 break;
kono
parents:
diff changeset
95 case 1:
kono
parents:
diff changeset
96 filename = getexecname ();
kono
parents:
diff changeset
97 break;
kono
parents:
diff changeset
98 case 2:
kono
parents:
diff changeset
99 filename = "/proc/self/exe";
kono
parents:
diff changeset
100 break;
kono
parents:
diff changeset
101 case 3:
kono
parents:
diff changeset
102 filename = "/proc/curproc/file";
kono
parents:
diff changeset
103 break;
kono
parents:
diff changeset
104 case 4:
kono
parents:
diff changeset
105 snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out",
kono
parents:
diff changeset
106 (long) getpid ());
kono
parents:
diff changeset
107 filename = buf;
kono
parents:
diff changeset
108 break;
kono
parents:
diff changeset
109 default:
kono
parents:
diff changeset
110 abort ();
kono
parents:
diff changeset
111 }
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 if (filename == NULL)
kono
parents:
diff changeset
114 continue;
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 descriptor = backtrace_open (filename, error_callback, data,
kono
parents:
diff changeset
117 &does_not_exist);
kono
parents:
diff changeset
118 if (descriptor < 0 && !does_not_exist)
kono
parents:
diff changeset
119 {
kono
parents:
diff changeset
120 called_error_callback = 1;
kono
parents:
diff changeset
121 break;
kono
parents:
diff changeset
122 }
kono
parents:
diff changeset
123 if (descriptor >= 0)
kono
parents:
diff changeset
124 break;
kono
parents:
diff changeset
125 }
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 if (descriptor < 0)
kono
parents:
diff changeset
128 {
kono
parents:
diff changeset
129 if (!called_error_callback)
kono
parents:
diff changeset
130 {
kono
parents:
diff changeset
131 if (state->filename != NULL)
kono
parents:
diff changeset
132 error_callback (data, state->filename, ENOENT);
kono
parents:
diff changeset
133 else
kono
parents:
diff changeset
134 error_callback (data,
kono
parents:
diff changeset
135 "libbacktrace could not find executable to open",
kono
parents:
diff changeset
136 0);
kono
parents:
diff changeset
137 }
kono
parents:
diff changeset
138 failed = 1;
kono
parents:
diff changeset
139 }
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 if (!failed)
kono
parents:
diff changeset
142 {
kono
parents:
diff changeset
143 if (!backtrace_initialize (state, filename, descriptor, error_callback,
kono
parents:
diff changeset
144 data, &fileline_fn))
kono
parents:
diff changeset
145 failed = 1;
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 if (failed)
kono
parents:
diff changeset
149 {
kono
parents:
diff changeset
150 if (!state->threaded)
kono
parents:
diff changeset
151 state->fileline_initialization_failed = 1;
kono
parents:
diff changeset
152 else
kono
parents:
diff changeset
153 backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
kono
parents:
diff changeset
154 return 0;
kono
parents:
diff changeset
155 }
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 if (!state->threaded)
kono
parents:
diff changeset
158 state->fileline_fn = fileline_fn;
kono
parents:
diff changeset
159 else
kono
parents:
diff changeset
160 {
kono
parents:
diff changeset
161 backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 /* Note that if two threads initialize at once, one of the data
kono
parents:
diff changeset
164 sets may be leaked. */
kono
parents:
diff changeset
165 }
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 return 1;
kono
parents:
diff changeset
168 }
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 /* Given a PC, find the file name, line number, and function name. */
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 int
kono
parents:
diff changeset
173 backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
kono
parents:
diff changeset
174 backtrace_full_callback callback,
kono
parents:
diff changeset
175 backtrace_error_callback error_callback, void *data)
kono
parents:
diff changeset
176 {
kono
parents:
diff changeset
177 if (!fileline_initialize (state, error_callback, data))
kono
parents:
diff changeset
178 return 0;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 if (state->fileline_initialization_failed)
kono
parents:
diff changeset
181 return 0;
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 return state->fileline_fn (state, pc, callback, error_callback, data);
kono
parents:
diff changeset
184 }
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 /* Given a PC, find the symbol for it, and its value. */
kono
parents:
diff changeset
187
kono
parents:
diff changeset
188 int
kono
parents:
diff changeset
189 backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
kono
parents:
diff changeset
190 backtrace_syminfo_callback callback,
kono
parents:
diff changeset
191 backtrace_error_callback error_callback, void *data)
kono
parents:
diff changeset
192 {
kono
parents:
diff changeset
193 if (!fileline_initialize (state, error_callback, data))
kono
parents:
diff changeset
194 return 0;
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 if (state->fileline_initialization_failed)
kono
parents:
diff changeset
197 return 0;
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 state->syminfo_fn (state, pc, callback, error_callback, data);
kono
parents:
diff changeset
200 return 1;
kono
parents:
diff changeset
201 }