]>
Commit | Line | Data |
---|---|---|
eff02e4f | 1 | /* elf.c -- Get debug data from an ELF file for backtraces. |
cbe34bb5 | 2 | Copyright (C) 2012-2017 Free Software Foundation, Inc. |
eff02e4f ILT |
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 | |
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 | ||
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 | ||
9283471b | 35 | #include <errno.h> |
eff02e4f ILT |
36 | #include <stdlib.h> |
37 | #include <string.h> | |
38 | #include <sys/types.h> | |
9283471b ILT |
39 | #include <sys/stat.h> |
40 | #include <unistd.h> | |
eff02e4f | 41 | |
e561a992 ILT |
42 | #ifdef HAVE_DL_ITERATE_PHDR |
43 | #include <link.h> | |
44 | #endif | |
45 | ||
eff02e4f ILT |
46 | #include "backtrace.h" |
47 | #include "internal.h" | |
48 | ||
9283471b ILT |
49 | #ifndef S_ISLNK |
50 | #ifndef S_IFLNK | |
51 | #define S_IFLNK 0120000 | |
52 | #endif | |
53 | #ifndef S_IFMT | |
54 | #define S_IFMT 0170000 | |
55 | #endif | |
56 | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) | |
57 | #endif | |
58 | ||
59 | #if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN | |
60 | ||
61 | /* If strnlen is not declared, provide our own version. */ | |
62 | ||
63 | static size_t | |
64 | xstrnlen (const char *s, size_t maxlen) | |
65 | { | |
66 | size_t i; | |
67 | ||
68 | for (i = 0; i < maxlen; ++i) | |
69 | if (s[i] == '\0') | |
70 | break; | |
71 | return i; | |
72 | } | |
73 | ||
74 | #define strnlen xstrnlen | |
75 | ||
76 | #endif | |
77 | ||
e561a992 ILT |
78 | #ifndef HAVE_DL_ITERATE_PHDR |
79 | ||
80 | /* Dummy version of dl_iterate_phdr for systems that don't have it. */ | |
81 | ||
82 | #define dl_phdr_info x_dl_phdr_info | |
83 | #define dl_iterate_phdr x_dl_iterate_phdr | |
84 | ||
85 | struct dl_phdr_info | |
86 | { | |
87 | uintptr_t dlpi_addr; | |
88 | const char *dlpi_name; | |
89 | }; | |
90 | ||
91 | static int | |
92 | dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, | |
93 | size_t, void *) ATTRIBUTE_UNUSED, | |
94 | void *data ATTRIBUTE_UNUSED) | |
95 | { | |
96 | return 0; | |
97 | } | |
98 | ||
99 | #endif /* ! defined (HAVE_DL_ITERATE_PHDR) */ | |
100 | ||
eff02e4f ILT |
101 | /* The configure script must tell us whether we are 32-bit or 64-bit |
102 | ELF. We could make this code test and support either possibility, | |
103 | but there is no point. This code only works for the currently | |
104 | running executable, which means that we know the ELF mode at | |
7e2a8417 | 105 | configure time. */ |
eff02e4f ILT |
106 | |
107 | #if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64 | |
108 | #error "Unknown BACKTRACE_ELF_SIZE" | |
109 | #endif | |
110 | ||
e561a992 ILT |
111 | /* <link.h> might #include <elf.h> which might define our constants |
112 | with slightly different values. Undefine them to be safe. */ | |
113 | ||
114 | #undef EI_NIDENT | |
115 | #undef EI_MAG0 | |
116 | #undef EI_MAG1 | |
117 | #undef EI_MAG2 | |
118 | #undef EI_MAG3 | |
119 | #undef EI_CLASS | |
120 | #undef EI_DATA | |
121 | #undef EI_VERSION | |
122 | #undef ELF_MAG0 | |
123 | #undef ELF_MAG1 | |
124 | #undef ELF_MAG2 | |
125 | #undef ELF_MAG3 | |
126 | #undef ELFCLASS32 | |
127 | #undef ELFCLASS64 | |
128 | #undef ELFDATA2LSB | |
129 | #undef ELFDATA2MSB | |
130 | #undef EV_CURRENT | |
0284b52e | 131 | #undef ET_DYN |
e561a992 ILT |
132 | #undef SHN_LORESERVE |
133 | #undef SHN_XINDEX | |
f1857815 | 134 | #undef SHN_UNDEF |
e561a992 ILT |
135 | #undef SHT_SYMTAB |
136 | #undef SHT_STRTAB | |
137 | #undef SHT_DYNSYM | |
cfa658e4 | 138 | #undef STT_OBJECT |
e561a992 | 139 | #undef STT_FUNC |
9283471b | 140 | #undef NT_GNU_BUILD_ID |
e561a992 | 141 | |
eff02e4f ILT |
142 | /* Basic types. */ |
143 | ||
40d15b5b ILT |
144 | typedef uint16_t b_elf_half; /* Elf_Half. */ |
145 | typedef uint32_t b_elf_word; /* Elf_Word. */ | |
146 | typedef int32_t b_elf_sword; /* Elf_Sword. */ | |
eff02e4f ILT |
147 | |
148 | #if BACKTRACE_ELF_SIZE == 32 | |
149 | ||
40d15b5b ILT |
150 | typedef uint32_t b_elf_addr; /* Elf_Addr. */ |
151 | typedef uint32_t b_elf_off; /* Elf_Off. */ | |
eff02e4f | 152 | |
40d15b5b | 153 | typedef uint32_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ |
eff02e4f ILT |
154 | |
155 | #else | |
156 | ||
40d15b5b ILT |
157 | typedef uint64_t b_elf_addr; /* Elf_Addr. */ |
158 | typedef uint64_t b_elf_off; /* Elf_Off. */ | |
159 | typedef uint64_t b_elf_xword; /* Elf_Xword. */ | |
160 | typedef int64_t b_elf_sxword; /* Elf_Sxword. */ | |
eff02e4f | 161 | |
40d15b5b | 162 | typedef uint64_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ |
eff02e4f ILT |
163 | |
164 | #endif | |
165 | ||
166 | /* Data structures and associated constants. */ | |
167 | ||
168 | #define EI_NIDENT 16 | |
169 | ||
170 | typedef struct { | |
171 | unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ | |
40d15b5b ILT |
172 | b_elf_half e_type; /* Identifies object file type */ |
173 | b_elf_half e_machine; /* Specifies required architecture */ | |
174 | b_elf_word e_version; /* Identifies object file version */ | |
175 | b_elf_addr e_entry; /* Entry point virtual address */ | |
176 | b_elf_off e_phoff; /* Program header table file offset */ | |
177 | b_elf_off e_shoff; /* Section header table file offset */ | |
178 | b_elf_word e_flags; /* Processor-specific flags */ | |
179 | b_elf_half e_ehsize; /* ELF header size in bytes */ | |
180 | b_elf_half e_phentsize; /* Program header table entry size */ | |
181 | b_elf_half e_phnum; /* Program header table entry count */ | |
182 | b_elf_half e_shentsize; /* Section header table entry size */ | |
183 | b_elf_half e_shnum; /* Section header table entry count */ | |
184 | b_elf_half e_shstrndx; /* Section header string table index */ | |
185 | } b_elf_ehdr; /* Elf_Ehdr. */ | |
eff02e4f ILT |
186 | |
187 | #define EI_MAG0 0 | |
188 | #define EI_MAG1 1 | |
189 | #define EI_MAG2 2 | |
190 | #define EI_MAG3 3 | |
191 | #define EI_CLASS 4 | |
192 | #define EI_DATA 5 | |
193 | #define EI_VERSION 6 | |
194 | ||
195 | #define ELFMAG0 0x7f | |
196 | #define ELFMAG1 'E' | |
197 | #define ELFMAG2 'L' | |
198 | #define ELFMAG3 'F' | |
199 | ||
200 | #define ELFCLASS32 1 | |
201 | #define ELFCLASS64 2 | |
202 | ||
203 | #define ELFDATA2LSB 1 | |
204 | #define ELFDATA2MSB 2 | |
205 | ||
206 | #define EV_CURRENT 1 | |
207 | ||
0284b52e JJ |
208 | #define ET_DYN 3 |
209 | ||
eff02e4f | 210 | typedef struct { |
40d15b5b ILT |
211 | b_elf_word sh_name; /* Section name, index in string tbl */ |
212 | b_elf_word sh_type; /* Type of section */ | |
213 | b_elf_wxword sh_flags; /* Miscellaneous section attributes */ | |
214 | b_elf_addr sh_addr; /* Section virtual addr at execution */ | |
215 | b_elf_off sh_offset; /* Section file offset */ | |
216 | b_elf_wxword sh_size; /* Size of section in bytes */ | |
217 | b_elf_word sh_link; /* Index of another section */ | |
218 | b_elf_word sh_info; /* Additional section information */ | |
219 | b_elf_wxword sh_addralign; /* Section alignment */ | |
220 | b_elf_wxword sh_entsize; /* Entry size if section holds table */ | |
221 | } b_elf_shdr; /* Elf_Shdr. */ | |
eff02e4f | 222 | |
f1857815 | 223 | #define SHN_UNDEF 0x0000 /* Undefined section */ |
eff02e4f ILT |
224 | #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ |
225 | #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ | |
226 | ||
227 | #define SHT_SYMTAB 2 | |
228 | #define SHT_STRTAB 3 | |
229 | #define SHT_DYNSYM 11 | |
230 | ||
231 | #if BACKTRACE_ELF_SIZE == 32 | |
232 | ||
233 | typedef struct | |
234 | { | |
40d15b5b ILT |
235 | b_elf_word st_name; /* Symbol name, index in string tbl */ |
236 | b_elf_addr st_value; /* Symbol value */ | |
237 | b_elf_word st_size; /* Symbol size */ | |
eff02e4f ILT |
238 | unsigned char st_info; /* Symbol binding and type */ |
239 | unsigned char st_other; /* Visibility and other data */ | |
40d15b5b ILT |
240 | b_elf_half st_shndx; /* Symbol section index */ |
241 | } b_elf_sym; /* Elf_Sym. */ | |
eff02e4f ILT |
242 | |
243 | #else /* BACKTRACE_ELF_SIZE != 32 */ | |
244 | ||
245 | typedef struct | |
246 | { | |
40d15b5b | 247 | b_elf_word st_name; /* Symbol name, index in string tbl */ |
eff02e4f ILT |
248 | unsigned char st_info; /* Symbol binding and type */ |
249 | unsigned char st_other; /* Visibility and other data */ | |
40d15b5b ILT |
250 | b_elf_half st_shndx; /* Symbol section index */ |
251 | b_elf_addr st_value; /* Symbol value */ | |
252 | b_elf_xword st_size; /* Symbol size */ | |
253 | } b_elf_sym; /* Elf_Sym. */ | |
eff02e4f ILT |
254 | |
255 | #endif /* BACKTRACE_ELF_SIZE != 32 */ | |
256 | ||
cfa658e4 | 257 | #define STT_OBJECT 1 |
eff02e4f ILT |
258 | #define STT_FUNC 2 |
259 | ||
9283471b ILT |
260 | typedef struct |
261 | { | |
262 | uint32_t namesz; | |
263 | uint32_t descsz; | |
264 | uint32_t type; | |
265 | char name[1]; | |
266 | } b_elf_note; | |
267 | ||
268 | #define NT_GNU_BUILD_ID 3 | |
269 | ||
eff02e4f ILT |
270 | /* An index of ELF sections we care about. */ |
271 | ||
272 | enum debug_section | |
273 | { | |
274 | DEBUG_INFO, | |
275 | DEBUG_LINE, | |
276 | DEBUG_ABBREV, | |
277 | DEBUG_RANGES, | |
278 | DEBUG_STR, | |
279 | DEBUG_MAX | |
280 | }; | |
281 | ||
282 | /* Names of sections, indexed by enum elf_section. */ | |
283 | ||
284 | static const char * const debug_section_names[DEBUG_MAX] = | |
285 | { | |
286 | ".debug_info", | |
287 | ".debug_line", | |
288 | ".debug_abbrev", | |
289 | ".debug_ranges", | |
290 | ".debug_str" | |
291 | }; | |
292 | ||
293 | /* Information we gather for the sections we care about. */ | |
294 | ||
295 | struct debug_section_info | |
296 | { | |
297 | /* Section file offset. */ | |
298 | off_t offset; | |
299 | /* Section size. */ | |
300 | size_t size; | |
301 | /* Section contents, after read from file. */ | |
302 | const unsigned char *data; | |
303 | }; | |
304 | ||
305 | /* Information we keep for an ELF symbol. */ | |
306 | ||
307 | struct elf_symbol | |
308 | { | |
309 | /* The name of the symbol. */ | |
310 | const char *name; | |
311 | /* The address of the symbol. */ | |
312 | uintptr_t address; | |
313 | /* The size of the symbol. */ | |
314 | size_t size; | |
315 | }; | |
316 | ||
317 | /* Information to pass to elf_syminfo. */ | |
318 | ||
319 | struct elf_syminfo_data | |
320 | { | |
e561a992 ILT |
321 | /* Symbols for the next module. */ |
322 | struct elf_syminfo_data *next; | |
eff02e4f ILT |
323 | /* The ELF symbols, sorted by address. */ |
324 | struct elf_symbol *symbols; | |
325 | /* The number of symbols. */ | |
326 | size_t count; | |
327 | }; | |
328 | ||
9283471b ILT |
329 | /* Compute the CRC-32 of BUF/LEN. This uses the CRC used for |
330 | .gnu_debuglink files. */ | |
331 | ||
332 | static uint32_t | |
333 | elf_crc32 (uint32_t crc, const unsigned char *buf, size_t len) | |
334 | { | |
335 | static const uint32_t crc32_table[256] = | |
336 | { | |
337 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, | |
338 | 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, | |
339 | 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, | |
340 | 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, | |
341 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, | |
342 | 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, | |
343 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, | |
344 | 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | |
345 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, | |
346 | 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, | |
347 | 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, | |
348 | 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, | |
349 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, | |
350 | 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, | |
351 | 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, | |
352 | 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | |
353 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, | |
354 | 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, | |
355 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, | |
356 | 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, | |
357 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, | |
358 | 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, | |
359 | 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, | |
360 | 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | |
361 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, | |
362 | 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, | |
363 | 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, | |
364 | 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, | |
365 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, | |
366 | 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, | |
367 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, | |
368 | 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | |
369 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, | |
370 | 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, | |
371 | 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, | |
372 | 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, | |
373 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, | |
374 | 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, | |
375 | 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, | |
376 | 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | |
377 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, | |
378 | 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, | |
379 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, | |
380 | 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, | |
381 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, | |
382 | 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, | |
383 | 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, | |
384 | 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | |
385 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, | |
386 | 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, | |
387 | 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, | |
388 | 0x2d02ef8d | |
389 | }; | |
390 | const unsigned char *end; | |
391 | ||
392 | crc = ~crc; | |
393 | for (end = buf + len; buf < end; ++ buf) | |
394 | crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); | |
395 | return ~crc; | |
396 | } | |
397 | ||
398 | /* Return the CRC-32 of the entire file open at DESCRIPTOR. */ | |
399 | ||
400 | static uint32_t | |
401 | elf_crc32_file (struct backtrace_state *state, int descriptor, | |
402 | backtrace_error_callback error_callback, void *data) | |
403 | { | |
404 | struct stat st; | |
405 | struct backtrace_view file_view; | |
406 | uint32_t ret; | |
407 | ||
408 | if (fstat (descriptor, &st) < 0) | |
409 | { | |
410 | error_callback (data, "fstat", errno); | |
411 | return 0; | |
412 | } | |
413 | ||
414 | if (!backtrace_get_view (state, descriptor, 0, st.st_size, error_callback, | |
415 | data, &file_view)) | |
416 | return 0; | |
417 | ||
418 | ret = elf_crc32 (0, (const unsigned char *) file_view.data, st.st_size); | |
419 | ||
420 | backtrace_release_view (state, &file_view, error_callback, data); | |
421 | ||
422 | return ret; | |
423 | } | |
424 | ||
eff02e4f ILT |
425 | /* A dummy callback function used when we can't find any debug info. */ |
426 | ||
427 | static int | |
428 | elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED, | |
429 | uintptr_t pc ATTRIBUTE_UNUSED, | |
430 | backtrace_full_callback callback ATTRIBUTE_UNUSED, | |
431 | backtrace_error_callback error_callback, void *data) | |
432 | { | |
433 | error_callback (data, "no debug info in ELF executable", -1); | |
434 | return 0; | |
435 | } | |
436 | ||
437 | /* A dummy callback function used when we can't find a symbol | |
438 | table. */ | |
439 | ||
440 | static void | |
441 | elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED, | |
cfa658e4 | 442 | uintptr_t addr ATTRIBUTE_UNUSED, |
eff02e4f ILT |
443 | backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, |
444 | backtrace_error_callback error_callback, void *data) | |
445 | { | |
446 | error_callback (data, "no symbol table in ELF executable", -1); | |
447 | } | |
448 | ||
449 | /* Compare struct elf_symbol for qsort. */ | |
450 | ||
451 | static int | |
452 | elf_symbol_compare (const void *v1, const void *v2) | |
453 | { | |
454 | const struct elf_symbol *e1 = (const struct elf_symbol *) v1; | |
455 | const struct elf_symbol *e2 = (const struct elf_symbol *) v2; | |
456 | ||
457 | if (e1->address < e2->address) | |
458 | return -1; | |
459 | else if (e1->address > e2->address) | |
460 | return 1; | |
461 | else | |
462 | return 0; | |
463 | } | |
464 | ||
cfa658e4 | 465 | /* Compare an ADDR against an elf_symbol for bsearch. We allocate one |
eff02e4f ILT |
466 | extra entry in the array so that this can look safely at the next |
467 | entry. */ | |
468 | ||
469 | static int | |
470 | elf_symbol_search (const void *vkey, const void *ventry) | |
471 | { | |
472 | const uintptr_t *key = (const uintptr_t *) vkey; | |
473 | const struct elf_symbol *entry = (const struct elf_symbol *) ventry; | |
cfa658e4 | 474 | uintptr_t addr; |
eff02e4f | 475 | |
cfa658e4 ILT |
476 | addr = *key; |
477 | if (addr < entry->address) | |
eff02e4f | 478 | return -1; |
cfa658e4 | 479 | else if (addr >= entry->address + entry->size) |
eff02e4f ILT |
480 | return 1; |
481 | else | |
482 | return 0; | |
483 | } | |
484 | ||
485 | /* Initialize the symbol table info for elf_syminfo. */ | |
486 | ||
487 | static int | |
488 | elf_initialize_syminfo (struct backtrace_state *state, | |
f1857815 | 489 | uintptr_t base_address, |
eff02e4f ILT |
490 | const unsigned char *symtab_data, size_t symtab_size, |
491 | const unsigned char *strtab, size_t strtab_size, | |
492 | backtrace_error_callback error_callback, | |
493 | void *data, struct elf_syminfo_data *sdata) | |
494 | { | |
495 | size_t sym_count; | |
40d15b5b | 496 | const b_elf_sym *sym; |
eff02e4f ILT |
497 | size_t elf_symbol_count; |
498 | size_t elf_symbol_size; | |
499 | struct elf_symbol *elf_symbols; | |
500 | size_t i; | |
501 | unsigned int j; | |
502 | ||
40d15b5b | 503 | sym_count = symtab_size / sizeof (b_elf_sym); |
eff02e4f ILT |
504 | |
505 | /* We only care about function symbols. Count them. */ | |
40d15b5b | 506 | sym = (const b_elf_sym *) symtab_data; |
eff02e4f ILT |
507 | elf_symbol_count = 0; |
508 | for (i = 0; i < sym_count; ++i, ++sym) | |
509 | { | |
cfa658e4 ILT |
510 | int info; |
511 | ||
512 | info = sym->st_info & 0xf; | |
f1857815 JJ |
513 | if ((info == STT_FUNC || info == STT_OBJECT) |
514 | && sym->st_shndx != SHN_UNDEF) | |
eff02e4f ILT |
515 | ++elf_symbol_count; |
516 | } | |
517 | ||
518 | elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol); | |
519 | elf_symbols = ((struct elf_symbol *) | |
520 | backtrace_alloc (state, elf_symbol_size, error_callback, | |
521 | data)); | |
522 | if (elf_symbols == NULL) | |
523 | return 0; | |
524 | ||
40d15b5b | 525 | sym = (const b_elf_sym *) symtab_data; |
eff02e4f ILT |
526 | j = 0; |
527 | for (i = 0; i < sym_count; ++i, ++sym) | |
528 | { | |
cfa658e4 ILT |
529 | int info; |
530 | ||
531 | info = sym->st_info & 0xf; | |
532 | if (info != STT_FUNC && info != STT_OBJECT) | |
eff02e4f | 533 | continue; |
f1857815 JJ |
534 | if (sym->st_shndx == SHN_UNDEF) |
535 | continue; | |
eff02e4f ILT |
536 | if (sym->st_name >= strtab_size) |
537 | { | |
538 | error_callback (data, "symbol string index out of range", 0); | |
539 | backtrace_free (state, elf_symbols, elf_symbol_size, error_callback, | |
540 | data); | |
541 | return 0; | |
542 | } | |
543 | elf_symbols[j].name = (const char *) strtab + sym->st_name; | |
f1857815 | 544 | elf_symbols[j].address = sym->st_value + base_address; |
eff02e4f ILT |
545 | elf_symbols[j].size = sym->st_size; |
546 | ++j; | |
547 | } | |
548 | ||
c5604b48 ILT |
549 | backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol), |
550 | elf_symbol_compare); | |
eff02e4f | 551 | |
e561a992 | 552 | sdata->next = NULL; |
eff02e4f ILT |
553 | sdata->symbols = elf_symbols; |
554 | sdata->count = elf_symbol_count; | |
555 | ||
556 | return 1; | |
557 | } | |
558 | ||
e561a992 ILT |
559 | /* Add EDATA to the list in STATE. */ |
560 | ||
561 | static void | |
562 | elf_add_syminfo_data (struct backtrace_state *state, | |
563 | struct elf_syminfo_data *edata) | |
564 | { | |
565 | if (!state->threaded) | |
566 | { | |
567 | struct elf_syminfo_data **pp; | |
568 | ||
74f80620 | 569 | for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; |
e561a992 ILT |
570 | *pp != NULL; |
571 | pp = &(*pp)->next) | |
572 | ; | |
573 | *pp = edata; | |
574 | } | |
575 | else | |
576 | { | |
577 | while (1) | |
578 | { | |
579 | struct elf_syminfo_data **pp; | |
580 | ||
74f80620 | 581 | pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; |
e561a992 ILT |
582 | |
583 | while (1) | |
584 | { | |
585 | struct elf_syminfo_data *p; | |
586 | ||
49579c7e | 587 | p = backtrace_atomic_load_pointer (pp); |
e561a992 ILT |
588 | |
589 | if (p == NULL) | |
590 | break; | |
591 | ||
592 | pp = &p->next; | |
593 | } | |
594 | ||
595 | if (__sync_bool_compare_and_swap (pp, NULL, edata)) | |
596 | break; | |
597 | } | |
598 | } | |
599 | } | |
600 | ||
cfa658e4 | 601 | /* Return the symbol name and value for an ADDR. */ |
eff02e4f ILT |
602 | |
603 | static void | |
cfa658e4 | 604 | elf_syminfo (struct backtrace_state *state, uintptr_t addr, |
eff02e4f ILT |
605 | backtrace_syminfo_callback callback, |
606 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, | |
607 | void *data) | |
608 | { | |
609 | struct elf_syminfo_data *edata; | |
78625ce6 AM |
610 | struct elf_symbol *sym = NULL; |
611 | ||
612 | if (!state->threaded) | |
613 | { | |
614 | for (edata = (struct elf_syminfo_data *) state->syminfo_data; | |
615 | edata != NULL; | |
616 | edata = edata->next) | |
617 | { | |
618 | sym = ((struct elf_symbol *) | |
cfa658e4 | 619 | bsearch (&addr, edata->symbols, edata->count, |
78625ce6 AM |
620 | sizeof (struct elf_symbol), elf_symbol_search)); |
621 | if (sym != NULL) | |
622 | break; | |
623 | } | |
624 | } | |
625 | else | |
626 | { | |
627 | struct elf_syminfo_data **pp; | |
628 | ||
629 | pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; | |
630 | while (1) | |
631 | { | |
49579c7e | 632 | edata = backtrace_atomic_load_pointer (pp); |
78625ce6 AM |
633 | if (edata == NULL) |
634 | break; | |
635 | ||
636 | sym = ((struct elf_symbol *) | |
cfa658e4 | 637 | bsearch (&addr, edata->symbols, edata->count, |
78625ce6 AM |
638 | sizeof (struct elf_symbol), elf_symbol_search)); |
639 | if (sym != NULL) | |
640 | break; | |
641 | ||
642 | pp = &edata->next; | |
643 | } | |
644 | } | |
eff02e4f | 645 | |
eff02e4f | 646 | if (sym == NULL) |
1f96a712 | 647 | callback (data, addr, NULL, 0, 0); |
eff02e4f | 648 | else |
1f96a712 | 649 | callback (data, addr, sym->name, sym->address, sym->size); |
eff02e4f ILT |
650 | } |
651 | ||
9283471b ILT |
652 | /* Return whether FILENAME is a symlink. */ |
653 | ||
654 | static int | |
655 | elf_is_symlink (const char *filename) | |
656 | { | |
657 | struct stat st; | |
658 | ||
659 | if (lstat (filename, &st) < 0) | |
660 | return 0; | |
661 | return S_ISLNK (st.st_mode); | |
662 | } | |
663 | ||
664 | /* Return the results of reading the symlink FILENAME in a buffer | |
665 | allocated by backtrace_alloc. Return the length of the buffer in | |
666 | *LEN. */ | |
667 | ||
668 | static char * | |
669 | elf_readlink (struct backtrace_state *state, const char *filename, | |
670 | backtrace_error_callback error_callback, void *data, | |
671 | size_t *plen) | |
672 | { | |
673 | size_t len; | |
674 | char *buf; | |
675 | ||
676 | len = 128; | |
677 | while (1) | |
678 | { | |
679 | ssize_t rl; | |
680 | ||
681 | buf = backtrace_alloc (state, len, error_callback, data); | |
682 | if (buf == NULL) | |
683 | return NULL; | |
684 | rl = readlink (filename, buf, len); | |
685 | if (rl < 0) | |
686 | { | |
687 | backtrace_free (state, buf, len, error_callback, data); | |
688 | return NULL; | |
689 | } | |
690 | if ((size_t) rl < len - 1) | |
691 | { | |
692 | buf[rl] = '\0'; | |
693 | *plen = len; | |
694 | return buf; | |
695 | } | |
696 | backtrace_free (state, buf, len, error_callback, data); | |
697 | len *= 2; | |
698 | } | |
699 | } | |
700 | ||
701 | /* Open a separate debug info file, using the build ID to find it. | |
702 | Returns an open file descriptor, or -1. | |
703 | ||
704 | The GDB manual says that the only place gdb looks for a debug file | |
705 | when the build ID is known is in /usr/lib/debug/.build-id. */ | |
706 | ||
707 | static int | |
708 | elf_open_debugfile_by_buildid (struct backtrace_state *state, | |
709 | const char *buildid_data, size_t buildid_size, | |
710 | backtrace_error_callback error_callback, | |
711 | void *data) | |
712 | { | |
713 | const char * const prefix = "/usr/lib/debug/.build-id/"; | |
714 | const size_t prefix_len = strlen (prefix); | |
715 | const char * const suffix = ".debug"; | |
716 | const size_t suffix_len = strlen (suffix); | |
717 | size_t len; | |
718 | char *bd_filename; | |
719 | char *t; | |
720 | size_t i; | |
721 | int ret; | |
722 | int does_not_exist; | |
723 | ||
724 | len = prefix_len + buildid_size * 2 + suffix_len + 2; | |
725 | bd_filename = backtrace_alloc (state, len, error_callback, data); | |
726 | if (bd_filename == NULL) | |
727 | return -1; | |
728 | ||
729 | t = bd_filename; | |
730 | memcpy (t, prefix, prefix_len); | |
731 | t += prefix_len; | |
732 | for (i = 0; i < buildid_size; i++) | |
733 | { | |
734 | unsigned char b; | |
735 | unsigned char nib; | |
736 | ||
737 | b = (unsigned char) buildid_data[i]; | |
738 | nib = (b & 0xf0) >> 4; | |
739 | *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10; | |
740 | nib = b & 0x0f; | |
741 | *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10; | |
742 | if (i == 0) | |
743 | *t++ = '/'; | |
744 | } | |
745 | memcpy (t, suffix, suffix_len); | |
746 | t[suffix_len] = '\0'; | |
747 | ||
748 | ret = backtrace_open (bd_filename, error_callback, data, &does_not_exist); | |
749 | ||
750 | backtrace_free (state, bd_filename, len, error_callback, data); | |
751 | ||
752 | /* gdb checks that the debuginfo file has the same build ID note. | |
753 | That seems kind of pointless to me--why would it have the right | |
754 | name but not the right build ID?--so skipping the check. */ | |
755 | ||
756 | return ret; | |
757 | } | |
758 | ||
759 | /* Try to open a file whose name is PREFIX (length PREFIX_LEN) | |
760 | concatenated with PREFIX2 (length PREFIX2_LEN) concatenated with | |
761 | DEBUGLINK_NAME. Returns an open file descriptor, or -1. */ | |
762 | ||
763 | static int | |
764 | elf_try_debugfile (struct backtrace_state *state, const char *prefix, | |
765 | size_t prefix_len, const char *prefix2, size_t prefix2_len, | |
766 | const char *debuglink_name, | |
767 | backtrace_error_callback error_callback, void *data) | |
768 | { | |
769 | size_t debuglink_len; | |
770 | size_t try_len; | |
771 | char *try; | |
772 | int does_not_exist; | |
773 | int ret; | |
774 | ||
775 | debuglink_len = strlen (debuglink_name); | |
776 | try_len = prefix_len + prefix2_len + debuglink_len + 1; | |
777 | try = backtrace_alloc (state, try_len, error_callback, data); | |
778 | if (try == NULL) | |
779 | return -1; | |
780 | ||
781 | memcpy (try, prefix, prefix_len); | |
782 | memcpy (try + prefix_len, prefix2, prefix2_len); | |
783 | memcpy (try + prefix_len + prefix2_len, debuglink_name, debuglink_len); | |
784 | try[prefix_len + prefix2_len + debuglink_len] = '\0'; | |
785 | ||
786 | ret = backtrace_open (try, error_callback, data, &does_not_exist); | |
787 | ||
788 | backtrace_free (state, try, try_len, error_callback, data); | |
789 | ||
790 | return ret; | |
791 | } | |
792 | ||
793 | /* Find a separate debug info file, using the debuglink section data | |
794 | to find it. Returns an open file descriptor, or -1. */ | |
795 | ||
796 | static int | |
797 | elf_find_debugfile_by_debuglink (struct backtrace_state *state, | |
798 | const char *filename, | |
799 | const char *debuglink_name, | |
800 | backtrace_error_callback error_callback, | |
801 | void *data) | |
802 | { | |
803 | int ret; | |
804 | char *alc; | |
805 | size_t alc_len; | |
806 | const char *slash; | |
807 | int ddescriptor; | |
808 | const char *prefix; | |
809 | size_t prefix_len; | |
810 | ||
811 | /* Resolve symlinks in FILENAME. Since FILENAME is fairly likely to | |
812 | be /proc/self/exe, symlinks are common. We don't try to resolve | |
813 | the whole path name, just the base name. */ | |
814 | ret = -1; | |
815 | alc = NULL; | |
816 | alc_len = 0; | |
817 | while (elf_is_symlink (filename)) | |
818 | { | |
819 | char *new_buf; | |
820 | size_t new_len; | |
821 | ||
822 | new_buf = elf_readlink (state, filename, error_callback, data, &new_len); | |
823 | if (new_buf == NULL) | |
824 | break; | |
825 | ||
826 | if (new_buf[0] == '/') | |
827 | filename = new_buf; | |
828 | else | |
829 | { | |
830 | slash = strrchr (filename, '/'); | |
831 | if (slash == NULL) | |
832 | filename = new_buf; | |
833 | else | |
834 | { | |
835 | size_t clen; | |
836 | char *c; | |
837 | ||
838 | slash++; | |
839 | clen = slash - filename + strlen (new_buf) + 1; | |
840 | c = backtrace_alloc (state, clen, error_callback, data); | |
841 | if (c == NULL) | |
842 | goto done; | |
843 | ||
844 | memcpy (c, filename, slash - filename); | |
845 | memcpy (c + (slash - filename), new_buf, strlen (new_buf)); | |
846 | c[slash - filename + strlen (new_buf)] = '\0'; | |
847 | backtrace_free (state, new_buf, new_len, error_callback, data); | |
848 | filename = c; | |
849 | new_buf = c; | |
850 | new_len = clen; | |
851 | } | |
852 | } | |
853 | ||
854 | if (alc != NULL) | |
855 | backtrace_free (state, alc, alc_len, error_callback, data); | |
856 | alc = new_buf; | |
857 | alc_len = new_len; | |
858 | } | |
859 | ||
860 | /* Look for DEBUGLINK_NAME in the same directory as FILENAME. */ | |
861 | ||
862 | slash = strrchr (filename, '/'); | |
863 | if (slash == NULL) | |
864 | { | |
865 | prefix = ""; | |
866 | prefix_len = 0; | |
867 | } | |
868 | else | |
869 | { | |
870 | slash++; | |
871 | prefix = filename; | |
872 | prefix_len = slash - filename; | |
873 | } | |
874 | ||
875 | ddescriptor = elf_try_debugfile (state, prefix, prefix_len, "", 0, | |
876 | debuglink_name, error_callback, data); | |
877 | if (ddescriptor >= 0) | |
878 | { | |
879 | ret = ddescriptor; | |
880 | goto done; | |
881 | } | |
882 | ||
883 | /* Look for DEBUGLINK_NAME in a .debug subdirectory of FILENAME. */ | |
884 | ||
885 | ddescriptor = elf_try_debugfile (state, prefix, prefix_len, ".debug/", | |
886 | strlen (".debug/"), debuglink_name, | |
887 | error_callback, data); | |
888 | if (ddescriptor >= 0) | |
889 | { | |
890 | ret = ddescriptor; | |
891 | goto done; | |
892 | } | |
893 | ||
894 | /* Look for DEBUGLINK_NAME in /usr/lib/debug. */ | |
895 | ||
896 | ddescriptor = elf_try_debugfile (state, "/usr/lib/debug/", | |
897 | strlen ("/usr/lib/debug/"), prefix, | |
898 | prefix_len, debuglink_name, | |
899 | error_callback, data); | |
900 | if (ddescriptor >= 0) | |
901 | ret = ddescriptor; | |
902 | ||
903 | done: | |
904 | if (alc != NULL && alc_len > 0) | |
905 | backtrace_free (state, alc, alc_len, error_callback, data); | |
906 | return ret; | |
907 | } | |
908 | ||
909 | /* Open a separate debug info file, using the debuglink section data | |
910 | to find it. Returns an open file descriptor, or -1. */ | |
911 | ||
912 | static int | |
913 | elf_open_debugfile_by_debuglink (struct backtrace_state *state, | |
914 | const char *filename, | |
915 | const char *debuglink_name, | |
916 | uint32_t debuglink_crc, | |
917 | backtrace_error_callback error_callback, | |
918 | void *data) | |
919 | { | |
920 | int ddescriptor; | |
921 | uint32_t got_crc; | |
922 | ||
923 | ddescriptor = elf_find_debugfile_by_debuglink (state, filename, | |
924 | debuglink_name, | |
925 | error_callback, data); | |
926 | if (ddescriptor < 0) | |
927 | return -1; | |
928 | ||
929 | got_crc = elf_crc32_file (state, ddescriptor, error_callback, data); | |
930 | if (got_crc != debuglink_crc) | |
931 | { | |
932 | backtrace_close (ddescriptor, error_callback, data); | |
933 | return -1; | |
934 | } | |
935 | ||
936 | return ddescriptor; | |
937 | } | |
938 | ||
0284b52e JJ |
939 | /* Add the backtrace data for one ELF file. Returns 1 on success, |
940 | 0 on failure (in both cases descriptor is closed) or -1 if exe | |
941 | is non-zero and the ELF file is ET_DYN, which tells the caller that | |
942 | elf_add will need to be called on the descriptor again after | |
943 | base_address is determined. */ | |
eff02e4f | 944 | |
e561a992 | 945 | static int |
9283471b ILT |
946 | elf_add (struct backtrace_state *state, const char *filename, int descriptor, |
947 | uintptr_t base_address, backtrace_error_callback error_callback, | |
948 | void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf, | |
949 | int exe, int debuginfo) | |
eff02e4f ILT |
950 | { |
951 | struct backtrace_view ehdr_view; | |
40d15b5b | 952 | b_elf_ehdr ehdr; |
eff02e4f ILT |
953 | off_t shoff; |
954 | unsigned int shnum; | |
955 | unsigned int shstrndx; | |
956 | struct backtrace_view shdrs_view; | |
957 | int shdrs_view_valid; | |
40d15b5b ILT |
958 | const b_elf_shdr *shdrs; |
959 | const b_elf_shdr *shstrhdr; | |
eff02e4f ILT |
960 | size_t shstr_size; |
961 | off_t shstr_off; | |
962 | struct backtrace_view names_view; | |
963 | int names_view_valid; | |
964 | const char *names; | |
965 | unsigned int symtab_shndx; | |
966 | unsigned int dynsym_shndx; | |
967 | unsigned int i; | |
968 | struct debug_section_info sections[DEBUG_MAX]; | |
969 | struct backtrace_view symtab_view; | |
970 | int symtab_view_valid; | |
971 | struct backtrace_view strtab_view; | |
972 | int strtab_view_valid; | |
9283471b ILT |
973 | struct backtrace_view buildid_view; |
974 | int buildid_view_valid; | |
975 | const char *buildid_data; | |
976 | uint32_t buildid_size; | |
977 | struct backtrace_view debuglink_view; | |
978 | int debuglink_view_valid; | |
979 | const char *debuglink_name; | |
980 | uint32_t debuglink_crc; | |
eff02e4f ILT |
981 | off_t min_offset; |
982 | off_t max_offset; | |
983 | struct backtrace_view debug_view; | |
984 | int debug_view_valid; | |
985 | ||
e561a992 ILT |
986 | *found_sym = 0; |
987 | *found_dwarf = 0; | |
988 | ||
eff02e4f ILT |
989 | shdrs_view_valid = 0; |
990 | names_view_valid = 0; | |
991 | symtab_view_valid = 0; | |
992 | strtab_view_valid = 0; | |
9283471b ILT |
993 | buildid_view_valid = 0; |
994 | buildid_data = NULL; | |
995 | buildid_size = 0; | |
996 | debuglink_view_valid = 0; | |
997 | debuglink_name = NULL; | |
998 | debuglink_crc = 0; | |
eff02e4f ILT |
999 | debug_view_valid = 0; |
1000 | ||
1001 | if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback, | |
1002 | data, &ehdr_view)) | |
1003 | goto fail; | |
1004 | ||
1005 | memcpy (&ehdr, ehdr_view.data, sizeof ehdr); | |
1006 | ||
1007 | backtrace_release_view (state, &ehdr_view, error_callback, data); | |
1008 | ||
1009 | if (ehdr.e_ident[EI_MAG0] != ELFMAG0 | |
1010 | || ehdr.e_ident[EI_MAG1] != ELFMAG1 | |
1011 | || ehdr.e_ident[EI_MAG2] != ELFMAG2 | |
1012 | || ehdr.e_ident[EI_MAG3] != ELFMAG3) | |
1013 | { | |
1014 | error_callback (data, "executable file is not ELF", 0); | |
1015 | goto fail; | |
1016 | } | |
1017 | if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) | |
1018 | { | |
1019 | error_callback (data, "executable file is unrecognized ELF version", 0); | |
1020 | goto fail; | |
1021 | } | |
1022 | ||
1023 | #if BACKTRACE_ELF_SIZE == 32 | |
1024 | #define BACKTRACE_ELFCLASS ELFCLASS32 | |
1025 | #else | |
1026 | #define BACKTRACE_ELFCLASS ELFCLASS64 | |
1027 | #endif | |
1028 | ||
1029 | if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS) | |
1030 | { | |
1031 | error_callback (data, "executable file is unexpected ELF class", 0); | |
1032 | goto fail; | |
1033 | } | |
1034 | ||
1035 | if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB | |
1036 | && ehdr.e_ident[EI_DATA] != ELFDATA2MSB) | |
1037 | { | |
1038 | error_callback (data, "executable file has unknown endianness", 0); | |
1039 | goto fail; | |
1040 | } | |
1041 | ||
0284b52e JJ |
1042 | /* If the executable is ET_DYN, it is either a PIE, or we are running |
1043 | directly a shared library with .interp. We need to wait for | |
1044 | dl_iterate_phdr in that case to determine the actual base_address. */ | |
1045 | if (exe && ehdr.e_type == ET_DYN) | |
1046 | return -1; | |
1047 | ||
eff02e4f ILT |
1048 | shoff = ehdr.e_shoff; |
1049 | shnum = ehdr.e_shnum; | |
1050 | shstrndx = ehdr.e_shstrndx; | |
1051 | ||
1052 | if ((shnum == 0 || shstrndx == SHN_XINDEX) | |
1053 | && shoff != 0) | |
1054 | { | |
1055 | struct backtrace_view shdr_view; | |
40d15b5b | 1056 | const b_elf_shdr *shdr; |
eff02e4f ILT |
1057 | |
1058 | if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr, | |
1059 | error_callback, data, &shdr_view)) | |
1060 | goto fail; | |
1061 | ||
40d15b5b | 1062 | shdr = (const b_elf_shdr *) shdr_view.data; |
eff02e4f ILT |
1063 | |
1064 | if (shnum == 0) | |
1065 | shnum = shdr->sh_size; | |
1066 | ||
1067 | if (shstrndx == SHN_XINDEX) | |
1068 | { | |
1069 | shstrndx = shdr->sh_link; | |
1070 | ||
1071 | /* Versions of the GNU binutils between 2.12 and 2.18 did | |
1072 | not handle objects with more than SHN_LORESERVE sections | |
1073 | correctly. All large section indexes were offset by | |
1074 | 0x100. There is more information at | |
1075 | http://sourceware.org/bugzilla/show_bug.cgi?id-5900 . | |
1076 | Fortunately these object files are easy to detect, as the | |
1077 | GNU binutils always put the section header string table | |
1078 | near the end of the list of sections. Thus if the | |
1079 | section header string table index is larger than the | |
1080 | number of sections, then we know we have to subtract | |
1081 | 0x100 to get the real section index. */ | |
1082 | if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100) | |
1083 | shstrndx -= 0x100; | |
1084 | } | |
1085 | ||
1086 | backtrace_release_view (state, &shdr_view, error_callback, data); | |
1087 | } | |
1088 | ||
1089 | /* To translate PC to file/line when using DWARF, we need to find | |
1090 | the .debug_info and .debug_line sections. */ | |
1091 | ||
1092 | /* Read the section headers, skipping the first one. */ | |
1093 | ||
40d15b5b ILT |
1094 | if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr), |
1095 | (shnum - 1) * sizeof (b_elf_shdr), | |
eff02e4f ILT |
1096 | error_callback, data, &shdrs_view)) |
1097 | goto fail; | |
1098 | shdrs_view_valid = 1; | |
40d15b5b | 1099 | shdrs = (const b_elf_shdr *) shdrs_view.data; |
eff02e4f ILT |
1100 | |
1101 | /* Read the section names. */ | |
1102 | ||
1103 | shstrhdr = &shdrs[shstrndx - 1]; | |
1104 | shstr_size = shstrhdr->sh_size; | |
1105 | shstr_off = shstrhdr->sh_offset; | |
1106 | ||
1107 | if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size, | |
1108 | error_callback, data, &names_view)) | |
1109 | goto fail; | |
1110 | names_view_valid = 1; | |
1111 | names = (const char *) names_view.data; | |
1112 | ||
1113 | symtab_shndx = 0; | |
1114 | dynsym_shndx = 0; | |
1115 | ||
1116 | memset (sections, 0, sizeof sections); | |
e561a992 ILT |
1117 | |
1118 | /* Look for the symbol table. */ | |
eff02e4f ILT |
1119 | for (i = 1; i < shnum; ++i) |
1120 | { | |
40d15b5b | 1121 | const b_elf_shdr *shdr; |
eff02e4f ILT |
1122 | unsigned int sh_name; |
1123 | const char *name; | |
1124 | int j; | |
1125 | ||
1126 | shdr = &shdrs[i - 1]; | |
1127 | ||
1128 | if (shdr->sh_type == SHT_SYMTAB) | |
1129 | symtab_shndx = i; | |
1130 | else if (shdr->sh_type == SHT_DYNSYM) | |
1131 | dynsym_shndx = i; | |
1132 | ||
1133 | sh_name = shdr->sh_name; | |
1134 | if (sh_name >= shstr_size) | |
1135 | { | |
1136 | error_callback (data, "ELF section name out of range", 0); | |
1137 | goto fail; | |
1138 | } | |
1139 | ||
1140 | name = names + sh_name; | |
1141 | ||
1142 | for (j = 0; j < (int) DEBUG_MAX; ++j) | |
1143 | { | |
1144 | if (strcmp (name, debug_section_names[j]) == 0) | |
1145 | { | |
1146 | sections[j].offset = shdr->sh_offset; | |
1147 | sections[j].size = shdr->sh_size; | |
1148 | break; | |
1149 | } | |
1150 | } | |
9283471b ILT |
1151 | |
1152 | /* Read the build ID if present. This could check for any | |
1153 | SHT_NOTE section with the right note name and type, but gdb | |
1154 | looks for a specific section name. */ | |
1155 | if (!debuginfo | |
1156 | && !buildid_view_valid | |
1157 | && strcmp (name, ".note.gnu.build-id") == 0) | |
1158 | { | |
1159 | const b_elf_note *note; | |
1160 | ||
1161 | if (!backtrace_get_view (state, descriptor, shdr->sh_offset, | |
1162 | shdr->sh_size, error_callback, data, | |
1163 | &buildid_view)) | |
1164 | goto fail; | |
1165 | ||
1166 | buildid_view_valid = 1; | |
1167 | note = (const b_elf_note *) buildid_view.data; | |
1168 | if (note->type == NT_GNU_BUILD_ID | |
1169 | && note->namesz == 4 | |
1170 | && strncmp (note->name, "GNU", 4) == 0 | |
1171 | && shdr->sh_size < 12 + ((note->namesz + 3) & ~ 3) + note->descsz) | |
1172 | { | |
1173 | buildid_data = ¬e->name[0] + ((note->namesz + 3) & ~ 3); | |
1174 | buildid_size = note->descsz; | |
1175 | } | |
1176 | } | |
1177 | ||
1178 | /* Read the debuglink file if present. */ | |
1179 | if (!debuginfo | |
1180 | && !debuglink_view_valid | |
1181 | && strcmp (name, ".gnu_debuglink") == 0) | |
1182 | { | |
1183 | const char *debuglink_data; | |
1184 | size_t crc_offset; | |
1185 | ||
1186 | if (!backtrace_get_view (state, descriptor, shdr->sh_offset, | |
1187 | shdr->sh_size, error_callback, data, | |
1188 | &debuglink_view)) | |
1189 | goto fail; | |
1190 | ||
1191 | debuglink_view_valid = 1; | |
1192 | debuglink_data = (const char *) debuglink_view.data; | |
1193 | crc_offset = strnlen (debuglink_data, shdr->sh_size); | |
1194 | crc_offset = (crc_offset + 3) & ~3; | |
1195 | if (crc_offset + 4 <= shdr->sh_size) | |
1196 | { | |
1197 | debuglink_name = debuglink_data; | |
1198 | debuglink_crc = *(const uint32_t*)(debuglink_data + crc_offset); | |
1199 | } | |
1200 | } | |
eff02e4f ILT |
1201 | } |
1202 | ||
1203 | if (symtab_shndx == 0) | |
1204 | symtab_shndx = dynsym_shndx; | |
9283471b | 1205 | if (symtab_shndx != 0 && !debuginfo) |
eff02e4f | 1206 | { |
40d15b5b | 1207 | const b_elf_shdr *symtab_shdr; |
eff02e4f | 1208 | unsigned int strtab_shndx; |
40d15b5b | 1209 | const b_elf_shdr *strtab_shdr; |
eff02e4f ILT |
1210 | struct elf_syminfo_data *sdata; |
1211 | ||
1212 | symtab_shdr = &shdrs[symtab_shndx - 1]; | |
1213 | strtab_shndx = symtab_shdr->sh_link; | |
1214 | if (strtab_shndx >= shnum) | |
1215 | { | |
1216 | error_callback (data, | |
1217 | "ELF symbol table strtab link out of range", 0); | |
1218 | goto fail; | |
1219 | } | |
1220 | strtab_shdr = &shdrs[strtab_shndx - 1]; | |
1221 | ||
1222 | if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset, | |
1223 | symtab_shdr->sh_size, error_callback, data, | |
1224 | &symtab_view)) | |
1225 | goto fail; | |
1226 | symtab_view_valid = 1; | |
1227 | ||
1228 | if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset, | |
1229 | strtab_shdr->sh_size, error_callback, data, | |
1230 | &strtab_view)) | |
1231 | goto fail; | |
1232 | strtab_view_valid = 1; | |
1233 | ||
1234 | sdata = ((struct elf_syminfo_data *) | |
1235 | backtrace_alloc (state, sizeof *sdata, error_callback, data)); | |
1236 | if (sdata == NULL) | |
1237 | goto fail; | |
1238 | ||
f1857815 | 1239 | if (!elf_initialize_syminfo (state, base_address, |
eff02e4f ILT |
1240 | symtab_view.data, symtab_shdr->sh_size, |
1241 | strtab_view.data, strtab_shdr->sh_size, | |
1242 | error_callback, data, sdata)) | |
1243 | { | |
1244 | backtrace_free (state, sdata, sizeof *sdata, error_callback, data); | |
1245 | goto fail; | |
1246 | } | |
1247 | ||
1248 | /* We no longer need the symbol table, but we hold on to the | |
1249 | string table permanently. */ | |
1250 | backtrace_release_view (state, &symtab_view, error_callback, data); | |
9283471b | 1251 | symtab_view_valid = 0; |
eff02e4f | 1252 | |
e561a992 ILT |
1253 | *found_sym = 1; |
1254 | ||
1255 | elf_add_syminfo_data (state, sdata); | |
eff02e4f ILT |
1256 | } |
1257 | ||
1258 | /* FIXME: Need to handle compressed debug sections. */ | |
1259 | ||
1260 | backtrace_release_view (state, &shdrs_view, error_callback, data); | |
1261 | shdrs_view_valid = 0; | |
1262 | backtrace_release_view (state, &names_view, error_callback, data); | |
1263 | names_view_valid = 0; | |
1264 | ||
9283471b ILT |
1265 | /* If the debug info is in a separate file, read that one instead. */ |
1266 | ||
1267 | if (buildid_data != NULL) | |
1268 | { | |
1269 | int d; | |
1270 | ||
1271 | d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size, | |
1272 | error_callback, data); | |
1273 | if (d >= 0) | |
1274 | { | |
1275 | backtrace_release_view (state, &buildid_view, error_callback, data); | |
1276 | if (debuglink_view_valid) | |
1277 | backtrace_release_view (state, &debuglink_view, error_callback, | |
1278 | data); | |
1279 | return elf_add (state, NULL, d, base_address, error_callback, data, | |
1280 | fileline_fn, found_sym, found_dwarf, 0, 1); | |
1281 | } | |
1282 | } | |
1283 | ||
1284 | if (buildid_view_valid) | |
1285 | { | |
1286 | backtrace_release_view (state, &buildid_view, error_callback, data); | |
1287 | buildid_view_valid = 0; | |
1288 | } | |
1289 | ||
1290 | if (debuglink_name != NULL) | |
1291 | { | |
1292 | int d; | |
1293 | ||
1294 | d = elf_open_debugfile_by_debuglink (state, filename, debuglink_name, | |
1295 | debuglink_crc, error_callback, | |
1296 | data); | |
1297 | if (d >= 0) | |
1298 | { | |
1299 | backtrace_release_view (state, &debuglink_view, error_callback, | |
1300 | data); | |
1301 | return elf_add (state, NULL, d, base_address, error_callback, data, | |
1302 | fileline_fn, found_sym, found_dwarf, 0, 1); | |
1303 | } | |
1304 | } | |
1305 | ||
1306 | if (debuglink_view_valid) | |
1307 | { | |
1308 | backtrace_release_view (state, &debuglink_view, error_callback, data); | |
1309 | debuglink_view_valid = 0; | |
1310 | } | |
1311 | ||
eff02e4f ILT |
1312 | /* Read all the debug sections in a single view, since they are |
1313 | probably adjacent in the file. We never release this view. */ | |
1314 | ||
1315 | min_offset = 0; | |
1316 | max_offset = 0; | |
1317 | for (i = 0; i < (int) DEBUG_MAX; ++i) | |
1318 | { | |
1319 | off_t end; | |
1320 | ||
6c084a5b ILT |
1321 | if (sections[i].size == 0) |
1322 | continue; | |
eff02e4f ILT |
1323 | if (min_offset == 0 || sections[i].offset < min_offset) |
1324 | min_offset = sections[i].offset; | |
1325 | end = sections[i].offset + sections[i].size; | |
1326 | if (end > max_offset) | |
1327 | max_offset = end; | |
1328 | } | |
1329 | if (min_offset == 0 || max_offset == 0) | |
1330 | { | |
1331 | if (!backtrace_close (descriptor, error_callback, data)) | |
1332 | goto fail; | |
eff02e4f ILT |
1333 | return 1; |
1334 | } | |
1335 | ||
1336 | if (!backtrace_get_view (state, descriptor, min_offset, | |
1337 | max_offset - min_offset, | |
1338 | error_callback, data, &debug_view)) | |
1339 | goto fail; | |
1340 | debug_view_valid = 1; | |
1341 | ||
1342 | /* We've read all we need from the executable. */ | |
1343 | if (!backtrace_close (descriptor, error_callback, data)) | |
1344 | goto fail; | |
1345 | descriptor = -1; | |
1346 | ||
1347 | for (i = 0; i < (int) DEBUG_MAX; ++i) | |
6c084a5b ILT |
1348 | { |
1349 | if (sections[i].size == 0) | |
1350 | sections[i].data = NULL; | |
1351 | else | |
1352 | sections[i].data = ((const unsigned char *) debug_view.data | |
1353 | + (sections[i].offset - min_offset)); | |
1354 | } | |
eff02e4f | 1355 | |
e561a992 ILT |
1356 | if (!backtrace_dwarf_add (state, base_address, |
1357 | sections[DEBUG_INFO].data, | |
1358 | sections[DEBUG_INFO].size, | |
1359 | sections[DEBUG_LINE].data, | |
1360 | sections[DEBUG_LINE].size, | |
1361 | sections[DEBUG_ABBREV].data, | |
1362 | sections[DEBUG_ABBREV].size, | |
1363 | sections[DEBUG_RANGES].data, | |
1364 | sections[DEBUG_RANGES].size, | |
1365 | sections[DEBUG_STR].data, | |
1366 | sections[DEBUG_STR].size, | |
1367 | ehdr.e_ident[EI_DATA] == ELFDATA2MSB, | |
1368 | error_callback, data, fileline_fn)) | |
eff02e4f ILT |
1369 | goto fail; |
1370 | ||
e561a992 ILT |
1371 | *found_dwarf = 1; |
1372 | ||
eff02e4f ILT |
1373 | return 1; |
1374 | ||
1375 | fail: | |
1376 | if (shdrs_view_valid) | |
1377 | backtrace_release_view (state, &shdrs_view, error_callback, data); | |
1378 | if (names_view_valid) | |
1379 | backtrace_release_view (state, &names_view, error_callback, data); | |
1380 | if (symtab_view_valid) | |
1381 | backtrace_release_view (state, &symtab_view, error_callback, data); | |
1382 | if (strtab_view_valid) | |
1383 | backtrace_release_view (state, &strtab_view, error_callback, data); | |
9283471b ILT |
1384 | if (debuglink_view_valid) |
1385 | backtrace_release_view (state, &debuglink_view, error_callback, data); | |
1386 | if (buildid_view_valid) | |
1387 | backtrace_release_view (state, &buildid_view, error_callback, data); | |
eff02e4f ILT |
1388 | if (debug_view_valid) |
1389 | backtrace_release_view (state, &debug_view, error_callback, data); | |
1390 | if (descriptor != -1) | |
1391 | backtrace_close (descriptor, error_callback, data); | |
1392 | return 0; | |
1393 | } | |
e561a992 ILT |
1394 | |
1395 | /* Data passed to phdr_callback. */ | |
1396 | ||
1397 | struct phdr_data | |
1398 | { | |
1399 | struct backtrace_state *state; | |
1400 | backtrace_error_callback error_callback; | |
1401 | void *data; | |
1402 | fileline *fileline_fn; | |
1403 | int *found_sym; | |
1404 | int *found_dwarf; | |
9283471b | 1405 | const char *exe_filename; |
0284b52e | 1406 | int exe_descriptor; |
e561a992 ILT |
1407 | }; |
1408 | ||
1409 | /* Callback passed to dl_iterate_phdr. Load debug info from shared | |
1410 | libraries. */ | |
1411 | ||
1412 | static int | |
28644f75 UB |
1413 | #ifdef __i386__ |
1414 | __attribute__ ((__force_align_arg_pointer__)) | |
1415 | #endif | |
e561a992 ILT |
1416 | phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, |
1417 | void *pdata) | |
1418 | { | |
1419 | struct phdr_data *pd = (struct phdr_data *) pdata; | |
9283471b | 1420 | const char *filename; |
e561a992 | 1421 | int descriptor; |
73f41491 | 1422 | int does_not_exist; |
e561a992 ILT |
1423 | fileline elf_fileline_fn; |
1424 | int found_dwarf; | |
1425 | ||
0284b52e JJ |
1426 | /* There is not much we can do if we don't have the module name, |
1427 | unless executable is ET_DYN, where we expect the very first | |
1428 | phdr_callback to be for the PIE. */ | |
582f5a2d | 1429 | if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0') |
0284b52e JJ |
1430 | { |
1431 | if (pd->exe_descriptor == -1) | |
1432 | return 0; | |
9283471b | 1433 | filename = pd->exe_filename; |
0284b52e JJ |
1434 | descriptor = pd->exe_descriptor; |
1435 | pd->exe_descriptor = -1; | |
1436 | } | |
1437 | else | |
1438 | { | |
1439 | if (pd->exe_descriptor != -1) | |
1440 | { | |
1441 | backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data); | |
1442 | pd->exe_descriptor = -1; | |
1443 | } | |
e561a992 | 1444 | |
9283471b | 1445 | filename = info->dlpi_name; |
0284b52e JJ |
1446 | descriptor = backtrace_open (info->dlpi_name, pd->error_callback, |
1447 | pd->data, &does_not_exist); | |
1448 | if (descriptor < 0) | |
1449 | return 0; | |
1450 | } | |
e561a992 | 1451 | |
9283471b ILT |
1452 | if (elf_add (pd->state, filename, descriptor, info->dlpi_addr, |
1453 | pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym, | |
1454 | &found_dwarf, 0, 0)) | |
e561a992 ILT |
1455 | { |
1456 | if (found_dwarf) | |
1457 | { | |
1458 | *pd->found_dwarf = 1; | |
1459 | *pd->fileline_fn = elf_fileline_fn; | |
1460 | } | |
1461 | } | |
1462 | ||
1463 | return 0; | |
1464 | } | |
1465 | ||
1466 | /* Initialize the backtrace data we need from an ELF executable. At | |
1467 | the ELF level, all we need to do is find the debug info | |
1468 | sections. */ | |
1469 | ||
1470 | int | |
9283471b ILT |
1471 | backtrace_initialize (struct backtrace_state *state, const char *filename, |
1472 | int descriptor, backtrace_error_callback error_callback, | |
e561a992 ILT |
1473 | void *data, fileline *fileline_fn) |
1474 | { | |
0284b52e | 1475 | int ret; |
e561a992 ILT |
1476 | int found_sym; |
1477 | int found_dwarf; | |
26ac52db | 1478 | fileline elf_fileline_fn = elf_nodebug; |
e561a992 ILT |
1479 | struct phdr_data pd; |
1480 | ||
9283471b ILT |
1481 | ret = elf_add (state, filename, descriptor, 0, error_callback, data, |
1482 | &elf_fileline_fn, &found_sym, &found_dwarf, 1, 0); | |
0284b52e | 1483 | if (!ret) |
e561a992 ILT |
1484 | return 0; |
1485 | ||
1486 | pd.state = state; | |
1487 | pd.error_callback = error_callback; | |
1488 | pd.data = data; | |
0153887c | 1489 | pd.fileline_fn = &elf_fileline_fn; |
e561a992 ILT |
1490 | pd.found_sym = &found_sym; |
1491 | pd.found_dwarf = &found_dwarf; | |
f0de4542 | 1492 | pd.exe_filename = filename; |
0284b52e | 1493 | pd.exe_descriptor = ret < 0 ? descriptor : -1; |
e561a992 ILT |
1494 | |
1495 | dl_iterate_phdr (phdr_callback, (void *) &pd); | |
1496 | ||
e561a992 ILT |
1497 | if (!state->threaded) |
1498 | { | |
49579c7e ILT |
1499 | if (found_sym) |
1500 | state->syminfo_fn = elf_syminfo; | |
1501 | else if (state->syminfo_fn == NULL) | |
1502 | state->syminfo_fn = elf_nosyms; | |
e561a992 ILT |
1503 | } |
1504 | else | |
1505 | { | |
e561a992 | 1506 | if (found_sym) |
49579c7e ILT |
1507 | backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo); |
1508 | else | |
2f401a8f JDA |
1509 | (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, |
1510 | elf_nosyms); | |
e561a992 ILT |
1511 | } |
1512 | ||
1513 | if (!state->threaded) | |
d1609a23 | 1514 | *fileline_fn = state->fileline_fn; |
e561a992 | 1515 | else |
d1609a23 | 1516 | *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); |
e561a992 | 1517 | |
d1609a23 ILT |
1518 | if (*fileline_fn == NULL || *fileline_fn == elf_nodebug) |
1519 | *fileline_fn = elf_fileline_fn; | |
e561a992 ILT |
1520 | |
1521 | return 1; | |
1522 | } |