1 | // elf.c: |
2 | #include <errno.h> |
3 | #include <stdlib.h> |
4 | #include <string.h> |
5 | #include <sys/stat.h> |
6 | #include <sys/types.h> |
7 | #include <unistd.h> |
8 | |
9 | #ifdef HAVE_DL_ITERATE_PHDR |
10 | #include <link.h> |
11 | #endif |
12 | |
13 | #ifndef S_ISLNK |
14 | #ifndef S_IFLNK |
15 | #define S_IFLNK 0120000 |
16 | #endif |
17 | #ifndef S_IFMT |
18 | #define S_IFMT 0170000 |
19 | #endif |
20 | #define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) |
21 | #endif |
22 | |
23 | #ifndef __GNUC__ |
24 | #define __builtin_prefetch(p, r, l) |
25 | #define unlikely(x) (x) |
26 | #else |
27 | #define unlikely(x) __builtin_expect(!!(x), 0) |
28 | #endif |
29 | |
30 | #if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN |
31 | |
32 | static size_t xstrnlen(const char *s, size_t maxlen) { |
33 | size_t i; |
34 | |
35 | for (i = 0; i < maxlen; ++i) |
36 | if (s[i] == '\0') break; |
37 | return i; |
38 | } |
39 | |
40 | #define strnlen xstrnlen |
41 | |
42 | #endif |
43 | |
44 | #ifndef HAVE_LSTAT |
45 | |
46 | static int xlstat(const char *path ATTRIBUTE_UNUSED, |
47 | struct stat *st ATTRIBUTE_UNUSED) { |
48 | return -1; |
49 | } |
50 | |
51 | #define lstat xlstat |
52 | |
53 | #endif |
54 | |
55 | #ifndef HAVE_READLINK |
56 | |
57 | static ssize_t xreadlink(const char *path ATTRIBUTE_UNUSED, |
58 | char *buf ATTRIBUTE_UNUSED, |
59 | size_t bufsz ATTRIBUTE_UNUSED) { |
60 | return -1; |
61 | } |
62 | |
63 | #define readlink xreadlink |
64 | |
65 | #endif |
66 | |
67 | #ifndef HAVE_DL_ITERATE_PHDR |
68 | |
69 | #define dl_phdr_info x_dl_phdr_info |
70 | #define dl_iterate_phdr x_dl_iterate_phdr |
71 | |
72 | struct dl_phdr_info { |
73 | uintptr_t dlpi_addr; |
74 | const char *dlpi_name; |
75 | }; |
76 | |
77 | static int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, |
78 | void *) ATTRIBUTE_UNUSED, |
79 | void *data ATTRIBUTE_UNUSED) { |
80 | return 0; |
81 | } |
82 | |
83 | #endif |
84 | |
85 | #if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64 |
86 | #error "Unknown BACKTRACE_ELF_SIZE" |
87 | #endif |
88 | |
89 | #undef EI_NIDENT |
90 | #undef EI_MAG0 |
91 | #undef EI_MAG1 |
92 | #undef EI_MAG2 |
93 | #undef EI_MAG3 |
94 | #undef EI_CLASS |
95 | #undef EI_DATA |
96 | #undef EI_VERSION |
97 | #undef ELF_MAG0 |
98 | #undef ELF_MAG1 |
99 | #undef ELF_MAG2 |
100 | #undef ELF_MAG3 |
101 | #undef ELFCLASS32 |
102 | #undef ELFCLASS64 |
103 | #undef ELFDATA2LSB |
104 | #undef ELFDATA2MSB |
105 | #undef EV_CURRENT |
106 | #undef ET_DYN |
107 | #undef EM_PPC64 |
108 | #undef EF_PPC64_ABI |
109 | #undef SHN_LORESERVE |
110 | #undef SHN_XINDEX |
111 | #undef SHN_UNDEF |
112 | #undef SHT_PROGBITS |
113 | #undef SHT_SYMTAB |
114 | #undef SHT_STRTAB |
115 | #undef SHT_DYNSYM |
116 | #undef SHF_COMPRESSED |
117 | #undef STT_OBJECT |
118 | #undef STT_FUNC |
119 | #undef NT_GNU_BUILD_ID |
120 | #undef ELFCOMPRESS_ZLIB |
121 | |
122 | typedef uint16_t b_elf_half; |
123 | typedef uint32_t b_elf_word; |
124 | typedef int32_t b_elf_sword; |
125 | #if BACKTRACE_ELF_SIZE == 32 |
126 | |
127 | typedef uint32_t b_elf_addr; |
128 | typedef uint32_t b_elf_off; |
129 | typedef uint32_t b_elf_wxword; |
130 | #else |
131 | |
132 | typedef uint64_t b_elf_addr; |
133 | typedef uint64_t b_elf_off; |
134 | typedef uint64_t b_elf_xword; |
135 | typedef int64_t b_elf_sxword; |
136 | typedef uint64_t b_elf_wxword; |
137 | #endif |
138 | |
139 | #define EI_NIDENT 16 |
140 | |
141 | typedef struct { |
142 | unsigned char e_ident[EI_NIDENT]; |
143 | b_elf_half e_type; |
144 | b_elf_half e_machine; |
145 | b_elf_word e_version; |
146 | b_elf_addr e_entry; |
147 | b_elf_off e_phoff; |
148 | b_elf_off e_shoff; |
149 | b_elf_word e_flags; |
150 | b_elf_half e_ehsize; |
151 | b_elf_half e_phentsize; |
152 | b_elf_half e_phnum; |
153 | b_elf_half e_shentsize; |
154 | b_elf_half e_shnum; |
155 | b_elf_half e_shstrndx; |
156 | } b_elf_ehdr; |
157 | #define EI_MAG0 0 |
158 | #define EI_MAG1 1 |
159 | #define EI_MAG2 2 |
160 | #define EI_MAG3 3 |
161 | #define EI_CLASS 4 |
162 | #define EI_DATA 5 |
163 | #define EI_VERSION 6 |
164 | |
165 | #define ELFMAG0 0x7f |
166 | #define ELFMAG1 'E' |
167 | #define ELFMAG2 'L' |
168 | #define ELFMAG3 'F' |
169 | |
170 | #define ELFCLASS32 1 |
171 | #define ELFCLASS64 2 |
172 | |
173 | #define ELFDATA2LSB 1 |
174 | #define ELFDATA2MSB 2 |
175 | |
176 | #define EV_CURRENT 1 |
177 | |
178 | #define ET_DYN 3 |
179 | |
180 | #define EM_PPC64 21 |
181 | #define EF_PPC64_ABI 3 |
182 | |
183 | typedef struct { |
184 | b_elf_word sh_name; |
185 | b_elf_word sh_type; |
186 | b_elf_wxword sh_flags; |
187 | b_elf_addr sh_addr; |
188 | b_elf_off sh_offset; |
189 | b_elf_wxword sh_size; |
190 | b_elf_word sh_link; |
191 | b_elf_word sh_info; |
192 | b_elf_wxword sh_addralign; |
193 | b_elf_wxword sh_entsize; |
194 | } b_elf_shdr; |
195 | #define SHN_UNDEF 0x0000 |
196 | #define SHN_LORESERVE 0xFF00 |
197 | #define SHN_XINDEX 0xFFFF |
198 | #define SHT_PROGBITS 1 |
199 | #define SHT_SYMTAB 2 |
200 | #define SHT_STRTAB 3 |
201 | #define SHT_DYNSYM 11 |
202 | |
203 | #define SHF_COMPRESSED 0x800 |
204 | |
205 | #if BACKTRACE_ELF_SIZE == 32 |
206 | |
207 | typedef struct { |
208 | b_elf_word st_name; |
209 | b_elf_addr st_value; |
210 | b_elf_word st_size; |
211 | unsigned char st_info; |
212 | unsigned char st_other; |
213 | b_elf_half st_shndx; |
214 | } b_elf_sym; |
215 | #else |
216 | typedef struct { |
217 | b_elf_word st_name; |
218 | unsigned char st_info; |
219 | unsigned char st_other; |
220 | b_elf_half st_shndx; |
221 | b_elf_addr st_value; |
222 | b_elf_xword st_size; |
223 | } b_elf_sym; |
224 | #endif |
225 | #define STT_OBJECT 1 |
226 | #define STT_FUNC 2 |
227 | |
228 | typedef struct { |
229 | uint32_t namesz; |
230 | uint32_t descsz; |
231 | uint32_t type; |
232 | char name[1]; |
233 | } b_elf_note; |
234 | |
235 | #define NT_GNU_BUILD_ID 3 |
236 | |
237 | #if BACKTRACE_ELF_SIZE == 32 |
238 | |
239 | typedef struct { |
240 | b_elf_word ch_type; |
241 | b_elf_word ch_size; |
242 | b_elf_word ch_addralign; |
243 | } b_elf_chdr; |
244 | #else |
245 | typedef struct { |
246 | b_elf_word ch_type; |
247 | b_elf_word ch_reserved; |
248 | b_elf_xword ch_size; |
249 | b_elf_xword ch_addralign; |
250 | } b_elf_chdr; |
251 | #endif |
252 | #define ELFCOMPRESS_ZLIB 1 |
253 | |
254 | static const char *const dwarf_section_names[DEBUG_MAX] = { |
255 | ".debug_info", ".debug_line", ".debug_abbrev", |
256 | ".debug_ranges", ".debug_str", ".debug_addr", |
257 | ".debug_str_offsets", ".debug_line_str", ".debug_rnglists"}; |
258 | |
259 | struct debug_section_info { |
260 | off_t offset; |
261 | |
262 | size_t size; |
263 | |
264 | const unsigned char *data; |
265 | |
266 | int compressed; |
267 | }; |
268 | |
269 | struct elf_symbol { |
270 | const char *name; |
271 | |
272 | uintptr_t address; |
273 | |
274 | size_t size; |
275 | }; |
276 | |
277 | struct elf_syminfo_data { |
278 | struct elf_syminfo_data *next; |
279 | |
280 | struct elf_symbol *symbols; |
281 | |
282 | size_t count; |
283 | }; |
284 | |
285 | struct elf_view { |
286 | struct backtrace_view view; |
287 | int release; |
288 | }; |
289 | |
290 | struct elf_ppc64_opd_data { |
291 | b_elf_addr addr; |
292 | |
293 | const char *data; |
294 | |
295 | size_t size; |
296 | |
297 | struct elf_view view; |
298 | }; |
299 | |
300 | static int elf_get_view(struct backtrace_state *state, int descriptor, |
301 | const unsigned char *memory, size_t memory_size, |
302 | off_t offset, uint64_t size, |
303 | backtrace_error_callback error_callback, void *data, |
304 | struct elf_view *view) { |
305 | if (memory == NULL) { |
306 | view->release = 1; |
307 | return backtrace_get_view(state, descriptor, offset, size, error_callback, |
308 | data, &view->view); |
309 | } else { |
310 | if ((uint64_t)offset + size > (uint64_t)memory_size) { |
311 | error_callback(data, "out of range for in-memory file", 0); |
312 | return 0; |
313 | } |
314 | view->view.data = (const void *)(memory + offset); |
315 | view->view.base = NULL; |
316 | view->view.len = size; |
317 | view->release = 0; |
318 | return 1; |
319 | } |
320 | } |
321 | |
322 | static void elf_release_view(struct backtrace_state *state, |
323 | struct elf_view *view, |
324 | backtrace_error_callback error_callback, |
325 | void *data) { |
326 | if (view->release) |
327 | backtrace_release_view(state, &view->view, error_callback, data); |
328 | } |
329 | |
330 | static uint32_t elf_crc32(uint32_t crc, const unsigned char *buf, size_t len) { |
331 | static const uint32_t crc32_table[256] = { |
332 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, |
333 | 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, |
334 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, |
335 | 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, |
336 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, |
337 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, |
338 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, |
339 | 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, |
340 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, |
341 | 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, |
342 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, |
343 | 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, |
344 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, |
345 | 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, |
346 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, |
347 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, |
348 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, |
349 | 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, |
350 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, |
351 | 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, |
352 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, |
353 | 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, |
354 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, |
355 | 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, |
356 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, |
357 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, |
358 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, |
359 | 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, |
360 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, |
361 | 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, |
362 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, |
363 | 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, |
364 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, |
365 | 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, |
366 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, |
367 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, |
368 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, |
369 | 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, |
370 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, |
371 | 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, |
372 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, |
373 | 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, |
374 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; |
375 | const unsigned char *end; |
376 | |
377 | crc = ~crc; |
378 | for (end = buf + len; buf < end; ++buf) |
379 | crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); |
380 | return ~crc; |
381 | } |
382 | |
383 | static uint32_t elf_crc32_file(struct backtrace_state *state, int descriptor, |
384 | backtrace_error_callback error_callback, |
385 | void *data) { |
386 | struct stat st; |
387 | struct backtrace_view file_view; |
388 | uint32_t ret; |
389 | |
390 | if (fstat(descriptor, &st) < 0) { |
391 | error_callback(data, "fstat", errno); |
392 | return 0; |
393 | } |
394 | |
395 | if (!backtrace_get_view(state, descriptor, 0, st.st_size, error_callback, |
396 | data, &file_view)) |
397 | return 0; |
398 | |
399 | ret = elf_crc32(0, (const unsigned char *)file_view.data, st.st_size); |
400 | |
401 | backtrace_release_view(state, &file_view, error_callback, data); |
402 | |
403 | return ret; |
404 | } |
405 | |
406 | static void elf_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED, |
407 | uintptr_t addr ATTRIBUTE_UNUSED, |
408 | backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, |
409 | backtrace_error_callback error_callback, void *data) { |
410 | error_callback(data, "no symbol table in ELF executable", -1); |
411 | } |
412 | |
413 | static int elf_nodebug(struct backtrace_state *state, uintptr_t pc, |
414 | backtrace_full_callback callback, |
415 | backtrace_error_callback error_callback, void *data) { |
416 | if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms) { |
417 | struct backtrace_call_full bdata; |
418 | |
419 | bdata.full_callback = callback; |
420 | bdata.full_error_callback = error_callback; |
421 | bdata.full_data = data; |
422 | bdata.ret = 0; |
423 | state->syminfo_fn(state, pc, backtrace_syminfo_to_full_callback, |
424 | backtrace_syminfo_to_full_error_callback, &bdata); |
425 | return bdata.ret; |
426 | } |
427 | |
428 | error_callback(data, "no debug info in ELF executable", -1); |
429 | return 0; |
430 | } |
431 | |
432 | static int elf_symbol_compare(const void *v1, const void *v2) { |
433 | const struct elf_symbol *e1 = (const struct elf_symbol *)v1; |
434 | const struct elf_symbol *e2 = (const struct elf_symbol *)v2; |
435 | |
436 | if (e1->address < e2->address) |
437 | return -1; |
438 | else if (e1->address > e2->address) |
439 | return 1; |
440 | else |
441 | return 0; |
442 | } |
443 | |
444 | static int elf_symbol_search(const void *vkey, const void *ventry) { |
445 | const uintptr_t *key = (const uintptr_t *)vkey; |
446 | const struct elf_symbol *entry = (const struct elf_symbol *)ventry; |
447 | uintptr_t addr; |
448 | |
449 | addr = *key; |
450 | if (addr < entry->address) |
451 | return -1; |
452 | else if (addr >= entry->address + entry->size) |
453 | return 1; |
454 | else |
455 | return 0; |
456 | } |
457 | |
458 | static int elf_initialize_syminfo( |
459 | struct backtrace_state *state, uintptr_t base_address, |
460 | const unsigned char *symtab_data, size_t symtab_size, |
461 | const unsigned char *strtab, size_t strtab_size, |
462 | backtrace_error_callback error_callback, void *data, |
463 | struct elf_syminfo_data *sdata, struct elf_ppc64_opd_data *opd) { |
464 | size_t sym_count; |
465 | const b_elf_sym *sym; |
466 | size_t elf_symbol_count; |
467 | size_t elf_symbol_size; |
468 | struct elf_symbol *elf_symbols; |
469 | size_t i; |
470 | unsigned int j; |
471 | |
472 | sym_count = symtab_size / sizeof(b_elf_sym); |
473 | |
474 | sym = (const b_elf_sym *)symtab_data; |
475 | elf_symbol_count = 0; |
476 | for (i = 0; i < sym_count; ++i, ++sym) { |
477 | int info; |
478 | |
479 | info = sym->st_info & 0xf; |
480 | if ((info == STT_FUNC || info == STT_OBJECT) && sym->st_shndx != SHN_UNDEF) |
481 | ++elf_symbol_count; |
482 | } |
483 | |
484 | elf_symbol_size = elf_symbol_count * sizeof(struct elf_symbol); |
485 | elf_symbols = ((struct elf_symbol *)backtrace_alloc(state, elf_symbol_size, |
486 | error_callback, data)); |
487 | if (elf_symbols == NULL) return 0; |
488 | |
489 | sym = (const b_elf_sym *)symtab_data; |
490 | j = 0; |
491 | for (i = 0; i < sym_count; ++i, ++sym) { |
492 | int info; |
493 | |
494 | info = sym->st_info & 0xf; |
495 | if (info != STT_FUNC && info != STT_OBJECT) continue; |
496 | if (sym->st_shndx == SHN_UNDEF) continue; |
497 | if (sym->st_name >= strtab_size) { |
498 | error_callback(data, "symbol string index out of range", 0); |
499 | backtrace_free(state, elf_symbols, elf_symbol_size, error_callback, data); |
500 | return 0; |
501 | } |
502 | elf_symbols[j].name = (const char *)strtab + sym->st_name; |
503 | |
504 | if (opd && sym->st_value >= opd->addr && |
505 | sym->st_value < opd->addr + opd->size) |
506 | elf_symbols[j].address = |
507 | *(const b_elf_addr *)(opd->data + (sym->st_value - opd->addr)); |
508 | else |
509 | elf_symbols[j].address = sym->st_value; |
510 | elf_symbols[j].address += base_address; |
511 | elf_symbols[j].size = sym->st_size; |
512 | ++j; |
513 | } |
514 | |
515 | backtrace_qsort(elf_symbols, elf_symbol_count, sizeof(struct elf_symbol), |
516 | elf_symbol_compare); |
517 | |
518 | sdata->next = NULL; |
519 | sdata->symbols = elf_symbols; |
520 | sdata->count = elf_symbol_count; |
521 | |
522 | return 1; |
523 | } |
524 | |
525 | static void elf_add_syminfo_data(struct backtrace_state *state, |
526 | struct elf_syminfo_data *edata) { |
527 | if (!state->threaded) { |
528 | struct elf_syminfo_data **pp; |
529 | |
530 | for (pp = (struct elf_syminfo_data **)(void *)&state->syminfo_data; |
531 | *pp != NULL; pp = &(*pp)->next) |
532 | ; |
533 | *pp = edata; |
534 | } else { |
535 | while (1) { |
536 | struct elf_syminfo_data **pp; |
537 | |
538 | pp = (struct elf_syminfo_data **)(void *)&state->syminfo_data; |
539 | |
540 | while (1) { |
541 | struct elf_syminfo_data *p; |
542 | |
543 | p = backtrace_atomic_load_pointer(pp); |
544 | |
545 | if (p == NULL) break; |
546 | |
547 | pp = &p->next; |
548 | } |
549 | |
550 | if (__sync_bool_compare_and_swap(pp, NULL, edata)) break; |
551 | } |
552 | } |
553 | } |
554 | |
555 | static void elf_syminfo( |
556 | struct backtrace_state *state, uintptr_t addr, |
557 | backtrace_syminfo_callback callback, |
558 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data) { |
559 | struct elf_syminfo_data *edata; |
560 | struct elf_symbol *sym = NULL; |
561 | |
562 | if (!state->threaded) { |
563 | for (edata = (struct elf_syminfo_data *)state->syminfo_data; edata != NULL; |
564 | edata = edata->next) { |
565 | sym = ((struct elf_symbol *)bsearch(&addr, edata->symbols, edata->count, |
566 | sizeof(struct elf_symbol), |
567 | elf_symbol_search)); |
568 | if (sym != NULL) break; |
569 | } |
570 | } else { |
571 | struct elf_syminfo_data **pp; |
572 | |
573 | pp = (struct elf_syminfo_data **)(void *)&state->syminfo_data; |
574 | while (1) { |
575 | edata = backtrace_atomic_load_pointer(pp); |
576 | if (edata == NULL) break; |
577 | |
578 | sym = ((struct elf_symbol *)bsearch(&addr, edata->symbols, edata->count, |
579 | sizeof(struct elf_symbol), |
580 | elf_symbol_search)); |
581 | if (sym != NULL) break; |
582 | |
583 | pp = &edata->next; |
584 | } |
585 | } |
586 | |
587 | if (sym == NULL) |
588 | callback(data, addr, NULL, 0, 0); |
589 | else |
590 | callback(data, addr, sym->name, sym->address, sym->size); |
591 | } |
592 | |
593 | static int elf_is_symlink(const char *filename) { |
594 | struct stat st; |
595 | |
596 | if (lstat(filename, &st) < 0) return 0; |
597 | return S_ISLNK(st.st_mode); |
598 | } |
599 | |
600 | static char *elf_readlink(struct backtrace_state *state, const char *filename, |
601 | backtrace_error_callback error_callback, void *data, |
602 | size_t *plen) { |
603 | size_t len; |
604 | char *buf; |
605 | |
606 | len = 128; |
607 | while (1) { |
608 | ssize_t rl; |
609 | |
610 | buf = backtrace_alloc(state, len, error_callback, data); |
611 | if (buf == NULL) return NULL; |
612 | rl = readlink(filename, buf, len); |
613 | if (rl < 0) { |
614 | backtrace_free(state, buf, len, error_callback, data); |
615 | return NULL; |
616 | } |
617 | if ((size_t)rl < len - 1) { |
618 | buf[rl] = '\0'; |
619 | *plen = len; |
620 | return buf; |
621 | } |
622 | backtrace_free(state, buf, len, error_callback, data); |
623 | len *= 2; |
624 | } |
625 | } |
626 | |
627 | #define SYSTEM_BUILD_ID_DIR "/usr/lib/debug/.build-id/" |
628 | |
629 | static int elf_open_debugfile_by_buildid( |
630 | struct backtrace_state *state, const char *buildid_data, |
631 | size_t buildid_size, backtrace_error_callback error_callback, void *data) { |
632 | const char *const prefix = SYSTEM_BUILD_ID_DIR; |
633 | const size_t prefix_len = strlen(prefix); |
634 | const char *const suffix = ".debug"; |
635 | const size_t suffix_len = strlen(suffix); |
636 | size_t len; |
637 | char *bd_filename; |
638 | char *t; |
639 | size_t i; |
640 | int ret; |
641 | int does_not_exist; |
642 | |
643 | len = prefix_len + buildid_size * 2 + suffix_len + 2; |
644 | bd_filename = backtrace_alloc(state, len, error_callback, data); |
645 | if (bd_filename == NULL) return -1; |
646 | |
647 | t = bd_filename; |
648 | memcpy(t, prefix, prefix_len); |
649 | t += prefix_len; |
650 | for (i = 0; i < buildid_size; i++) { |
651 | unsigned char b; |
652 | unsigned char nib; |
653 | |
654 | b = (unsigned char)buildid_data[i]; |
655 | nib = (b & 0xf0) >> 4; |
656 | *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10; |
657 | nib = b & 0x0f; |
658 | *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10; |
659 | if (i == 0) *t++ = '/'; |
660 | } |
661 | memcpy(t, suffix, suffix_len); |
662 | t[suffix_len] = '\0'; |
663 | |
664 | ret = backtrace_open(bd_filename, error_callback, data, &does_not_exist); |
665 | |
666 | backtrace_free(state, bd_filename, len, error_callback, data); |
667 | |
668 | return ret; |
669 | } |
670 | |
671 | static int elf_try_debugfile(struct backtrace_state *state, const char *prefix, |
672 | size_t prefix_len, const char *prefix2, |
673 | size_t prefix2_len, const char *debuglink_name, |
674 | backtrace_error_callback error_callback, |
675 | void *data) { |
676 | size_t debuglink_len; |
677 | size_t try_len; |
678 | char *try; |
679 | int does_not_exist; |
680 | int ret; |
681 | |
682 | debuglink_len = strlen(debuglink_name); |
683 | try_len = prefix_len + prefix2_len + debuglink_len + 1; |
684 | try = backtrace_alloc(state, try_len, error_callback, data); |
685 | if (try == NULL) return -1; |
686 | |
687 | memcpy(try, prefix, prefix_len); |
688 | memcpy(try + prefix_len, prefix2, prefix2_len); |
689 | memcpy(try + prefix_len + prefix2_len, debuglink_name, debuglink_len); |
690 | try[prefix_len + prefix2_len + debuglink_len] = '\0'; |
691 | |
692 | ret = backtrace_open(try, error_callback, data, &does_not_exist); |
693 | |
694 | backtrace_free(state, try, try_len, error_callback, data); |
695 | |
696 | return ret; |
697 | } |
698 | |
699 | static int elf_find_debugfile_by_debuglink( |
700 | struct backtrace_state *state, const char *filename, |
701 | const char *debuglink_name, backtrace_error_callback error_callback, |
702 | void *data) { |
703 | int ret; |
704 | char *alc; |
705 | size_t alc_len; |
706 | const char *slash; |
707 | int ddescriptor; |
708 | const char *prefix; |
709 | size_t prefix_len; |
710 | |
711 | ret = -1; |
712 | alc = NULL; |
713 | alc_len = 0; |
714 | while (elf_is_symlink(filename)) { |
715 | char *new_buf; |
716 | size_t new_len; |
717 | |
718 | new_buf = elf_readlink(state, filename, error_callback, data, &new_len); |
719 | if (new_buf == NULL) break; |
720 | |
721 | if (new_buf[0] == '/') |
722 | filename = new_buf; |
723 | else { |
724 | slash = strrchr(filename, '/'); |
725 | if (slash == NULL) |
726 | filename = new_buf; |
727 | else { |
728 | size_t clen; |
729 | char *c; |
730 | |
731 | slash++; |
732 | clen = slash - filename + strlen(new_buf) + 1; |
733 | c = backtrace_alloc(state, clen, error_callback, data); |
734 | if (c == NULL) goto done; |
735 | |
736 | memcpy(c, filename, slash - filename); |
737 | memcpy(c + (slash - filename), new_buf, strlen(new_buf)); |
738 | c[slash - filename + strlen(new_buf)] = '\0'; |
739 | backtrace_free(state, new_buf, new_len, error_callback, data); |
740 | filename = c; |
741 | new_buf = c; |
742 | new_len = clen; |
743 | } |
744 | } |
745 | |
746 | if (alc != NULL) backtrace_free(state, alc, alc_len, error_callback, data); |
747 | alc = new_buf; |
748 | alc_len = new_len; |
749 | } |
750 | |
751 | slash = strrchr(filename, '/'); |
752 | if (slash == NULL) { |
753 | prefix = ""; |
754 | prefix_len = 0; |
755 | } else { |
756 | slash++; |
757 | prefix = filename; |
758 | prefix_len = slash - filename; |
759 | } |
760 | |
761 | ddescriptor = elf_try_debugfile(state, prefix, prefix_len, "", 0, |
762 | debuglink_name, error_callback, data); |
763 | if (ddescriptor >= 0) { |
764 | ret = ddescriptor; |
765 | goto done; |
766 | } |
767 | |
768 | ddescriptor = |
769 | elf_try_debugfile(state, prefix, prefix_len, ".debug/", strlen(".debug/"), |
770 | debuglink_name, error_callback, data); |
771 | if (ddescriptor >= 0) { |
772 | ret = ddescriptor; |
773 | goto done; |
774 | } |
775 | |
776 | ddescriptor = elf_try_debugfile(state, "/usr/lib/debug/", |
777 | strlen("/usr/lib/debug/"), prefix, prefix_len, |
778 | debuglink_name, error_callback, data); |
779 | if (ddescriptor >= 0) ret = ddescriptor; |
780 | |
781 | done: |
782 | if (alc != NULL && alc_len > 0) |
783 | backtrace_free(state, alc, alc_len, error_callback, data); |
784 | return ret; |
785 | } |
786 | |
787 | static int elf_open_debugfile_by_debuglink( |
788 | struct backtrace_state *state, const char *filename, |
789 | const char *debuglink_name, uint32_t debuglink_crc, |
790 | backtrace_error_callback error_callback, void *data) { |
791 | int ddescriptor; |
792 | |
793 | ddescriptor = elf_find_debugfile_by_debuglink(state, filename, debuglink_name, |
794 | error_callback, data); |
795 | if (ddescriptor < 0) return -1; |
796 | |
797 | if (debuglink_crc != 0) { |
798 | uint32_t got_crc; |
799 | |
800 | got_crc = elf_crc32_file(state, ddescriptor, error_callback, data); |
801 | if (got_crc != debuglink_crc) { |
802 | backtrace_close(ddescriptor, error_callback, data); |
803 | return -1; |
804 | } |
805 | } |
806 | |
807 | return ddescriptor; |
808 | } |
809 | |
810 | static void elf_uncompress_failed(void) {} |
811 | |
812 | static int elf_zlib_fetch(const unsigned char **ppin, |
813 | const unsigned char *pinend, uint64_t *pval, |
814 | unsigned int *pbits) { |
815 | unsigned int bits; |
816 | const unsigned char *pin; |
817 | uint64_t val; |
818 | uint32_t next; |
819 | |
820 | bits = *pbits; |
821 | if (bits >= 15) return 1; |
822 | pin = *ppin; |
823 | val = *pval; |
824 | |
825 | if (unlikely(pinend - pin < 4)) { |
826 | elf_uncompress_failed(); |
827 | return 0; |
828 | } |
829 | |
830 | #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ |
831 | defined(__ORDER_BIG_ENDIAN__) && \ |
832 | (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \ |
833 | __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) |
834 | |
835 | next = *(const uint32_t *)pin; |
836 | |
837 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
838 | next = __builtin_bswap32(next); |
839 | #endif |
840 | #else |
841 | next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24); |
842 | #endif |
843 | |
844 | val |= (uint64_t)next << bits; |
845 | bits += 32; |
846 | pin += 4; |
847 | |
848 | __builtin_prefetch(pin, 0, 0); |
849 | |
850 | *ppin = pin; |
851 | *pval = val; |
852 | *pbits = bits; |
853 | return 1; |
854 | } |
855 | |
856 | #define HUFFMAN_TABLE_SIZE (1024) |
857 | |
858 | #define HUFFMAN_VALUE_MASK 0x01ff |
859 | #define HUFFMAN_BITS_SHIFT 9 |
860 | #define HUFFMAN_BITS_MASK 0x7 |
861 | #define HUFFMAN_SECONDARY_SHIFT 12 |
862 | |
863 | #define ZDEBUG_TABLE_SIZE \ |
864 | (2 * HUFFMAN_TABLE_SIZE * sizeof(uint16_t) + (286 + 30) * sizeof(uint16_t) + \ |
865 | (286 + 30) * sizeof(unsigned char)) |
866 | |
867 | #define ZDEBUG_TABLE_CODELEN_OFFSET \ |
868 | (2 * HUFFMAN_TABLE_SIZE * sizeof(uint16_t) + (286 + 30) * sizeof(uint16_t)) |
869 | |
870 | #define ZDEBUG_TABLE_WORK_OFFSET (2 * HUFFMAN_TABLE_SIZE * sizeof(uint16_t)) |
871 | |
872 | #ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE |
873 | |
874 | static size_t final_next_secondary; |
875 | |
876 | #endif |
877 | |
878 | static int elf_zlib_inflate_table(unsigned char *codes, size_t codes_len, |
879 | uint16_t *zdebug_table, uint16_t *table) { |
880 | uint16_t count[16]; |
881 | uint16_t start[16]; |
882 | uint16_t prev[16]; |
883 | uint16_t firstcode[7]; |
884 | uint16_t *next; |
885 | size_t i; |
886 | size_t j; |
887 | unsigned int code; |
888 | size_t next_secondary; |
889 | |
890 | next = |
891 | (uint16_t *)(((unsigned char *)zdebug_table) + ZDEBUG_TABLE_WORK_OFFSET); |
892 | |
893 | memset(&count[0], 0, 16 * sizeof(uint16_t)); |
894 | for (i = 0; i < codes_len; ++i) { |
895 | if (unlikely(codes[i] >= 16)) { |
896 | elf_uncompress_failed(); |
897 | return 0; |
898 | } |
899 | |
900 | if (count[codes[i]] == 0) { |
901 | start[codes[i]] = i; |
902 | prev[codes[i]] = i; |
903 | } else { |
904 | next[prev[codes[i]]] = i; |
905 | prev[codes[i]] = i; |
906 | } |
907 | |
908 | ++count[codes[i]]; |
909 | } |
910 | |
911 | memset(table, 0, HUFFMAN_TABLE_SIZE * sizeof(uint16_t)); |
912 | |
913 | code = 0; |
914 | for (j = 1; j <= 8; ++j) { |
915 | unsigned int jcnt; |
916 | unsigned int val; |
917 | |
918 | jcnt = count[j]; |
919 | if (jcnt == 0) continue; |
920 | |
921 | if (unlikely(jcnt > (1U << j))) { |
922 | elf_uncompress_failed(); |
923 | return 0; |
924 | } |
925 | |
926 | val = start[j]; |
927 | for (i = 0; i < jcnt; ++i) { |
928 | uint16_t tval; |
929 | size_t ind; |
930 | unsigned int incr; |
931 | |
932 | if (unlikely((val & ~HUFFMAN_VALUE_MASK) != 0)) { |
933 | elf_uncompress_failed(); |
934 | return 0; |
935 | } |
936 | |
937 | tval = val | ((j - 1) << HUFFMAN_BITS_SHIFT); |
938 | |
939 | for (ind = code; ind < 0x100; ind += 1 << j) { |
940 | if (unlikely(table[ind] != 0)) { |
941 | elf_uncompress_failed(); |
942 | return 0; |
943 | } |
944 | table[ind] = tval; |
945 | } |
946 | |
947 | if (i + 1 < jcnt) val = next[val]; |
948 | |
949 | incr = 1U << (j - 1); |
950 | while ((code & incr) != 0) incr >>= 1; |
951 | if (incr == 0) |
952 | code = 0; |
953 | else { |
954 | code &= incr - 1; |
955 | code += incr; |
956 | } |
957 | } |
958 | } |
959 | |
960 | for (j = 9; j < 16; j++) { |
961 | unsigned int jcnt; |
962 | unsigned int k; |
963 | |
964 | jcnt = count[j]; |
965 | if (jcnt == 0) continue; |
966 | |
967 | firstcode[j - 9] = code; |
968 | |
969 | for (k = 0; k < j; ++k) { |
970 | if ((jcnt & (1U << k)) != 0) { |
971 | unsigned int m; |
972 | unsigned int bit; |
973 | |
974 | bit = 1U << (j - k - 1); |
975 | for (m = 0; m < j - k; ++m, bit >>= 1) { |
976 | if ((code & bit) == 0) { |
977 | code += bit; |
978 | break; |
979 | } |
980 | code &= ~bit; |
981 | } |
982 | jcnt &= ~(1U << k); |
983 | } |
984 | } |
985 | if (unlikely(jcnt != 0)) { |
986 | elf_uncompress_failed(); |
987 | return 0; |
988 | } |
989 | } |
990 | |
991 | next_secondary = 0; |
992 | for (j = 15; j >= 9; j--) { |
993 | unsigned int jcnt; |
994 | unsigned int val; |
995 | size_t primary; |
996 | size_t secondary; |
997 | size_t secondary_bits; |
998 | jcnt = count[j]; |
999 | if (jcnt == 0) continue; |
1000 | |
1001 | val = start[j]; |
1002 | code = firstcode[j - 9]; |
1003 | primary = 0x100; |
1004 | secondary = 0; |
1005 | secondary_bits = 0; |
1006 | for (i = 0; i < jcnt; ++i) { |
1007 | uint16_t tval; |
1008 | size_t ind; |
1009 | unsigned int incr; |
1010 | |
1011 | if ((code & 0xff) != primary) { |
1012 | uint16_t tprimary; |
1013 | |
1014 | primary = code & 0xff; |
1015 | |
1016 | tprimary = table[primary]; |
1017 | if (tprimary == 0) { |
1018 | if (unlikely((next_secondary & HUFFMAN_VALUE_MASK) != |
1019 | next_secondary)) { |
1020 | elf_uncompress_failed(); |
1021 | return 0; |
1022 | } |
1023 | |
1024 | secondary = next_secondary; |
1025 | secondary_bits = j - 8; |
1026 | next_secondary += 1 << secondary_bits; |
1027 | table[primary] = (secondary + ((j - 8) << HUFFMAN_BITS_SHIFT) + |
1028 | (1U << HUFFMAN_SECONDARY_SHIFT)); |
1029 | } else { |
1030 | if (unlikely((tprimary & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0)) { |
1031 | elf_uncompress_failed(); |
1032 | return 0; |
1033 | } |
1034 | secondary = tprimary & HUFFMAN_VALUE_MASK; |
1035 | secondary_bits = |
1036 | ((tprimary >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK); |
1037 | if (unlikely(secondary_bits < j - 8)) { |
1038 | elf_uncompress_failed(); |
1039 | return 0; |
1040 | } |
1041 | } |
1042 | } |
1043 | |
1044 | tval = val | ((j - 8) << HUFFMAN_BITS_SHIFT); |
1045 | |
1046 | for (ind = code >> 8; ind < (1U << secondary_bits); |
1047 | ind += 1U << (j - 8)) { |
1048 | if (unlikely(table[secondary + 0x100 + ind] != 0)) { |
1049 | elf_uncompress_failed(); |
1050 | return 0; |
1051 | } |
1052 | table[secondary + 0x100 + ind] = tval; |
1053 | } |
1054 | |
1055 | if (i + 1 < jcnt) val = next[val]; |
1056 | |
1057 | incr = 1U << (j - 1); |
1058 | while ((code & incr) != 0) incr >>= 1; |
1059 | if (incr == 0) |
1060 | code = 0; |
1061 | else { |
1062 | code &= incr - 1; |
1063 | code += incr; |
1064 | } |
1065 | } |
1066 | } |
1067 | |
1068 | #ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE |
1069 | final_next_secondary = next_secondary; |
1070 | #endif |
1071 | |
1072 | return 1; |
1073 | } |
1074 | |
1075 | static const uint16_t elf_zlib_default_table[0x170] = { |
1076 | 0xd00, 0xe50, 0xe10, 0xf18, 0xd10, 0xe70, 0xe30, 0x1230, 0xd08, 0xe60, |
1077 | 0xe20, 0x1210, 0xe00, 0xe80, 0xe40, 0x1250, 0xd04, 0xe58, 0xe18, 0x1200, |
1078 | 0xd14, 0xe78, 0xe38, 0x1240, 0xd0c, 0xe68, 0xe28, 0x1220, 0xe08, 0xe88, |
1079 | 0xe48, 0x1260, 0xd02, 0xe54, 0xe14, 0xf1c, 0xd12, 0xe74, 0xe34, 0x1238, |
1080 | 0xd0a, 0xe64, 0xe24, 0x1218, 0xe04, 0xe84, 0xe44, 0x1258, 0xd06, 0xe5c, |
1081 | 0xe1c, 0x1208, 0xd16, 0xe7c, 0xe3c, 0x1248, 0xd0e, 0xe6c, 0xe2c, 0x1228, |
1082 | 0xe0c, 0xe8c, 0xe4c, 0x1268, 0xd01, 0xe52, 0xe12, 0xf1a, 0xd11, 0xe72, |
1083 | 0xe32, 0x1234, 0xd09, 0xe62, 0xe22, 0x1214, 0xe02, 0xe82, 0xe42, 0x1254, |
1084 | 0xd05, 0xe5a, 0xe1a, 0x1204, 0xd15, 0xe7a, 0xe3a, 0x1244, 0xd0d, 0xe6a, |
1085 | 0xe2a, 0x1224, 0xe0a, 0xe8a, 0xe4a, 0x1264, 0xd03, 0xe56, 0xe16, 0xf1e, |
1086 | 0xd13, 0xe76, 0xe36, 0x123c, 0xd0b, 0xe66, 0xe26, 0x121c, 0xe06, 0xe86, |
1087 | 0xe46, 0x125c, 0xd07, 0xe5e, 0xe1e, 0x120c, 0xd17, 0xe7e, 0xe3e, 0x124c, |
1088 | 0xd0f, 0xe6e, 0xe2e, 0x122c, 0xe0e, 0xe8e, 0xe4e, 0x126c, 0xd00, 0xe51, |
1089 | 0xe11, 0xf19, 0xd10, 0xe71, 0xe31, 0x1232, 0xd08, 0xe61, 0xe21, 0x1212, |
1090 | 0xe01, 0xe81, 0xe41, 0x1252, 0xd04, 0xe59, 0xe19, 0x1202, 0xd14, 0xe79, |
1091 | 0xe39, 0x1242, 0xd0c, 0xe69, 0xe29, 0x1222, 0xe09, 0xe89, 0xe49, 0x1262, |
1092 | 0xd02, 0xe55, 0xe15, 0xf1d, 0xd12, 0xe75, 0xe35, 0x123a, 0xd0a, 0xe65, |
1093 | 0xe25, 0x121a, 0xe05, 0xe85, 0xe45, 0x125a, 0xd06, 0xe5d, 0xe1d, 0x120a, |
1094 | 0xd16, 0xe7d, 0xe3d, 0x124a, 0xd0e, 0xe6d, 0xe2d, 0x122a, 0xe0d, 0xe8d, |
1095 | 0xe4d, 0x126a, 0xd01, 0xe53, 0xe13, 0xf1b, 0xd11, 0xe73, 0xe33, 0x1236, |
1096 | 0xd09, 0xe63, 0xe23, 0x1216, 0xe03, 0xe83, 0xe43, 0x1256, 0xd05, 0xe5b, |
1097 | 0xe1b, 0x1206, 0xd15, 0xe7b, 0xe3b, 0x1246, 0xd0d, 0xe6b, 0xe2b, 0x1226, |
1098 | 0xe0b, 0xe8b, 0xe4b, 0x1266, 0xd03, 0xe57, 0xe17, 0xf1f, 0xd13, 0xe77, |
1099 | 0xe37, 0x123e, 0xd0b, 0xe67, 0xe27, 0x121e, 0xe07, 0xe87, 0xe47, 0x125e, |
1100 | 0xd07, 0xe5f, 0xe1f, 0x120e, 0xd17, 0xe7f, 0xe3f, 0x124e, 0xd0f, 0xe6f, |
1101 | 0xe2f, 0x122e, 0xe0f, 0xe8f, 0xe4f, 0x126e, 0x290, 0x291, 0x292, 0x293, |
1102 | 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29a, 0x29b, 0x29c, 0x29d, |
1103 | 0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a3, 0x2a4, 0x2a5, 0x2a6, 0x2a7, |
1104 | 0x2a8, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ad, 0x2ae, 0x2af, 0x2b0, 0x2b1, |
1105 | 0x2b2, 0x2b3, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b8, 0x2b9, 0x2ba, 0x2bb, |
1106 | 0x2bc, 0x2bd, 0x2be, 0x2bf, 0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c5, |
1107 | 0x2c6, 0x2c7, 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2cf, |
1108 | 0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2d7, 0x2d8, 0x2d9, |
1109 | 0x2da, 0x2db, 0x2dc, 0x2dd, 0x2de, 0x2df, 0x2e0, 0x2e1, 0x2e2, 0x2e3, |
1110 | 0x2e4, 0x2e5, 0x2e6, 0x2e7, 0x2e8, 0x2e9, 0x2ea, 0x2eb, 0x2ec, 0x2ed, |
1111 | 0x2ee, 0x2ef, 0x2f0, 0x2f1, 0x2f2, 0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7, |
1112 | 0x2f8, 0x2f9, 0x2fa, 0x2fb, 0x2fc, 0x2fd, 0x2fe, 0x2ff, |
1113 | }; |
1114 | |
1115 | static const uint16_t elf_zlib_default_dist_table[0x100] = { |
1116 | 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, |
1117 | 0x81a, 0x806, 0x816, 0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, |
1118 | 0x80d, 0x81d, 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, |
1119 | 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, |
1120 | 0x806, 0x816, 0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, |
1121 | 0x81d, 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, |
1122 | 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, |
1123 | 0x816, 0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, |
1124 | 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, |
1125 | 0x818, 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, |
1126 | 0x80e, 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, |
1127 | 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818, |
1128 | 0x804, 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, |
1129 | 0x81e, 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813, |
1130 | 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818, 0x804, |
1131 | 0x814, 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, |
1132 | 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813, 0x80b, |
1133 | 0x81b, 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, |
1134 | 0x80c, 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, 0x801, |
1135 | 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813, 0x80b, 0x81b, |
1136 | 0x807, 0x817, 0x80f, 0x81f, 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, |
1137 | 0x81c, 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, 0x801, 0x811, |
1138 | 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, 0x803, 0x813, 0x80b, 0x81b, 0x807, |
1139 | 0x817, 0x80f, 0x81f, |
1140 | }; |
1141 | |
1142 | static int elf_zlib_inflate(const unsigned char *pin, size_t sin, |
1143 | uint16_t *zdebug_table, unsigned char *pout, |
1144 | size_t sout) { |
1145 | unsigned char *porigout; |
1146 | const unsigned char *pinend; |
1147 | unsigned char *poutend; |
1148 | |
1149 | porigout = pout; |
1150 | pinend = pin + sin; |
1151 | poutend = pout + sout; |
1152 | while ((pinend - pin) > 4) { |
1153 | uint64_t val; |
1154 | unsigned int bits; |
1155 | int last; |
1156 | |
1157 | if (unlikely((pin[0] & 0xf) != 8)) { |
1158 | elf_uncompress_failed(); |
1159 | return 0; |
1160 | } |
1161 | if (unlikely((pin[0] >> 4) > 7)) { |
1162 | elf_uncompress_failed(); |
1163 | return 0; |
1164 | } |
1165 | if (unlikely((pin[1] & 0x20) != 0)) { |
1166 | elf_uncompress_failed(); |
1167 | return 0; |
1168 | } |
1169 | val = (pin[0] << 8) | pin[1]; |
1170 | if (unlikely(val % 31 != 0)) { |
1171 | elf_uncompress_failed(); |
1172 | return 0; |
1173 | } |
1174 | pin += 2; |
1175 | |
1176 | val = 0; |
1177 | bits = 0; |
1178 | while ((((uintptr_t)pin) & 3) != 0) { |
1179 | val |= (uint64_t)*pin << bits; |
1180 | bits += 8; |
1181 | ++pin; |
1182 | } |
1183 | |
1184 | last = 0; |
1185 | |
1186 | while (!last) { |
1187 | unsigned int type; |
1188 | const uint16_t *tlit; |
1189 | const uint16_t *tdist; |
1190 | |
1191 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1192 | |
1193 | last = val & 1; |
1194 | type = (val >> 1) & 3; |
1195 | val >>= 3; |
1196 | bits -= 3; |
1197 | |
1198 | if (unlikely(type == 3)) { |
1199 | elf_uncompress_failed(); |
1200 | return 0; |
1201 | } |
1202 | |
1203 | if (type == 0) { |
1204 | uint16_t len; |
1205 | uint16_t lenc; |
1206 | |
1207 | while (bits >= 8) { |
1208 | --pin; |
1209 | bits -= 8; |
1210 | } |
1211 | |
1212 | val = 0; |
1213 | bits = 0; |
1214 | if (unlikely((pinend - pin) < 4)) { |
1215 | elf_uncompress_failed(); |
1216 | return 0; |
1217 | } |
1218 | len = pin[0] | (pin[1] << 8); |
1219 | lenc = pin[2] | (pin[3] << 8); |
1220 | pin += 4; |
1221 | lenc = ~lenc; |
1222 | if (unlikely(len != lenc)) { |
1223 | elf_uncompress_failed(); |
1224 | return 0; |
1225 | } |
1226 | if (unlikely(len > (unsigned int)(pinend - pin) || |
1227 | len > (unsigned int)(poutend - pout))) { |
1228 | elf_uncompress_failed(); |
1229 | return 0; |
1230 | } |
1231 | memcpy(pout, pin, len); |
1232 | pout += len; |
1233 | pin += len; |
1234 | |
1235 | while ((((uintptr_t)pin) & 3) != 0) { |
1236 | val |= (uint64_t)*pin << bits; |
1237 | bits += 8; |
1238 | ++pin; |
1239 | } |
1240 | |
1241 | continue; |
1242 | } |
1243 | |
1244 | if (type == 1) { |
1245 | tlit = elf_zlib_default_table; |
1246 | tdist = elf_zlib_default_dist_table; |
1247 | } else { |
1248 | unsigned int nlit; |
1249 | unsigned int ndist; |
1250 | unsigned int nclen; |
1251 | unsigned char codebits[19]; |
1252 | unsigned char *plenbase; |
1253 | unsigned char *plen; |
1254 | unsigned char *plenend; |
1255 | |
1256 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1257 | |
1258 | nlit = (val & 0x1f) + 257; |
1259 | val >>= 5; |
1260 | ndist = (val & 0x1f) + 1; |
1261 | val >>= 5; |
1262 | nclen = (val & 0xf) + 4; |
1263 | val >>= 4; |
1264 | bits -= 14; |
1265 | if (unlikely(nlit > 286 || ndist > 30)) { |
1266 | elf_uncompress_failed(); |
1267 | return 0; |
1268 | } |
1269 | |
1270 | memset(&codebits[0], 0, 19); |
1271 | |
1272 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1273 | |
1274 | codebits[16] = val & 7; |
1275 | codebits[17] = (val >> 3) & 7; |
1276 | codebits[18] = (val >> 6) & 7; |
1277 | codebits[0] = (val >> 9) & 7; |
1278 | val >>= 12; |
1279 | bits -= 12; |
1280 | |
1281 | if (nclen == 4) goto codebitsdone; |
1282 | |
1283 | codebits[8] = val & 7; |
1284 | val >>= 3; |
1285 | bits -= 3; |
1286 | |
1287 | if (nclen == 5) goto codebitsdone; |
1288 | |
1289 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1290 | |
1291 | codebits[7] = val & 7; |
1292 | val >>= 3; |
1293 | bits -= 3; |
1294 | |
1295 | if (nclen == 6) goto codebitsdone; |
1296 | |
1297 | codebits[9] = val & 7; |
1298 | val >>= 3; |
1299 | bits -= 3; |
1300 | |
1301 | if (nclen == 7) goto codebitsdone; |
1302 | |
1303 | codebits[6] = val & 7; |
1304 | val >>= 3; |
1305 | bits -= 3; |
1306 | |
1307 | if (nclen == 8) goto codebitsdone; |
1308 | |
1309 | codebits[10] = val & 7; |
1310 | val >>= 3; |
1311 | bits -= 3; |
1312 | |
1313 | if (nclen == 9) goto codebitsdone; |
1314 | |
1315 | codebits[5] = val & 7; |
1316 | val >>= 3; |
1317 | bits -= 3; |
1318 | |
1319 | if (nclen == 10) goto codebitsdone; |
1320 | |
1321 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1322 | |
1323 | codebits[11] = val & 7; |
1324 | val >>= 3; |
1325 | bits -= 3; |
1326 | |
1327 | if (nclen == 11) goto codebitsdone; |
1328 | |
1329 | codebits[4] = val & 7; |
1330 | val >>= 3; |
1331 | bits -= 3; |
1332 | |
1333 | if (nclen == 12) goto codebitsdone; |
1334 | |
1335 | codebits[12] = val & 7; |
1336 | val >>= 3; |
1337 | bits -= 3; |
1338 | |
1339 | if (nclen == 13) goto codebitsdone; |
1340 | |
1341 | codebits[3] = val & 7; |
1342 | val >>= 3; |
1343 | bits -= 3; |
1344 | |
1345 | if (nclen == 14) goto codebitsdone; |
1346 | |
1347 | codebits[13] = val & 7; |
1348 | val >>= 3; |
1349 | bits -= 3; |
1350 | |
1351 | if (nclen == 15) goto codebitsdone; |
1352 | |
1353 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1354 | |
1355 | codebits[2] = val & 7; |
1356 | val >>= 3; |
1357 | bits -= 3; |
1358 | |
1359 | if (nclen == 16) goto codebitsdone; |
1360 | |
1361 | codebits[14] = val & 7; |
1362 | val >>= 3; |
1363 | bits -= 3; |
1364 | |
1365 | if (nclen == 17) goto codebitsdone; |
1366 | |
1367 | codebits[1] = val & 7; |
1368 | val >>= 3; |
1369 | bits -= 3; |
1370 | |
1371 | if (nclen == 18) goto codebitsdone; |
1372 | |
1373 | codebits[15] = val & 7; |
1374 | val >>= 3; |
1375 | bits -= 3; |
1376 | |
1377 | codebitsdone: |
1378 | |
1379 | if (!elf_zlib_inflate_table(codebits, 19, zdebug_table, zdebug_table)) |
1380 | return 0; |
1381 | |
1382 | plenbase = |
1383 | (((unsigned char *)zdebug_table) + ZDEBUG_TABLE_CODELEN_OFFSET); |
1384 | plen = plenbase; |
1385 | plenend = plen + nlit + ndist; |
1386 | while (plen < plenend) { |
1387 | uint16_t t; |
1388 | unsigned int b; |
1389 | uint16_t v; |
1390 | |
1391 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1392 | |
1393 | t = zdebug_table[val & 0xff]; |
1394 | |
1395 | if (unlikely((t & (1U << HUFFMAN_SECONDARY_SHIFT)) != 0)) { |
1396 | elf_uncompress_failed(); |
1397 | return 0; |
1398 | } |
1399 | |
1400 | b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK; |
1401 | val >>= b + 1; |
1402 | bits -= b + 1; |
1403 | |
1404 | v = t & HUFFMAN_VALUE_MASK; |
1405 | if (v < 16) |
1406 | *plen++ = v; |
1407 | else if (v == 16) { |
1408 | unsigned int c; |
1409 | unsigned int prev; |
1410 | |
1411 | if (unlikely(plen == plenbase)) { |
1412 | elf_uncompress_failed(); |
1413 | return 0; |
1414 | } |
1415 | |
1416 | c = 3 + (val & 0x3); |
1417 | val >>= 2; |
1418 | bits -= 2; |
1419 | if (unlikely((unsigned int)(plenend - plen) < c)) { |
1420 | elf_uncompress_failed(); |
1421 | return 0; |
1422 | } |
1423 | |
1424 | prev = plen[-1]; |
1425 | switch (c) { |
1426 | case 6: |
1427 | *plen++ = prev; |
1428 | ATTRIBUTE_FALLTHROUGH; |
1429 | case 5: |
1430 | *plen++ = prev; |
1431 | ATTRIBUTE_FALLTHROUGH; |
1432 | case 4: |
1433 | *plen++ = prev; |
1434 | } |
1435 | *plen++ = prev; |
1436 | *plen++ = prev; |
1437 | *plen++ = prev; |
1438 | } else if (v == 17) { |
1439 | unsigned int c; |
1440 | |
1441 | c = 3 + (val & 0x7); |
1442 | val >>= 3; |
1443 | bits -= 3; |
1444 | if (unlikely((unsigned int)(plenend - plen) < c)) { |
1445 | elf_uncompress_failed(); |
1446 | return 0; |
1447 | } |
1448 | |
1449 | switch (c) { |
1450 | case 10: |
1451 | *plen++ = 0; |
1452 | ATTRIBUTE_FALLTHROUGH; |
1453 | case 9: |
1454 | *plen++ = 0; |
1455 | ATTRIBUTE_FALLTHROUGH; |
1456 | case 8: |
1457 | *plen++ = 0; |
1458 | ATTRIBUTE_FALLTHROUGH; |
1459 | case 7: |
1460 | *plen++ = 0; |
1461 | ATTRIBUTE_FALLTHROUGH; |
1462 | case 6: |
1463 | *plen++ = 0; |
1464 | ATTRIBUTE_FALLTHROUGH; |
1465 | case 5: |
1466 | *plen++ = 0; |
1467 | ATTRIBUTE_FALLTHROUGH; |
1468 | case 4: |
1469 | *plen++ = 0; |
1470 | } |
1471 | *plen++ = 0; |
1472 | *plen++ = 0; |
1473 | *plen++ = 0; |
1474 | } else if (v == 18) { |
1475 | unsigned int c; |
1476 | |
1477 | c = 11 + (val & 0x7f); |
1478 | val >>= 7; |
1479 | bits -= 7; |
1480 | if (unlikely((unsigned int)(plenend - plen) < c)) { |
1481 | elf_uncompress_failed(); |
1482 | return 0; |
1483 | } |
1484 | |
1485 | memset(plen, 0, c); |
1486 | plen += c; |
1487 | } else { |
1488 | elf_uncompress_failed(); |
1489 | return 0; |
1490 | } |
1491 | } |
1492 | |
1493 | plen = plenbase; |
1494 | if (unlikely(plen[256] == 0)) { |
1495 | elf_uncompress_failed(); |
1496 | return 0; |
1497 | } |
1498 | |
1499 | if (!elf_zlib_inflate_table(plen, nlit, zdebug_table, zdebug_table)) |
1500 | return 0; |
1501 | if (!elf_zlib_inflate_table(plen + nlit, ndist, zdebug_table, |
1502 | zdebug_table + HUFFMAN_TABLE_SIZE)) |
1503 | return 0; |
1504 | tlit = zdebug_table; |
1505 | tdist = zdebug_table + HUFFMAN_TABLE_SIZE; |
1506 | } |
1507 | |
1508 | while (1) { |
1509 | uint16_t t; |
1510 | unsigned int b; |
1511 | uint16_t v; |
1512 | unsigned int lit; |
1513 | |
1514 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1515 | |
1516 | t = tlit[val & 0xff]; |
1517 | b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK; |
1518 | v = t & HUFFMAN_VALUE_MASK; |
1519 | |
1520 | if ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0) { |
1521 | lit = v; |
1522 | val >>= b + 1; |
1523 | bits -= b + 1; |
1524 | } else { |
1525 | t = tlit[v + 0x100 + ((val >> 8) & ((1U << b) - 1))]; |
1526 | b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK; |
1527 | lit = t & HUFFMAN_VALUE_MASK; |
1528 | val >>= b + 8; |
1529 | bits -= b + 8; |
1530 | } |
1531 | |
1532 | if (lit < 256) { |
1533 | if (unlikely(pout == poutend)) { |
1534 | elf_uncompress_failed(); |
1535 | return 0; |
1536 | } |
1537 | |
1538 | *pout++ = lit; |
1539 | |
1540 | __builtin_prefetch(pout, 1, 3); |
1541 | } else if (lit == 256) { |
1542 | break; |
1543 | } else { |
1544 | unsigned int dist; |
1545 | unsigned int len; |
1546 | |
1547 | if (lit < 265) |
1548 | len = lit - 257 + 3; |
1549 | else if (lit == 285) |
1550 | len = 258; |
1551 | else if (unlikely(lit > 285)) { |
1552 | elf_uncompress_failed(); |
1553 | return 0; |
1554 | } else { |
1555 | unsigned int extra; |
1556 | |
1557 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1558 | |
1559 | lit -= 265; |
1560 | extra = (lit >> 2) + 1; |
1561 | len = (lit & 3) << extra; |
1562 | len += 11; |
1563 | len += ((1U << (extra - 1)) - 1) << 3; |
1564 | len += val & ((1U << extra) - 1); |
1565 | val >>= extra; |
1566 | bits -= extra; |
1567 | } |
1568 | |
1569 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1570 | |
1571 | t = tdist[val & 0xff]; |
1572 | b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK; |
1573 | v = t & HUFFMAN_VALUE_MASK; |
1574 | |
1575 | if ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) == 0) { |
1576 | dist = v; |
1577 | val >>= b + 1; |
1578 | bits -= b + 1; |
1579 | } else { |
1580 | t = tdist[v + 0x100 + ((val >> 8) & ((1U << b) - 1))]; |
1581 | b = (t >> HUFFMAN_BITS_SHIFT) & HUFFMAN_BITS_MASK; |
1582 | dist = t & HUFFMAN_VALUE_MASK; |
1583 | val >>= b + 8; |
1584 | bits -= b + 8; |
1585 | } |
1586 | |
1587 | if (dist == 0) { |
1588 | if (unlikely(pout == porigout)) { |
1589 | elf_uncompress_failed(); |
1590 | return 0; |
1591 | } |
1592 | |
1593 | if (unlikely((unsigned int)(poutend - pout) < len)) { |
1594 | elf_uncompress_failed(); |
1595 | return 0; |
1596 | } |
1597 | |
1598 | memset(pout, pout[-1], len); |
1599 | pout += len; |
1600 | } else if (unlikely(dist > 29)) { |
1601 | elf_uncompress_failed(); |
1602 | return 0; |
1603 | } else { |
1604 | if (dist < 4) |
1605 | dist = dist + 1; |
1606 | else { |
1607 | unsigned int extra; |
1608 | |
1609 | if (!elf_zlib_fetch(&pin, pinend, &val, &bits)) return 0; |
1610 | |
1611 | dist -= 4; |
1612 | extra = (dist >> 1) + 1; |
1613 | dist = (dist & 1) << extra; |
1614 | dist += 5; |
1615 | dist += ((1U << (extra - 1)) - 1) << 2; |
1616 | dist += val & ((1U << extra) - 1); |
1617 | val >>= extra; |
1618 | bits -= extra; |
1619 | } |
1620 | |
1621 | if (unlikely((unsigned int)(pout - porigout) < dist)) { |
1622 | elf_uncompress_failed(); |
1623 | return 0; |
1624 | } |
1625 | |
1626 | if (unlikely((unsigned int)(poutend - pout) < len)) { |
1627 | elf_uncompress_failed(); |
1628 | return 0; |
1629 | } |
1630 | |
1631 | if (dist >= len) { |
1632 | memcpy(pout, pout - dist, len); |
1633 | pout += len; |
1634 | } else { |
1635 | while (len > 0) { |
1636 | unsigned int copy; |
1637 | |
1638 | copy = len < dist ? len : dist; |
1639 | memcpy(pout, pout - dist, copy); |
1640 | len -= copy; |
1641 | pout += copy; |
1642 | } |
1643 | } |
1644 | } |
1645 | } |
1646 | } |
1647 | } |
1648 | } |
1649 | |
1650 | if (unlikely(pout != poutend)) { |
1651 | elf_uncompress_failed(); |
1652 | return 0; |
1653 | } |
1654 | |
1655 | return 1; |
1656 | } |
1657 | |
1658 | static int elf_zlib_verify_checksum(const unsigned char *checkbytes, |
1659 | const unsigned char *uncompressed, |
1660 | size_t uncompressed_size) { |
1661 | unsigned int i; |
1662 | unsigned int cksum; |
1663 | const unsigned char *p; |
1664 | uint32_t s1; |
1665 | uint32_t s2; |
1666 | size_t hsz; |
1667 | |
1668 | cksum = 0; |
1669 | for (i = 0; i < 4; i++) cksum = (cksum << 8) | checkbytes[i]; |
1670 | |
1671 | s1 = 1; |
1672 | s2 = 0; |
1673 | |
1674 | p = uncompressed; |
1675 | hsz = uncompressed_size; |
1676 | while (hsz >= 5552) { |
1677 | for (i = 0; i < 5552; i += 16) { |
1678 | s1 = s1 + *p++; |
1679 | s2 = s2 + s1; |
1680 | s1 = s1 + *p++; |
1681 | s2 = s2 + s1; |
1682 | s1 = s1 + *p++; |
1683 | s2 = s2 + s1; |
1684 | s1 = s1 + *p++; |
1685 | s2 = s2 + s1; |
1686 | s1 = s1 + *p++; |
1687 | s2 = s2 + s1; |
1688 | s1 = s1 + *p++; |
1689 | s2 = s2 + s1; |
1690 | s1 = s1 + *p++; |
1691 | s2 = s2 + s1; |
1692 | s1 = s1 + *p++; |
1693 | s2 = s2 + s1; |
1694 | s1 = s1 + *p++; |
1695 | s2 = s2 + s1; |
1696 | s1 = s1 + *p++; |
1697 | s2 = s2 + s1; |
1698 | s1 = s1 + *p++; |
1699 | s2 = s2 + s1; |
1700 | s1 = s1 + *p++; |
1701 | s2 = s2 + s1; |
1702 | s1 = s1 + *p++; |
1703 | s2 = s2 + s1; |
1704 | s1 = s1 + *p++; |
1705 | s2 = s2 + s1; |
1706 | s1 = s1 + *p++; |
1707 | s2 = s2 + s1; |
1708 | s1 = s1 + *p++; |
1709 | s2 = s2 + s1; |
1710 | } |
1711 | hsz -= 5552; |
1712 | s1 %= 65521; |
1713 | s2 %= 65521; |
1714 | } |
1715 | |
1716 | while (hsz >= 16) { |
1717 | s1 = s1 + *p++; |
1718 | s2 = s2 + s1; |
1719 | s1 = s1 + *p++; |
1720 | s2 = s2 + s1; |
1721 | s1 = s1 + *p++; |
1722 | s2 = s2 + s1; |
1723 | s1 = s1 + *p++; |
1724 | s2 = s2 + s1; |
1725 | s1 = s1 + *p++; |
1726 | s2 = s2 + s1; |
1727 | s1 = s1 + *p++; |
1728 | s2 = s2 + s1; |
1729 | s1 = s1 + *p++; |
1730 | s2 = s2 + s1; |
1731 | s1 = s1 + *p++; |
1732 | s2 = s2 + s1; |
1733 | s1 = s1 + *p++; |
1734 | s2 = s2 + s1; |
1735 | s1 = s1 + *p++; |
1736 | s2 = s2 + s1; |
1737 | s1 = s1 + *p++; |
1738 | s2 = s2 + s1; |
1739 | s1 = s1 + *p++; |
1740 | s2 = s2 + s1; |
1741 | s1 = s1 + *p++; |
1742 | s2 = s2 + s1; |
1743 | s1 = s1 + *p++; |
1744 | s2 = s2 + s1; |
1745 | s1 = s1 + *p++; |
1746 | s2 = s2 + s1; |
1747 | s1 = s1 + *p++; |
1748 | s2 = s2 + s1; |
1749 | |
1750 | hsz -= 16; |
1751 | } |
1752 | |
1753 | for (i = 0; i < hsz; ++i) { |
1754 | s1 = s1 + *p++; |
1755 | s2 = s2 + s1; |
1756 | } |
1757 | |
1758 | s1 %= 65521; |
1759 | s2 %= 65521; |
1760 | |
1761 | if (unlikely((s2 << 16) + s1 != cksum)) { |
1762 | elf_uncompress_failed(); |
1763 | return 0; |
1764 | } |
1765 | |
1766 | return 1; |
1767 | } |
1768 | |
1769 | static int elf_zlib_inflate_and_verify(const unsigned char *pin, size_t sin, |
1770 | uint16_t *zdebug_table, |
1771 | unsigned char *pout, size_t sout) { |
1772 | if (!elf_zlib_inflate(pin, sin, zdebug_table, pout, sout)) return 0; |
1773 | if (!elf_zlib_verify_checksum(pin + sin - 4, pout, sout)) return 0; |
1774 | return 1; |
1775 | } |
1776 | |
1777 | static int elf_uncompress_zdebug(struct backtrace_state *state, |
1778 | const unsigned char *compressed, |
1779 | size_t compressed_size, uint16_t *zdebug_table, |
1780 | backtrace_error_callback error_callback, |
1781 | void *data, unsigned char **uncompressed, |
1782 | size_t *uncompressed_size) { |
1783 | size_t sz; |
1784 | size_t i; |
1785 | unsigned char *po; |
1786 | |
1787 | *uncompressed = NULL; |
1788 | *uncompressed_size = 0; |
1789 | |
1790 | if (compressed_size < 12 || memcmp(compressed, "ZLIB", 4) != 0) return 1; |
1791 | |
1792 | sz = 0; |
1793 | for (i = 0; i < 8; i++) sz = (sz << 8) | compressed[i + 4]; |
1794 | |
1795 | if (*uncompressed != NULL && *uncompressed_size >= sz) |
1796 | po = *uncompressed; |
1797 | else { |
1798 | po = (unsigned char *)backtrace_alloc(state, sz, error_callback, data); |
1799 | if (po == NULL) return 0; |
1800 | } |
1801 | |
1802 | if (!elf_zlib_inflate_and_verify(compressed + 12, compressed_size - 12, |
1803 | zdebug_table, po, sz)) |
1804 | return 1; |
1805 | |
1806 | *uncompressed = po; |
1807 | *uncompressed_size = sz; |
1808 | |
1809 | return 1; |
1810 | } |
1811 | |
1812 | static int elf_uncompress_chdr(struct backtrace_state *state, |
1813 | const unsigned char *compressed, |
1814 | size_t compressed_size, uint16_t *zdebug_table, |
1815 | backtrace_error_callback error_callback, |
1816 | void *data, unsigned char **uncompressed, |
1817 | size_t *uncompressed_size) { |
1818 | const b_elf_chdr *chdr; |
1819 | unsigned char *po; |
1820 | |
1821 | *uncompressed = NULL; |
1822 | *uncompressed_size = 0; |
1823 | |
1824 | if (compressed_size < sizeof(b_elf_chdr)) return 1; |
1825 | |
1826 | chdr = (const b_elf_chdr *)compressed; |
1827 | |
1828 | if (chdr->ch_type != ELFCOMPRESS_ZLIB) { |
1829 | return 1; |
1830 | } |
1831 | |
1832 | if (*uncompressed != NULL && *uncompressed_size >= chdr->ch_size) |
1833 | po = *uncompressed; |
1834 | else { |
1835 | po = (unsigned char *)backtrace_alloc(state, chdr->ch_size, error_callback, |
1836 | data); |
1837 | if (po == NULL) return 0; |
1838 | } |
1839 | |
1840 | if (!elf_zlib_inflate_and_verify(compressed + sizeof(b_elf_chdr), |
1841 | compressed_size - sizeof(b_elf_chdr), |
1842 | zdebug_table, po, chdr->ch_size)) |
1843 | return 1; |
1844 | |
1845 | *uncompressed = po; |
1846 | *uncompressed_size = chdr->ch_size; |
1847 | |
1848 | return 1; |
1849 | } |
1850 | |
1851 | int backtrace_uncompress_zdebug(struct backtrace_state *state, |
1852 | const unsigned char *compressed, |
1853 | size_t compressed_size, |
1854 | backtrace_error_callback error_callback, |
1855 | void *data, unsigned char **uncompressed, |
1856 | size_t *uncompressed_size) { |
1857 | uint16_t *zdebug_table; |
1858 | int ret; |
1859 | |
1860 | zdebug_table = ((uint16_t *)backtrace_alloc(state, ZDEBUG_TABLE_SIZE, |
1861 | error_callback, data)); |
1862 | if (zdebug_table == NULL) return 0; |
1863 | ret = elf_uncompress_zdebug(state, compressed, compressed_size, zdebug_table, |
1864 | error_callback, data, uncompressed, |
1865 | uncompressed_size); |
1866 | backtrace_free(state, zdebug_table, ZDEBUG_TABLE_SIZE, error_callback, data); |
1867 | return ret; |
1868 | } |
1869 | |
1870 | #define LZMA_STATES (12) |
1871 | |
1872 | #define LZMA_POS_STATES (16) |
1873 | |
1874 | #define LZMA_DIST_STATES (4) |
1875 | |
1876 | #define LZMA_DIST_SLOTS (64) |
1877 | |
1878 | #define LZMA_DIST_MODEL_START (4) |
1879 | |
1880 | #define LZMA_DIST_MODEL_END (14) |
1881 | |
1882 | #define LZMA_FULL_DISTANCES (128) |
1883 | |
1884 | #define LZMA_ALIGN_SIZE (16) |
1885 | |
1886 | #define LZMA_LEN_LOW_SYMBOLS (8) |
1887 | #define LZMA_LEN_MID_SYMBOLS (8) |
1888 | #define LZMA_LEN_HIGH_SYMBOLS (256) |
1889 | |
1890 | #define LZMA_LITERAL_CODERS_MAX (16) |
1891 | #define LZMA_LITERAL_CODER_SIZE (0x300) |
1892 | |
1893 | #define LZMA_PROB_IS_MATCH_LEN (LZMA_STATES * LZMA_POS_STATES) |
1894 | #define LZMA_PROB_IS_REP_LEN LZMA_STATES |
1895 | #define LZMA_PROB_IS_REP0_LEN LZMA_STATES |
1896 | #define LZMA_PROB_IS_REP1_LEN LZMA_STATES |
1897 | #define LZMA_PROB_IS_REP2_LEN LZMA_STATES |
1898 | #define LZMA_PROB_IS_REP0_LONG_LEN (LZMA_STATES * LZMA_POS_STATES) |
1899 | #define LZMA_PROB_DIST_SLOT_LEN (LZMA_DIST_STATES * LZMA_DIST_SLOTS) |
1900 | #define LZMA_PROB_DIST_SPECIAL_LEN (LZMA_FULL_DISTANCES - LZMA_DIST_MODEL_END) |
1901 | #define LZMA_PROB_DIST_ALIGN_LEN LZMA_ALIGN_SIZE |
1902 | #define LZMA_PROB_MATCH_LEN_CHOICE_LEN 1 |
1903 | #define LZMA_PROB_MATCH_LEN_CHOICE2_LEN 1 |
1904 | #define LZMA_PROB_MATCH_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS) |
1905 | #define LZMA_PROB_MATCH_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS) |
1906 | #define LZMA_PROB_MATCH_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS |
1907 | #define LZMA_PROB_REP_LEN_CHOICE_LEN 1 |
1908 | #define LZMA_PROB_REP_LEN_CHOICE2_LEN 1 |
1909 | #define LZMA_PROB_REP_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS) |
1910 | #define LZMA_PROB_REP_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS) |
1911 | #define LZMA_PROB_REP_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS |
1912 | #define LZMA_PROB_LITERAL_LEN \ |
1913 | (LZMA_LITERAL_CODERS_MAX * LZMA_LITERAL_CODER_SIZE) |
1914 | |
1915 | #define LZMA_PROB_IS_MATCH_OFFSET 0 |
1916 | #define LZMA_PROB_IS_REP_OFFSET \ |
1917 | (LZMA_PROB_IS_MATCH_OFFSET + LZMA_PROB_IS_MATCH_LEN) |
1918 | #define LZMA_PROB_IS_REP0_OFFSET \ |
1919 | (LZMA_PROB_IS_REP_OFFSET + LZMA_PROB_IS_REP_LEN) |
1920 | #define LZMA_PROB_IS_REP1_OFFSET \ |
1921 | (LZMA_PROB_IS_REP0_OFFSET + LZMA_PROB_IS_REP0_LEN) |
1922 | #define LZMA_PROB_IS_REP2_OFFSET \ |
1923 | (LZMA_PROB_IS_REP1_OFFSET + LZMA_PROB_IS_REP1_LEN) |
1924 | #define LZMA_PROB_IS_REP0_LONG_OFFSET \ |
1925 | (LZMA_PROB_IS_REP2_OFFSET + LZMA_PROB_IS_REP2_LEN) |
1926 | #define LZMA_PROB_DIST_SLOT_OFFSET \ |
1927 | (LZMA_PROB_IS_REP0_LONG_OFFSET + LZMA_PROB_IS_REP0_LONG_LEN) |
1928 | #define LZMA_PROB_DIST_SPECIAL_OFFSET \ |
1929 | (LZMA_PROB_DIST_SLOT_OFFSET + LZMA_PROB_DIST_SLOT_LEN) |
1930 | #define LZMA_PROB_DIST_ALIGN_OFFSET \ |
1931 | (LZMA_PROB_DIST_SPECIAL_OFFSET + LZMA_PROB_DIST_SPECIAL_LEN) |
1932 | #define LZMA_PROB_MATCH_LEN_CHOICE_OFFSET \ |
1933 | (LZMA_PROB_DIST_ALIGN_OFFSET + LZMA_PROB_DIST_ALIGN_LEN) |
1934 | #define LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET \ |
1935 | (LZMA_PROB_MATCH_LEN_CHOICE_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE_LEN) |
1936 | #define LZMA_PROB_MATCH_LEN_LOW_OFFSET \ |
1937 | (LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE2_LEN) |
1938 | #define LZMA_PROB_MATCH_LEN_MID_OFFSET \ |
1939 | (LZMA_PROB_MATCH_LEN_LOW_OFFSET + LZMA_PROB_MATCH_LEN_LOW_LEN) |
1940 | #define LZMA_PROB_MATCH_LEN_HIGH_OFFSET \ |
1941 | (LZMA_PROB_MATCH_LEN_MID_OFFSET + LZMA_PROB_MATCH_LEN_MID_LEN) |
1942 | #define LZMA_PROB_REP_LEN_CHOICE_OFFSET \ |
1943 | (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + LZMA_PROB_MATCH_LEN_HIGH_LEN) |
1944 | #define LZMA_PROB_REP_LEN_CHOICE2_OFFSET \ |
1945 | (LZMA_PROB_REP_LEN_CHOICE_OFFSET + LZMA_PROB_REP_LEN_CHOICE_LEN) |
1946 | #define LZMA_PROB_REP_LEN_LOW_OFFSET \ |
1947 | (LZMA_PROB_REP_LEN_CHOICE2_OFFSET + LZMA_PROB_REP_LEN_CHOICE2_LEN) |
1948 | #define LZMA_PROB_REP_LEN_MID_OFFSET \ |
1949 | (LZMA_PROB_REP_LEN_LOW_OFFSET + LZMA_PROB_REP_LEN_LOW_LEN) |
1950 | #define LZMA_PROB_REP_LEN_HIGH_OFFSET \ |
1951 | (LZMA_PROB_REP_LEN_MID_OFFSET + LZMA_PROB_REP_LEN_MID_LEN) |
1952 | #define LZMA_PROB_LITERAL_OFFSET \ |
1953 | (LZMA_PROB_REP_LEN_HIGH_OFFSET + LZMA_PROB_REP_LEN_HIGH_LEN) |
1954 | |
1955 | #define LZMA_PROB_TOTAL_COUNT (LZMA_PROB_LITERAL_OFFSET + LZMA_PROB_LITERAL_LEN) |
1956 | |
1957 | #if LZMA_PROB_TOTAL_COUNT != 1846 + (1 << 4) * 0x300 |
1958 | #error Wrong number of LZMA probabilities |
1959 | #endif |
1960 | |
1961 | #define LZMA_IS_MATCH(state, pos) \ |
1962 | (LZMA_PROB_IS_MATCH_OFFSET + (state)*LZMA_POS_STATES + (pos)) |
1963 | #define LZMA_IS_REP(state) (LZMA_PROB_IS_REP_OFFSET + (state)) |
1964 | #define LZMA_IS_REP0(state) (LZMA_PROB_IS_REP0_OFFSET + (state)) |
1965 | #define LZMA_IS_REP1(state) (LZMA_PROB_IS_REP1_OFFSET + (state)) |
1966 | #define LZMA_IS_REP2(state) (LZMA_PROB_IS_REP2_OFFSET + (state)) |
1967 | #define LZMA_IS_REP0_LONG(state, pos) \ |
1968 | (LZMA_PROB_IS_REP0_LONG_OFFSET + (state)*LZMA_POS_STATES + (pos)) |
1969 | #define LZMA_DIST_SLOT(dist, slot) \ |
1970 | (LZMA_PROB_DIST_SLOT_OFFSET + (dist)*LZMA_DIST_SLOTS + (slot)) |
1971 | #define LZMA_DIST_SPECIAL(dist) (LZMA_PROB_DIST_SPECIAL_OFFSET + (dist)) |
1972 | #define LZMA_DIST_ALIGN(dist) (LZMA_PROB_DIST_ALIGN_OFFSET + (dist)) |
1973 | #define LZMA_MATCH_LEN_CHOICE LZMA_PROB_MATCH_LEN_CHOICE_OFFSET |
1974 | #define LZMA_MATCH_LEN_CHOICE2 LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET |
1975 | #define LZMA_MATCH_LEN_LOW(pos, sym) \ |
1976 | (LZMA_PROB_MATCH_LEN_LOW_OFFSET + (pos)*LZMA_LEN_LOW_SYMBOLS + (sym)) |
1977 | #define LZMA_MATCH_LEN_MID(pos, sym) \ |
1978 | (LZMA_PROB_MATCH_LEN_MID_OFFSET + (pos)*LZMA_LEN_MID_SYMBOLS + (sym)) |
1979 | #define LZMA_MATCH_LEN_HIGH(sym) (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + (sym)) |
1980 | #define LZMA_REP_LEN_CHOICE LZMA_PROB_REP_LEN_CHOICE_OFFSET |
1981 | #define LZMA_REP_LEN_CHOICE2 LZMA_PROB_REP_LEN_CHOICE2_OFFSET |
1982 | #define LZMA_REP_LEN_LOW(pos, sym) \ |
1983 | (LZMA_PROB_REP_LEN_LOW_OFFSET + (pos)*LZMA_LEN_LOW_SYMBOLS + (sym)) |
1984 | #define LZMA_REP_LEN_MID(pos, sym) \ |
1985 | (LZMA_PROB_REP_LEN_MID_OFFSET + (pos)*LZMA_LEN_MID_SYMBOLS + (sym)) |
1986 | #define LZMA_REP_LEN_HIGH(sym) (LZMA_PROB_REP_LEN_HIGH_OFFSET + (sym)) |
1987 | #define LZMA_LITERAL(code, size) \ |
1988 | (LZMA_PROB_LITERAL_OFFSET + (code)*LZMA_LITERAL_CODER_SIZE + (size)) |
1989 | |
1990 | static int elf_lzma_varint(const unsigned char *compressed, |
1991 | size_t compressed_size, size_t *poffset, |
1992 | uint64_t *val) { |
1993 | size_t off; |
1994 | int i; |
1995 | uint64_t v; |
1996 | unsigned char b; |
1997 | |
1998 | off = *poffset; |
1999 | i = 0; |
2000 | v = 0; |
2001 | while (1) { |
2002 | if (unlikely(off >= compressed_size)) { |
2003 | elf_uncompress_failed(); |
2004 | return 0; |
2005 | } |
2006 | b = compressed[off]; |
2007 | v |= (b & 0x7f) << (i * 7); |
2008 | ++off; |
2009 | if ((b & 0x80) == 0) { |
2010 | *poffset = off; |
2011 | *val = v; |
2012 | return 1; |
2013 | } |
2014 | ++i; |
2015 | if (unlikely(i >= 9)) { |
2016 | elf_uncompress_failed(); |
2017 | return 0; |
2018 | } |
2019 | } |
2020 | } |
2021 | |
2022 | static void elf_lzma_range_normalize(const unsigned char *compressed, |
2023 | size_t compressed_size, size_t *poffset, |
2024 | uint32_t *prange, uint32_t *pcode) { |
2025 | if (*prange < (1U << 24)) { |
2026 | if (unlikely(*poffset >= compressed_size)) { |
2027 | elf_uncompress_failed(); |
2028 | return; |
2029 | } |
2030 | *prange <<= 8; |
2031 | *pcode <<= 8; |
2032 | *pcode += compressed[*poffset]; |
2033 | ++*poffset; |
2034 | } |
2035 | } |
2036 | |
2037 | static int elf_lzma_bit(const unsigned char *compressed, size_t compressed_size, |
2038 | uint16_t *prob, size_t *poffset, uint32_t *prange, |
2039 | uint32_t *pcode) { |
2040 | uint32_t bound; |
2041 | |
2042 | elf_lzma_range_normalize(compressed, compressed_size, poffset, prange, pcode); |
2043 | bound = (*prange >> 11) * (uint32_t)*prob; |
2044 | if (*pcode < bound) { |
2045 | *prange = bound; |
2046 | *prob += ((1U << 11) - *prob) >> 5; |
2047 | return 0; |
2048 | } else { |
2049 | *prange -= bound; |
2050 | *pcode -= bound; |
2051 | *prob -= *prob >> 5; |
2052 | return 1; |
2053 | } |
2054 | } |
2055 | |
2056 | static uint32_t elf_lzma_integer(const unsigned char *compressed, |
2057 | size_t compressed_size, uint16_t *probs, |
2058 | uint32_t bits, size_t *poffset, |
2059 | uint32_t *prange, uint32_t *pcode) { |
2060 | uint32_t sym; |
2061 | uint32_t i; |
2062 | |
2063 | sym = 1; |
2064 | for (i = 0; i < bits; i++) { |
2065 | int bit; |
2066 | |
2067 | bit = elf_lzma_bit(compressed, compressed_size, probs + sym, poffset, |
2068 | prange, pcode); |
2069 | sym <<= 1; |
2070 | sym += bit; |
2071 | } |
2072 | return sym - (1 << bits); |
2073 | } |
2074 | |
2075 | static uint32_t elf_lzma_reverse_integer(const unsigned char *compressed, |
2076 | size_t compressed_size, |
2077 | uint16_t *probs, uint32_t bits, |
2078 | size_t *poffset, uint32_t *prange, |
2079 | uint32_t *pcode) { |
2080 | uint32_t sym; |
2081 | uint32_t val; |
2082 | uint32_t i; |
2083 | |
2084 | sym = 1; |
2085 | val = 0; |
2086 | for (i = 0; i < bits; i++) { |
2087 | int bit; |
2088 | |
2089 | bit = elf_lzma_bit(compressed, compressed_size, probs + sym, poffset, |
2090 | prange, pcode); |
2091 | sym <<= 1; |
2092 | sym += bit; |
2093 | val += bit << i; |
2094 | } |
2095 | return val; |
2096 | } |
2097 | |
2098 | static uint32_t elf_lzma_len(const unsigned char *compressed, |
2099 | size_t compressed_size, uint16_t *probs, |
2100 | int is_rep, unsigned int pos_state, |
2101 | size_t *poffset, uint32_t *prange, |
2102 | uint32_t *pcode) { |
2103 | uint16_t *probs_choice; |
2104 | uint16_t *probs_sym; |
2105 | uint32_t bits; |
2106 | uint32_t len; |
2107 | |
2108 | probs_choice = probs + (is_rep ? LZMA_REP_LEN_CHOICE : LZMA_MATCH_LEN_CHOICE); |
2109 | if (elf_lzma_bit(compressed, compressed_size, probs_choice, poffset, prange, |
2110 | pcode)) { |
2111 | probs_choice = |
2112 | probs + (is_rep ? LZMA_REP_LEN_CHOICE2 : LZMA_MATCH_LEN_CHOICE2); |
2113 | if (elf_lzma_bit(compressed, compressed_size, probs_choice, poffset, prange, |
2114 | pcode)) { |
2115 | probs_sym = |
2116 | probs + (is_rep ? LZMA_REP_LEN_HIGH(0) : LZMA_MATCH_LEN_HIGH(0)); |
2117 | bits = 8; |
2118 | len = 2 + 8 + 8; |
2119 | } else { |
2120 | probs_sym = probs + (is_rep ? LZMA_REP_LEN_MID(pos_state, 0) |
2121 | : LZMA_MATCH_LEN_MID(pos_state, 0)); |
2122 | bits = 3; |
2123 | len = 2 + 8; |
2124 | } |
2125 | } else { |
2126 | probs_sym = probs + (is_rep ? LZMA_REP_LEN_LOW(pos_state, 0) |
2127 | : LZMA_MATCH_LEN_LOW(pos_state, 0)); |
2128 | bits = 3; |
2129 | len = 2; |
2130 | } |
2131 | |
2132 | len += elf_lzma_integer(compressed, compressed_size, probs_sym, bits, poffset, |
2133 | prange, pcode); |
2134 | return len; |
2135 | } |
2136 | |
2137 | static int elf_uncompress_lzma_block(const unsigned char *compressed, |
2138 | size_t compressed_size, |
2139 | unsigned char check, uint16_t *probs, |
2140 | unsigned char *uncompressed, |
2141 | size_t uncompressed_size, |
2142 | size_t *poffset) { |
2143 | size_t off; |
2144 | size_t block_header_offset; |
2145 | size_t block_header_size; |
2146 | unsigned char block_flags; |
2147 | uint64_t header_compressed_size; |
2148 | uint64_t header_uncompressed_size; |
2149 | unsigned char lzma2_properties; |
2150 | uint32_t computed_crc; |
2151 | uint32_t stream_crc; |
2152 | size_t uncompressed_offset; |
2153 | size_t dict_start_offset; |
2154 | unsigned int lc; |
2155 | unsigned int lp; |
2156 | unsigned int pb; |
2157 | uint32_t range; |
2158 | uint32_t code; |
2159 | uint32_t lstate; |
2160 | uint32_t dist[4]; |
2161 | |
2162 | off = *poffset; |
2163 | block_header_offset = off; |
2164 | |
2165 | if (unlikely(off >= compressed_size)) { |
2166 | elf_uncompress_failed(); |
2167 | return 0; |
2168 | } |
2169 | block_header_size = (compressed[off] + 1) * 4; |
2170 | if (unlikely(off + block_header_size > compressed_size)) { |
2171 | elf_uncompress_failed(); |
2172 | return 0; |
2173 | } |
2174 | |
2175 | block_flags = compressed[off + 1]; |
2176 | if (unlikely((block_flags & 0x3c) != 0)) { |
2177 | elf_uncompress_failed(); |
2178 | return 0; |
2179 | } |
2180 | |
2181 | off += 2; |
2182 | |
2183 | header_compressed_size = 0; |
2184 | if ((block_flags & 0x40) != 0) { |
2185 | *poffset = off; |
2186 | if (!elf_lzma_varint(compressed, compressed_size, poffset, |
2187 | &header_compressed_size)) |
2188 | return 0; |
2189 | off = *poffset; |
2190 | } |
2191 | |
2192 | header_uncompressed_size = 0; |
2193 | if ((block_flags & 0x80) != 0) { |
2194 | *poffset = off; |
2195 | if (!elf_lzma_varint(compressed, compressed_size, poffset, |
2196 | &header_uncompressed_size)) |
2197 | return 0; |
2198 | off = *poffset; |
2199 | } |
2200 | |
2201 | if (unlikely((block_flags & 0x3) != 0)) { |
2202 | elf_uncompress_failed(); |
2203 | return 0; |
2204 | } |
2205 | |
2206 | if (unlikely(off + 2 >= block_header_offset + block_header_size)) { |
2207 | elf_uncompress_failed(); |
2208 | return 0; |
2209 | } |
2210 | |
2211 | if (unlikely(compressed[off] != 0x21)) { |
2212 | elf_uncompress_failed(); |
2213 | return 0; |
2214 | } |
2215 | ++off; |
2216 | |
2217 | if (unlikely(compressed[off] != 1)) { |
2218 | elf_uncompress_failed(); |
2219 | return 0; |
2220 | } |
2221 | ++off; |
2222 | |
2223 | lzma2_properties = compressed[off]; |
2224 | ++off; |
2225 | |
2226 | if (unlikely(lzma2_properties > 40)) { |
2227 | elf_uncompress_failed(); |
2228 | return 0; |
2229 | } |
2230 | |
2231 | if (unlikely(off + 4 > compressed_size)) { |
2232 | elf_uncompress_failed(); |
2233 | return 0; |
2234 | } |
2235 | |
2236 | off = (off + 3) & ~(size_t)3; |
2237 | |
2238 | if (unlikely(off + 4 > compressed_size)) { |
2239 | elf_uncompress_failed(); |
2240 | return 0; |
2241 | } |
2242 | |
2243 | computed_crc = |
2244 | elf_crc32(0, compressed + block_header_offset, block_header_size - 4); |
2245 | stream_crc = (compressed[off] | (compressed[off + 1] << 8) | |
2246 | (compressed[off + 2] << 16) | (compressed[off + 3] << 24)); |
2247 | if (unlikely(computed_crc != stream_crc)) { |
2248 | elf_uncompress_failed(); |
2249 | return 0; |
2250 | } |
2251 | off += 4; |
2252 | |
2253 | uncompressed_offset = 0; |
2254 | dict_start_offset = 0; |
2255 | lc = 0; |
2256 | lp = 0; |
2257 | pb = 0; |
2258 | lstate = 0; |
2259 | while (off < compressed_size) { |
2260 | unsigned char control; |
2261 | |
2262 | range = 0xffffffff; |
2263 | code = 0; |
2264 | |
2265 | control = compressed[off]; |
2266 | ++off; |
2267 | if (unlikely(control == 0)) { |
2268 | break; |
2269 | } |
2270 | |
2271 | if (control == 1 || control >= 0xe0) { |
2272 | dict_start_offset = uncompressed_offset; |
2273 | } |
2274 | |
2275 | if (control < 0x80) { |
2276 | size_t chunk_size; |
2277 | |
2278 | if (unlikely(control > 2)) { |
2279 | elf_uncompress_failed(); |
2280 | return 0; |
2281 | } |
2282 | |
2283 | if (unlikely(off + 2 > compressed_size)) { |
2284 | elf_uncompress_failed(); |
2285 | return 0; |
2286 | } |
2287 | |
2288 | chunk_size = compressed[off] << 8; |
2289 | chunk_size += compressed[off + 1]; |
2290 | ++chunk_size; |
2291 | |
2292 | off += 2; |
2293 | |
2294 | if (unlikely(off + chunk_size > compressed_size)) { |
2295 | elf_uncompress_failed(); |
2296 | return 0; |
2297 | } |
2298 | if (unlikely(uncompressed_offset + chunk_size > uncompressed_size)) { |
2299 | elf_uncompress_failed(); |
2300 | return 0; |
2301 | } |
2302 | |
2303 | memcpy(uncompressed + uncompressed_offset, compressed + off, chunk_size); |
2304 | uncompressed_offset += chunk_size; |
2305 | off += chunk_size; |
2306 | } else { |
2307 | size_t uncompressed_chunk_start; |
2308 | size_t uncompressed_chunk_size; |
2309 | size_t compressed_chunk_size; |
2310 | size_t limit; |
2311 | |
2312 | if (unlikely(off + 4 >= compressed_size)) { |
2313 | elf_uncompress_failed(); |
2314 | return 0; |
2315 | } |
2316 | |
2317 | uncompressed_chunk_start = uncompressed_offset; |
2318 | |
2319 | uncompressed_chunk_size = (control & 0x1f) << 16; |
2320 | uncompressed_chunk_size += compressed[off] << 8; |
2321 | uncompressed_chunk_size += compressed[off + 1]; |
2322 | ++uncompressed_chunk_size; |
2323 | |
2324 | compressed_chunk_size = compressed[off + 2] << 8; |
2325 | compressed_chunk_size += compressed[off + 3]; |
2326 | ++compressed_chunk_size; |
2327 | |
2328 | off += 4; |
2329 | |
2330 | if (control >= 0xc0) { |
2331 | unsigned char props; |
2332 | |
2333 | if (unlikely(off >= compressed_size)) { |
2334 | elf_uncompress_failed(); |
2335 | return 0; |
2336 | } |
2337 | props = compressed[off]; |
2338 | ++off; |
2339 | if (unlikely(props > (4 * 5 + 4) * 9 + 8)) { |
2340 | elf_uncompress_failed(); |
2341 | return 0; |
2342 | } |
2343 | pb = 0; |
2344 | while (props >= 9 * 5) { |
2345 | props -= 9 * 5; |
2346 | ++pb; |
2347 | } |
2348 | lp = 0; |
2349 | while (props > 9) { |
2350 | props -= 9; |
2351 | ++lp; |
2352 | } |
2353 | lc = props; |
2354 | if (unlikely(lc + lp > 4)) { |
2355 | elf_uncompress_failed(); |
2356 | return 0; |
2357 | } |
2358 | } |
2359 | |
2360 | if (control >= 0xa0) { |
2361 | size_t i; |
2362 | |
2363 | lstate = 0; |
2364 | memset(&dist, 0, sizeof dist); |
2365 | for (i = 0; i < LZMA_PROB_TOTAL_COUNT; i++) probs[i] = 1 << 10; |
2366 | range = 0xffffffff; |
2367 | code = 0; |
2368 | } |
2369 | |
2370 | if (unlikely(off + 5 > compressed_size)) { |
2371 | elf_uncompress_failed(); |
2372 | return 0; |
2373 | } |
2374 | |
2375 | code = ((compressed[off + 1] << 24) + (compressed[off + 2] << 16) + |
2376 | (compressed[off + 3] << 8) + compressed[off + 4]); |
2377 | off += 5; |
2378 | |
2379 | limit = off + compressed_chunk_size; |
2380 | *poffset = off; |
2381 | while (*poffset < limit) { |
2382 | unsigned int pos_state; |
2383 | |
2384 | if (unlikely(uncompressed_offset == |
2385 | (uncompressed_chunk_start + uncompressed_chunk_size))) { |
2386 | break; |
2387 | } |
2388 | |
2389 | pos_state = |
2390 | ((uncompressed_offset - dict_start_offset) & ((1 << pb) - 1)); |
2391 | |
2392 | if (elf_lzma_bit(compressed, compressed_size, |
2393 | probs + LZMA_IS_MATCH(lstate, pos_state), poffset, |
2394 | &range, &code)) { |
2395 | uint32_t len; |
2396 | |
2397 | if (elf_lzma_bit(compressed, compressed_size, |
2398 | probs + LZMA_IS_REP(lstate), poffset, &range, |
2399 | &code)) { |
2400 | int short_rep; |
2401 | uint32_t next_dist; |
2402 | |
2403 | short_rep = 0; |
2404 | if (elf_lzma_bit(compressed, compressed_size, |
2405 | probs + LZMA_IS_REP0(lstate), poffset, &range, |
2406 | &code)) { |
2407 | if (elf_lzma_bit(compressed, compressed_size, |
2408 | probs + LZMA_IS_REP1(lstate), poffset, &range, |
2409 | &code)) { |
2410 | if (elf_lzma_bit(compressed, compressed_size, |
2411 | probs + LZMA_IS_REP2(lstate), poffset, &range, |
2412 | &code)) { |
2413 | next_dist = dist[3]; |
2414 | dist[3] = dist[2]; |
2415 | } else { |
2416 | next_dist = dist[2]; |
2417 | } |
2418 | dist[2] = dist[1]; |
2419 | } else { |
2420 | next_dist = dist[1]; |
2421 | } |
2422 | |
2423 | dist[1] = dist[0]; |
2424 | dist[0] = next_dist; |
2425 | } else { |
2426 | if (!elf_lzma_bit(compressed, compressed_size, |
2427 | (probs + LZMA_IS_REP0_LONG(lstate, pos_state)), |
2428 | poffset, &range, &code)) |
2429 | short_rep = 1; |
2430 | } |
2431 | |
2432 | if (lstate < 7) |
2433 | lstate = short_rep ? 9 : 8; |
2434 | else |
2435 | lstate = 11; |
2436 | |
2437 | if (short_rep) |
2438 | len = 1; |
2439 | else |
2440 | len = elf_lzma_len(compressed, compressed_size, probs, 1, |
2441 | pos_state, poffset, &range, &code); |
2442 | } else { |
2443 | uint32_t dist_state; |
2444 | uint32_t dist_slot; |
2445 | uint16_t *probs_dist; |
2446 | |
2447 | if (lstate < 7) |
2448 | lstate = 7; |
2449 | else |
2450 | lstate = 10; |
2451 | dist[3] = dist[2]; |
2452 | dist[2] = dist[1]; |
2453 | dist[1] = dist[0]; |
2454 | len = elf_lzma_len(compressed, compressed_size, probs, 0, pos_state, |
2455 | poffset, &range, &code); |
2456 | |
2457 | if (len < 4 + 2) |
2458 | dist_state = len - 2; |
2459 | else |
2460 | dist_state = 3; |
2461 | probs_dist = probs + LZMA_DIST_SLOT(dist_state, 0); |
2462 | dist_slot = elf_lzma_integer(compressed, compressed_size, |
2463 | probs_dist, 6, poffset, &range, &code); |
2464 | if (dist_slot < LZMA_DIST_MODEL_START) |
2465 | dist[0] = dist_slot; |
2466 | else { |
2467 | uint32_t limit; |
2468 | |
2469 | limit = (dist_slot >> 1) - 1; |
2470 | dist[0] = 2 + (dist_slot & 1); |
2471 | if (dist_slot < LZMA_DIST_MODEL_END) { |
2472 | dist[0] <<= limit; |
2473 | probs_dist = |
2474 | (probs + LZMA_DIST_SPECIAL(dist[0] - dist_slot - 1)); |
2475 | dist[0] += elf_lzma_reverse_integer(compressed, compressed_size, |
2476 | probs_dist, limit, poffset, |
2477 | &range, &code); |
2478 | } else { |
2479 | uint32_t dist0; |
2480 | uint32_t i; |
2481 | |
2482 | dist0 = dist[0]; |
2483 | for (i = 0; i < limit - 4; i++) { |
2484 | uint32_t mask; |
2485 | |
2486 | elf_lzma_range_normalize(compressed, compressed_size, poffset, |
2487 | &range, &code); |
2488 | range >>= 1; |
2489 | code -= range; |
2490 | mask = -(code >> 31); |
2491 | code += range & mask; |
2492 | dist0 <<= 1; |
2493 | dist0 += mask + 1; |
2494 | } |
2495 | dist0 <<= 4; |
2496 | probs_dist = probs + LZMA_DIST_ALIGN(0); |
2497 | dist0 += elf_lzma_reverse_integer(compressed, compressed_size, |
2498 | probs_dist, 4, poffset, |
2499 | &range, &code); |
2500 | dist[0] = dist0; |
2501 | } |
2502 | } |
2503 | } |
2504 | |
2505 | if (unlikely(uncompressed_offset - dict_start_offset < dist[0] + 1)) { |
2506 | elf_uncompress_failed(); |
2507 | return 0; |
2508 | } |
2509 | if (unlikely(uncompressed_offset + len > uncompressed_size)) { |
2510 | elf_uncompress_failed(); |
2511 | return 0; |
2512 | } |
2513 | |
2514 | if (dist[0] == 0) { |
2515 | memset(uncompressed + uncompressed_offset, |
2516 | uncompressed[uncompressed_offset - 1], len); |
2517 | uncompressed_offset += len; |
2518 | } else if (dist[0] + 1 >= len) { |
2519 | memcpy(uncompressed + uncompressed_offset, |
2520 | uncompressed + uncompressed_offset - dist[0] - 1, len); |
2521 | uncompressed_offset += len; |
2522 | } else { |
2523 | while (len > 0) { |
2524 | uint32_t copy; |
2525 | |
2526 | copy = len < dist[0] + 1 ? len : dist[0] + 1; |
2527 | memcpy(uncompressed + uncompressed_offset, |
2528 | (uncompressed + uncompressed_offset - dist[0] - 1), copy); |
2529 | len -= copy; |
2530 | uncompressed_offset += copy; |
2531 | } |
2532 | } |
2533 | } else { |
2534 | unsigned char prev; |
2535 | unsigned char low; |
2536 | size_t high; |
2537 | uint16_t *lit_probs; |
2538 | unsigned int sym; |
2539 | |
2540 | if (uncompressed_offset > 0) |
2541 | prev = uncompressed[uncompressed_offset - 1]; |
2542 | else |
2543 | prev = 0; |
2544 | low = prev >> (8 - lc); |
2545 | high = (((uncompressed_offset - dict_start_offset) & ((1 << lp) - 1)) |
2546 | << lc); |
2547 | lit_probs = probs + LZMA_LITERAL(low + high, 0); |
2548 | if (lstate < 7) |
2549 | sym = elf_lzma_integer(compressed, compressed_size, lit_probs, 8, |
2550 | poffset, &range, &code); |
2551 | else { |
2552 | unsigned int match; |
2553 | unsigned int bit; |
2554 | unsigned int match_bit; |
2555 | unsigned int idx; |
2556 | |
2557 | sym = 1; |
2558 | if (uncompressed_offset >= dist[0] + 1) |
2559 | match = uncompressed[uncompressed_offset - dist[0] - 1]; |
2560 | else |
2561 | match = 0; |
2562 | match <<= 1; |
2563 | bit = 0x100; |
2564 | do { |
2565 | match_bit = match & bit; |
2566 | match <<= 1; |
2567 | idx = bit + match_bit + sym; |
2568 | sym <<= 1; |
2569 | if (elf_lzma_bit(compressed, compressed_size, lit_probs + idx, |
2570 | poffset, &range, &code)) { |
2571 | ++sym; |
2572 | bit &= match_bit; |
2573 | } else { |
2574 | bit &= ~match_bit; |
2575 | } |
2576 | } while (sym < 0x100); |
2577 | } |
2578 | |
2579 | if (unlikely(uncompressed_offset >= uncompressed_size)) { |
2580 | elf_uncompress_failed(); |
2581 | return 0; |
2582 | } |
2583 | |
2584 | uncompressed[uncompressed_offset] = (unsigned char)sym; |
2585 | ++uncompressed_offset; |
2586 | if (lstate <= 3) |
2587 | lstate = 0; |
2588 | else if (lstate <= 9) |
2589 | lstate -= 3; |
2590 | else |
2591 | lstate -= 6; |
2592 | } |
2593 | } |
2594 | |
2595 | elf_lzma_range_normalize(compressed, compressed_size, poffset, &range, |
2596 | &code); |
2597 | |
2598 | off = *poffset; |
2599 | } |
2600 | } |
2601 | |
2602 | off = (off + 3) & ~(size_t)3; |
2603 | if (unlikely(off > compressed_size)) { |
2604 | elf_uncompress_failed(); |
2605 | return 0; |
2606 | } |
2607 | |
2608 | switch (check) { |
2609 | case 0: |
2610 | |
2611 | break; |
2612 | |
2613 | case 1: |
2614 | |
2615 | if (unlikely(off + 4 > compressed_size)) { |
2616 | elf_uncompress_failed(); |
2617 | return 0; |
2618 | } |
2619 | computed_crc = elf_crc32(0, uncompressed, uncompressed_offset); |
2620 | stream_crc = (compressed[off] | (compressed[off + 1] << 8) | |
2621 | (compressed[off + 2] << 16) | (compressed[off + 3] << 24)); |
2622 | if (computed_crc != stream_crc) { |
2623 | elf_uncompress_failed(); |
2624 | return 0; |
2625 | } |
2626 | off += 4; |
2627 | break; |
2628 | |
2629 | case 4: |
2630 | |
2631 | if (unlikely(off + 8 > compressed_size)) { |
2632 | elf_uncompress_failed(); |
2633 | return 0; |
2634 | } |
2635 | off += 8; |
2636 | break; |
2637 | |
2638 | case 10: |
2639 | |
2640 | if (unlikely(off + 32 > compressed_size)) { |
2641 | elf_uncompress_failed(); |
2642 | return 0; |
2643 | } |
2644 | off += 32; |
2645 | break; |
2646 | |
2647 | default: |
2648 | elf_uncompress_failed(); |
2649 | return 0; |
2650 | } |
2651 | |
2652 | *poffset = off; |
2653 | |
2654 | return 1; |
2655 | } |
2656 | |
2657 | static int elf_uncompress_lzma(struct backtrace_state *state, |
2658 | const unsigned char *compressed, |
2659 | size_t compressed_size, |
2660 | backtrace_error_callback error_callback, |
2661 | void *data, unsigned char **uncompressed, |
2662 | size_t *uncompressed_size) { |
2663 | size_t header_size; |
2664 | size_t footer_size; |
2665 | unsigned char check; |
2666 | uint32_t computed_crc; |
2667 | uint32_t stream_crc; |
2668 | size_t offset; |
2669 | size_t index_size; |
2670 | size_t footer_offset; |
2671 | size_t index_offset; |
2672 | uint64_t index_compressed_size; |
2673 | uint64_t index_uncompressed_size; |
2674 | unsigned char *mem; |
2675 | uint16_t *probs; |
2676 | size_t compressed_block_size; |
2677 | |
2678 | header_size = 12; |
2679 | footer_size = 12; |
2680 | if (unlikely(compressed_size < header_size + footer_size)) { |
2681 | elf_uncompress_failed(); |
2682 | return 0; |
2683 | } |
2684 | |
2685 | if (unlikely(memcmp(compressed, |
2686 | "\375" |
2687 | "7zXZ\0", |
2688 | 6) != 0)) { |
2689 | elf_uncompress_failed(); |
2690 | return 0; |
2691 | } |
2692 | |
2693 | if (unlikely(compressed[6] != 0)) { |
2694 | elf_uncompress_failed(); |
2695 | return 0; |
2696 | } |
2697 | check = compressed[7]; |
2698 | if (unlikely((check & 0xf8) != 0)) { |
2699 | elf_uncompress_failed(); |
2700 | return 0; |
2701 | } |
2702 | |
2703 | computed_crc = elf_crc32(0, compressed + 6, 2); |
2704 | stream_crc = (compressed[8] | (compressed[9] << 8) | (compressed[10] << 16) | |
2705 | (compressed[11] << 24)); |
2706 | if (unlikely(computed_crc != stream_crc)) { |
2707 | elf_uncompress_failed(); |
2708 | return 0; |
2709 | } |
2710 | |
2711 | offset = compressed_size; |
2712 | if (unlikely(memcmp(compressed + offset - 2, "YZ", 2) != 0)) { |
2713 | elf_uncompress_failed(); |
2714 | return 0; |
2715 | } |
2716 | offset -= 2; |
2717 | |
2718 | if (unlikely(compressed[offset - 2] != 0 || |
2719 | compressed[offset - 1] != check)) { |
2720 | elf_uncompress_failed(); |
2721 | return 0; |
2722 | } |
2723 | offset -= 2; |
2724 | |
2725 | index_size = |
2726 | (compressed[offset - 4] | (compressed[offset - 3] << 8) | |
2727 | (compressed[offset - 2] << 16) | (compressed[offset - 1] << 24)); |
2728 | index_size = (index_size + 1) * 4; |
2729 | offset -= 4; |
2730 | |
2731 | computed_crc = elf_crc32(0, compressed + offset, 6); |
2732 | stream_crc = |
2733 | (compressed[offset - 4] | (compressed[offset - 3] << 8) | |
2734 | (compressed[offset - 2] << 16) | (compressed[offset - 1] << 24)); |
2735 | if (unlikely(computed_crc != stream_crc)) { |
2736 | elf_uncompress_failed(); |
2737 | return 0; |
2738 | } |
2739 | offset -= 4; |
2740 | |
2741 | if (unlikely(offset < index_size + header_size)) { |
2742 | elf_uncompress_failed(); |
2743 | return 0; |
2744 | } |
2745 | |
2746 | footer_offset = offset; |
2747 | offset -= index_size; |
2748 | index_offset = offset; |
2749 | |
2750 | if (unlikely(compressed[offset] != 0)) { |
2751 | elf_uncompress_failed(); |
2752 | return 0; |
2753 | } |
2754 | ++offset; |
2755 | |
2756 | if (unlikely(compressed[offset] == 0)) { |
2757 | *uncompressed = NULL; |
2758 | *uncompressed_size = 0; |
2759 | return 1; |
2760 | } |
2761 | if (unlikely(compressed[offset] != 1)) { |
2762 | elf_uncompress_failed(); |
2763 | return 0; |
2764 | } |
2765 | ++offset; |
2766 | |
2767 | if (!elf_lzma_varint(compressed, compressed_size, &offset, |
2768 | &index_compressed_size)) |
2769 | return 0; |
2770 | if (!elf_lzma_varint(compressed, compressed_size, &offset, |
2771 | &index_uncompressed_size)) |
2772 | return 0; |
2773 | |
2774 | offset = (offset + 3) & ~(size_t)3; |
2775 | |
2776 | computed_crc = elf_crc32(0, compressed + index_offset, offset - index_offset); |
2777 | stream_crc = |
2778 | (compressed[offset] | (compressed[offset + 1] << 8) | |
2779 | (compressed[offset + 2] << 16) | (compressed[offset + 3] << 24)); |
2780 | if (unlikely(computed_crc != stream_crc)) { |
2781 | elf_uncompress_failed(); |
2782 | return 0; |
2783 | } |
2784 | offset += 4; |
2785 | |
2786 | if (unlikely(offset != footer_offset)) { |
2787 | elf_uncompress_failed(); |
2788 | return 0; |
2789 | } |
2790 | |
2791 | mem = (unsigned char *)backtrace_alloc(state, index_uncompressed_size, |
2792 | error_callback, data); |
2793 | if (unlikely(mem == NULL)) return 0; |
2794 | *uncompressed = mem; |
2795 | *uncompressed_size = index_uncompressed_size; |
2796 | |
2797 | probs = ((uint16_t *)backtrace_alloc( |
2798 | state, LZMA_PROB_TOTAL_COUNT * sizeof(uint16_t), error_callback, data)); |
2799 | if (unlikely(probs == NULL)) { |
2800 | backtrace_free(state, mem, index_uncompressed_size, error_callback, data); |
2801 | return 0; |
2802 | } |
2803 | |
2804 | offset = 12; |
2805 | if (!elf_uncompress_lzma_block(compressed, compressed_size, check, probs, mem, |
2806 | index_uncompressed_size, &offset)) { |
2807 | backtrace_free(state, mem, index_uncompressed_size, error_callback, data); |
2808 | return 0; |
2809 | } |
2810 | |
2811 | compressed_block_size = offset - 12; |
2812 | if (unlikely(compressed_block_size != |
2813 | ((index_compressed_size + 3) & ~(size_t)3))) { |
2814 | elf_uncompress_failed(); |
2815 | backtrace_free(state, mem, index_uncompressed_size, error_callback, data); |
2816 | return 0; |
2817 | } |
2818 | |
2819 | offset = (offset + 3) & ~(size_t)3; |
2820 | if (unlikely(offset != index_offset)) { |
2821 | elf_uncompress_failed(); |
2822 | backtrace_free(state, mem, index_uncompressed_size, error_callback, data); |
2823 | return 0; |
2824 | } |
2825 | |
2826 | return 1; |
2827 | } |
2828 | |
2829 | int backtrace_uncompress_lzma(struct backtrace_state *state, |
2830 | const unsigned char *compressed, |
2831 | size_t compressed_size, |
2832 | backtrace_error_callback error_callback, |
2833 | void *data, unsigned char **uncompressed, |
2834 | size_t *uncompressed_size) { |
2835 | return elf_uncompress_lzma(state, compressed, compressed_size, error_callback, |
2836 | data, uncompressed, uncompressed_size); |
2837 | } |
2838 | |
2839 | static int elf_add(struct backtrace_state *state, const char *filename, |
2840 | int descriptor, const unsigned char *memory, |
2841 | size_t memory_size, uintptr_t base_address, |
2842 | backtrace_error_callback error_callback, void *data, |
2843 | fileline *fileline_fn, int *found_sym, int *found_dwarf, |
2844 | struct dwarf_data **fileline_entry, int exe, int debuginfo, |
2845 | const char *with_buildid_data, uint32_t with_buildid_size) { |
2846 | struct elf_view ehdr_view; |
2847 | b_elf_ehdr ehdr; |
2848 | off_t shoff; |
2849 | unsigned int shnum; |
2850 | unsigned int shstrndx; |
2851 | struct elf_view shdrs_view; |
2852 | int shdrs_view_valid; |
2853 | const b_elf_shdr *shdrs; |
2854 | const b_elf_shdr *shstrhdr; |
2855 | size_t shstr_size; |
2856 | off_t shstr_off; |
2857 | struct elf_view names_view; |
2858 | int names_view_valid; |
2859 | const char *names; |
2860 | unsigned int symtab_shndx; |
2861 | unsigned int dynsym_shndx; |
2862 | unsigned int i; |
2863 | struct debug_section_info sections[DEBUG_MAX]; |
2864 | struct debug_section_info zsections[DEBUG_MAX]; |
2865 | struct elf_view symtab_view; |
2866 | int symtab_view_valid; |
2867 | struct elf_view strtab_view; |
2868 | int strtab_view_valid; |
2869 | struct elf_view buildid_view; |
2870 | int buildid_view_valid; |
2871 | const char *buildid_data; |
2872 | uint32_t buildid_size; |
2873 | struct elf_view debuglink_view; |
2874 | int debuglink_view_valid; |
2875 | const char *debuglink_name; |
2876 | uint32_t debuglink_crc; |
2877 | struct elf_view debugaltlink_view; |
2878 | int debugaltlink_view_valid; |
2879 | const char *debugaltlink_name; |
2880 | const char *debugaltlink_buildid_data; |
2881 | uint32_t debugaltlink_buildid_size; |
2882 | struct elf_view gnu_debugdata_view; |
2883 | int gnu_debugdata_view_valid; |
2884 | size_t gnu_debugdata_size; |
2885 | unsigned char *gnu_debugdata_uncompressed; |
2886 | size_t gnu_debugdata_uncompressed_size; |
2887 | off_t min_offset; |
2888 | off_t max_offset; |
2889 | off_t debug_size; |
2890 | struct elf_view debug_view; |
2891 | int debug_view_valid; |
2892 | unsigned int using_debug_view; |
2893 | uint16_t *zdebug_table; |
2894 | struct elf_view split_debug_view[DEBUG_MAX]; |
2895 | unsigned char split_debug_view_valid[DEBUG_MAX]; |
2896 | struct elf_ppc64_opd_data opd_data, *opd; |
2897 | struct dwarf_sections dwarf_sections; |
2898 | |
2899 | if (!debuginfo) { |
2900 | *found_sym = 0; |
2901 | *found_dwarf = 0; |
2902 | } |
2903 | |
2904 | shdrs_view_valid = 0; |
2905 | names_view_valid = 0; |
2906 | symtab_view_valid = 0; |
2907 | strtab_view_valid = 0; |
2908 | buildid_view_valid = 0; |
2909 | buildid_data = NULL; |
2910 | buildid_size = 0; |
2911 | debuglink_view_valid = 0; |
2912 | debuglink_name = NULL; |
2913 | debuglink_crc = 0; |
2914 | debugaltlink_view_valid = 0; |
2915 | debugaltlink_name = NULL; |
2916 | debugaltlink_buildid_data = NULL; |
2917 | debugaltlink_buildid_size = 0; |
2918 | gnu_debugdata_view_valid = 0; |
2919 | gnu_debugdata_size = 0; |
2920 | debug_view_valid = 0; |
2921 | memset(&split_debug_view_valid[0], 0, sizeof split_debug_view_valid); |
2922 | opd = NULL; |
2923 | |
2924 | if (!elf_get_view(state, descriptor, memory, memory_size, 0, sizeof ehdr, |
2925 | error_callback, data, &ehdr_view)) |
2926 | goto fail; |
2927 | |
2928 | memcpy(&ehdr, ehdr_view.view.data, sizeof ehdr); |
2929 | |
2930 | elf_release_view(state, &ehdr_view, error_callback, data); |
2931 | |
2932 | if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || |
2933 | ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3) { |
2934 | error_callback(data, "executable file is not ELF", 0); |
2935 | goto fail; |
2936 | } |
2937 | if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { |
2938 | error_callback(data, "executable file is unrecognized ELF version", 0); |
2939 | goto fail; |
2940 | } |
2941 | |
2942 | #if BACKTRACE_ELF_SIZE == 32 |
2943 | #define BACKTRACE_ELFCLASS ELFCLASS32 |
2944 | #else |
2945 | #define BACKTRACE_ELFCLASS ELFCLASS64 |
2946 | #endif |
2947 | |
2948 | if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS) { |
2949 | error_callback(data, "executable file is unexpected ELF class", 0); |
2950 | goto fail; |
2951 | } |
2952 | |
2953 | if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB && |
2954 | ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { |
2955 | error_callback(data, "executable file has unknown endianness", 0); |
2956 | goto fail; |
2957 | } |
2958 | |
2959 | if (exe && ehdr.e_type == ET_DYN) return -1; |
2960 | |
2961 | shoff = ehdr.e_shoff; |
2962 | shnum = ehdr.e_shnum; |
2963 | shstrndx = ehdr.e_shstrndx; |
2964 | |
2965 | if ((shnum == 0 || shstrndx == SHN_XINDEX) && shoff != 0) { |
2966 | struct elf_view shdr_view; |
2967 | const b_elf_shdr *shdr; |
2968 | |
2969 | if (!elf_get_view(state, descriptor, memory, memory_size, shoff, |
2970 | sizeof shdr, error_callback, data, &shdr_view)) |
2971 | goto fail; |
2972 | |
2973 | shdr = (const b_elf_shdr *)shdr_view.view.data; |
2974 | |
2975 | if (shnum == 0) shnum = shdr->sh_size; |
2976 | |
2977 | if (shstrndx == SHN_XINDEX) { |
2978 | shstrndx = shdr->sh_link; |
2979 | |
2980 | if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100) |
2981 | shstrndx -= 0x100; |
2982 | } |
2983 | |
2984 | elf_release_view(state, &shdr_view, error_callback, data); |
2985 | } |
2986 | |
2987 | if (shnum == 0 || shstrndx == 0) goto fail; |
2988 | |
2989 | if (!elf_get_view( |
2990 | state, descriptor, memory, memory_size, shoff + sizeof(b_elf_shdr), |
2991 | (shnum - 1) * sizeof(b_elf_shdr), error_callback, data, &shdrs_view)) |
2992 | goto fail; |
2993 | shdrs_view_valid = 1; |
2994 | shdrs = (const b_elf_shdr *)shdrs_view.view.data; |
2995 | |
2996 | shstrhdr = &shdrs[shstrndx - 1]; |
2997 | shstr_size = shstrhdr->sh_size; |
2998 | shstr_off = shstrhdr->sh_offset; |
2999 | |
3000 | if (!elf_get_view(state, descriptor, memory, memory_size, shstr_off, |
3001 | shstrhdr->sh_size, error_callback, data, &names_view)) |
3002 | goto fail; |
3003 | names_view_valid = 1; |
3004 | names = (const char *)names_view.view.data; |
3005 | |
3006 | symtab_shndx = 0; |
3007 | dynsym_shndx = 0; |
3008 | |
3009 | memset(sections, 0, sizeof sections); |
3010 | memset(zsections, 0, sizeof zsections); |
3011 | |
3012 | for (i = 1; i < shnum; ++i) { |
3013 | const b_elf_shdr *shdr; |
3014 | unsigned int sh_name; |
3015 | const char *name; |
3016 | int j; |
3017 | |
3018 | shdr = &shdrs[i - 1]; |
3019 | |
3020 | if (shdr->sh_type == SHT_SYMTAB) |
3021 | symtab_shndx = i; |
3022 | else if (shdr->sh_type == SHT_DYNSYM) |
3023 | dynsym_shndx = i; |
3024 | |
3025 | sh_name = shdr->sh_name; |
3026 | if (sh_name >= shstr_size) { |
3027 | error_callback(data, "ELF section name out of range", 0); |
3028 | goto fail; |
3029 | } |
3030 | |
3031 | name = names + sh_name; |
3032 | |
3033 | for (j = 0; j < (int)DEBUG_MAX; ++j) { |
3034 | if (strcmp(name, dwarf_section_names[j]) == 0) { |
3035 | sections[j].offset = shdr->sh_offset; |
3036 | sections[j].size = shdr->sh_size; |
3037 | sections[j].compressed = (shdr->sh_flags & SHF_COMPRESSED) != 0; |
3038 | break; |
3039 | } |
3040 | } |
3041 | |
3042 | if (name[0] == '.' && name[1] == 'z') { |
3043 | for (j = 0; j < (int)DEBUG_MAX; ++j) { |
3044 | if (strcmp(name + 2, dwarf_section_names[j] + 1) == 0) { |
3045 | zsections[j].offset = shdr->sh_offset; |
3046 | zsections[j].size = shdr->sh_size; |
3047 | break; |
3048 | } |
3049 | } |
3050 | } |
3051 | |
3052 | if ((!debuginfo || with_buildid_data != NULL) && !buildid_view_valid && |
3053 | strcmp(name, ".note.gnu.build-id") == 0) { |
3054 | const b_elf_note *note; |
3055 | |
3056 | if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset, |
3057 | shdr->sh_size, error_callback, data, &buildid_view)) |
3058 | goto fail; |
3059 | |
3060 | buildid_view_valid = 1; |
3061 | note = (const b_elf_note *)buildid_view.view.data; |
3062 | if (note->type == NT_GNU_BUILD_ID && note->namesz == 4 && |
3063 | strncmp(note->name, "GNU", 4) == 0 && |
3064 | shdr->sh_size <= 12 + ((note->namesz + 3) & ~3) + note->descsz) { |
3065 | buildid_data = ¬e->name[0] + ((note->namesz + 3) & ~3); |
3066 | buildid_size = note->descsz; |
3067 | } |
3068 | |
3069 | if (with_buildid_size != 0) { |
3070 | if (buildid_size != with_buildid_size) goto fail; |
3071 | |
3072 | if (memcmp(buildid_data, with_buildid_data, buildid_size) != 0) |
3073 | goto fail; |
3074 | } |
3075 | } |
3076 | |
3077 | if (!debuginfo && !debuglink_view_valid && |
3078 | strcmp(name, ".gnu_debuglink") == 0) { |
3079 | const char *debuglink_data; |
3080 | size_t crc_offset; |
3081 | |
3082 | if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset, |
3083 | shdr->sh_size, error_callback, data, &debuglink_view)) |
3084 | goto fail; |
3085 | |
3086 | debuglink_view_valid = 1; |
3087 | debuglink_data = (const char *)debuglink_view.view.data; |
3088 | crc_offset = strnlen(debuglink_data, shdr->sh_size); |
3089 | crc_offset = (crc_offset + 3) & ~3; |
3090 | if (crc_offset + 4 <= shdr->sh_size) { |
3091 | debuglink_name = debuglink_data; |
3092 | debuglink_crc = *(const uint32_t *)(debuglink_data + crc_offset); |
3093 | } |
3094 | } |
3095 | |
3096 | if (!debugaltlink_view_valid && strcmp(name, ".gnu_debugaltlink") == 0) { |
3097 | const char *debugaltlink_data; |
3098 | size_t debugaltlink_name_len; |
3099 | |
3100 | if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset, |
3101 | shdr->sh_size, error_callback, data, |
3102 | &debugaltlink_view)) |
3103 | goto fail; |
3104 | |
3105 | debugaltlink_view_valid = 1; |
3106 | debugaltlink_data = (const char *)debugaltlink_view.view.data; |
3107 | debugaltlink_name = debugaltlink_data; |
3108 | debugaltlink_name_len = strnlen(debugaltlink_data, shdr->sh_size); |
3109 | if (debugaltlink_name_len < shdr->sh_size) { |
3110 | debugaltlink_name_len += 1; |
3111 | |
3112 | debugaltlink_buildid_data = debugaltlink_data + debugaltlink_name_len; |
3113 | debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len; |
3114 | } |
3115 | } |
3116 | |
3117 | if (!gnu_debugdata_view_valid && strcmp(name, ".gnu_debugdata") == 0) { |
3118 | if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset, |
3119 | shdr->sh_size, error_callback, data, |
3120 | &gnu_debugdata_view)) |
3121 | goto fail; |
3122 | |
3123 | gnu_debugdata_size = shdr->sh_size; |
3124 | gnu_debugdata_view_valid = 1; |
3125 | } |
3126 | |
3127 | if (ehdr.e_machine == EM_PPC64 && (ehdr.e_flags & EF_PPC64_ABI) < 2 && |
3128 | shdr->sh_type == SHT_PROGBITS && strcmp(name, ".opd") == 0) { |
3129 | if (!elf_get_view(state, descriptor, memory, memory_size, shdr->sh_offset, |
3130 | shdr->sh_size, error_callback, data, &opd_data.view)) |
3131 | goto fail; |
3132 | |
3133 | opd = &opd_data; |
3134 | opd->addr = shdr->sh_addr; |
3135 | opd->data = (const char *)opd_data.view.view.data; |
3136 | opd->size = shdr->sh_size; |
3137 | } |
3138 | } |
3139 | |
3140 | if (symtab_shndx == 0) symtab_shndx = dynsym_shndx; |
3141 | if (symtab_shndx != 0 && !debuginfo) { |
3142 | const b_elf_shdr *symtab_shdr; |
3143 | unsigned int strtab_shndx; |
3144 | const b_elf_shdr *strtab_shdr; |
3145 | struct elf_syminfo_data *sdata; |
3146 | |
3147 | symtab_shdr = &shdrs[symtab_shndx - 1]; |
3148 | strtab_shndx = symtab_shdr->sh_link; |
3149 | if (strtab_shndx >= shnum) { |
3150 | error_callback(data, "ELF symbol table strtab link out of range", 0); |
3151 | goto fail; |
3152 | } |
3153 | strtab_shdr = &shdrs[strtab_shndx - 1]; |
3154 | |
3155 | if (!elf_get_view(state, descriptor, memory, memory_size, |
3156 | symtab_shdr->sh_offset, symtab_shdr->sh_size, |
3157 | error_callback, data, &symtab_view)) |
3158 | goto fail; |
3159 | symtab_view_valid = 1; |
3160 | |
3161 | if (!elf_get_view(state, descriptor, memory, memory_size, |
3162 | strtab_shdr->sh_offset, strtab_shdr->sh_size, |
3163 | error_callback, data, &strtab_view)) |
3164 | goto fail; |
3165 | strtab_view_valid = 1; |
3166 | |
3167 | sdata = ((struct elf_syminfo_data *)backtrace_alloc(state, sizeof *sdata, |
3168 | error_callback, data)); |
3169 | if (sdata == NULL) goto fail; |
3170 | |
3171 | if (!elf_initialize_syminfo(state, base_address, symtab_view.view.data, |
3172 | symtab_shdr->sh_size, strtab_view.view.data, |
3173 | strtab_shdr->sh_size, error_callback, data, |
3174 | sdata, opd)) { |
3175 | backtrace_free(state, sdata, sizeof *sdata, error_callback, data); |
3176 | goto fail; |
3177 | } |
3178 | |
3179 | elf_release_view(state, &symtab_view, error_callback, data); |
3180 | symtab_view_valid = 0; |
3181 | strtab_view_valid = 0; |
3182 | |
3183 | *found_sym = 1; |
3184 | |
3185 | elf_add_syminfo_data(state, sdata); |
3186 | } |
3187 | |
3188 | elf_release_view(state, &shdrs_view, error_callback, data); |
3189 | shdrs_view_valid = 0; |
3190 | elf_release_view(state, &names_view, error_callback, data); |
3191 | names_view_valid = 0; |
3192 | |
3193 | if (buildid_data != NULL) { |
3194 | int d; |
3195 | |
3196 | d = elf_open_debugfile_by_buildid(state, buildid_data, buildid_size, |
3197 | error_callback, data); |
3198 | if (d >= 0) { |
3199 | int ret; |
3200 | |
3201 | elf_release_view(state, &buildid_view, error_callback, data); |
3202 | if (debuglink_view_valid) |
3203 | elf_release_view(state, &debuglink_view, error_callback, data); |
3204 | if (debugaltlink_view_valid) |
3205 | elf_release_view(state, &debugaltlink_view, error_callback, data); |
3206 | ret = elf_add(state, "", d, NULL, 0, base_address, error_callback, data, |
3207 | fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL, 0); |
3208 | if (ret < 0) |
3209 | backtrace_close(d, error_callback, data); |
3210 | else if (descriptor >= 0) |
3211 | backtrace_close(descriptor, error_callback, data); |
3212 | return ret; |
3213 | } |
3214 | } |
3215 | |
3216 | if (buildid_view_valid) { |
3217 | elf_release_view(state, &buildid_view, error_callback, data); |
3218 | buildid_view_valid = 0; |
3219 | } |
3220 | |
3221 | if (opd) { |
3222 | elf_release_view(state, &opd->view, error_callback, data); |
3223 | opd = NULL; |
3224 | } |
3225 | |
3226 | if (debuglink_name != NULL) { |
3227 | int d; |
3228 | |
3229 | d = elf_open_debugfile_by_debuglink(state, filename, debuglink_name, |
3230 | debuglink_crc, error_callback, data); |
3231 | if (d >= 0) { |
3232 | int ret; |
3233 | |
3234 | elf_release_view(state, &debuglink_view, error_callback, data); |
3235 | if (debugaltlink_view_valid) |
3236 | elf_release_view(state, &debugaltlink_view, error_callback, data); |
3237 | ret = elf_add(state, "", d, NULL, 0, base_address, error_callback, data, |
3238 | fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL, 0); |
3239 | if (ret < 0) |
3240 | backtrace_close(d, error_callback, data); |
3241 | else if (descriptor >= 0) |
3242 | backtrace_close(descriptor, error_callback, data); |
3243 | return ret; |
3244 | } |
3245 | } |
3246 | |
3247 | if (debuglink_view_valid) { |
3248 | elf_release_view(state, &debuglink_view, error_callback, data); |
3249 | debuglink_view_valid = 0; |
3250 | } |
3251 | |
3252 | struct dwarf_data *fileline_altlink = NULL; |
3253 | if (debugaltlink_name != NULL) { |
3254 | int d; |
3255 | |
3256 | d = elf_open_debugfile_by_debuglink(state, filename, debugaltlink_name, 0, |
3257 | error_callback, data); |
3258 | if (d >= 0) { |
3259 | int ret; |
3260 | |
3261 | ret = |
3262 | elf_add(state, filename, d, NULL, 0, base_address, error_callback, |
3263 | data, fileline_fn, found_sym, found_dwarf, &fileline_altlink, |
3264 | 0, 1, debugaltlink_buildid_data, debugaltlink_buildid_size); |
3265 | elf_release_view(state, &debugaltlink_view, error_callback, data); |
3266 | debugaltlink_view_valid = 0; |
3267 | if (ret < 0) { |
3268 | backtrace_close(d, error_callback, data); |
3269 | return ret; |
3270 | } |
3271 | } |
3272 | } |
3273 | |
3274 | if (debugaltlink_view_valid) { |
3275 | elf_release_view(state, &debugaltlink_view, error_callback, data); |
3276 | debugaltlink_view_valid = 0; |
3277 | } |
3278 | |
3279 | if (gnu_debugdata_view_valid) { |
3280 | int ret; |
3281 | |
3282 | ret = elf_uncompress_lzma( |
3283 | state, ((const unsigned char *)gnu_debugdata_view.view.data), |
3284 | gnu_debugdata_size, error_callback, data, &gnu_debugdata_uncompressed, |
3285 | &gnu_debugdata_uncompressed_size); |
3286 | |
3287 | elf_release_view(state, &gnu_debugdata_view, error_callback, data); |
3288 | gnu_debugdata_view_valid = 0; |
3289 | |
3290 | if (ret) { |
3291 | ret = elf_add(state, filename, -1, gnu_debugdata_uncompressed, |
3292 | gnu_debugdata_uncompressed_size, base_address, |
3293 | error_callback, data, fileline_fn, found_sym, found_dwarf, |
3294 | NULL, 0, 0, NULL, 0); |
3295 | if (ret >= 0 && descriptor >= 0) |
3296 | backtrace_close(descriptor, error_callback, data); |
3297 | return ret; |
3298 | } |
3299 | } |
3300 | |
3301 | min_offset = 0; |
3302 | max_offset = 0; |
3303 | debug_size = 0; |
3304 | for (i = 0; i < (int)DEBUG_MAX; ++i) { |
3305 | off_t end; |
3306 | |
3307 | if (sections[i].size != 0) { |
3308 | if (min_offset == 0 || sections[i].offset < min_offset) |
3309 | min_offset = sections[i].offset; |
3310 | end = sections[i].offset + sections[i].size; |
3311 | if (end > max_offset) max_offset = end; |
3312 | debug_size += sections[i].size; |
3313 | } |
3314 | if (zsections[i].size != 0) { |
3315 | if (min_offset == 0 || zsections[i].offset < min_offset) |
3316 | min_offset = zsections[i].offset; |
3317 | end = zsections[i].offset + zsections[i].size; |
3318 | if (end > max_offset) max_offset = end; |
3319 | debug_size += zsections[i].size; |
3320 | } |
3321 | } |
3322 | if (min_offset == 0 || max_offset == 0) { |
3323 | if (descriptor >= 0) { |
3324 | if (!backtrace_close(descriptor, error_callback, data)) goto fail; |
3325 | } |
3326 | return 1; |
3327 | } |
3328 | |
3329 | if (max_offset - min_offset < 0x20000000 || |
3330 | max_offset - min_offset < debug_size + 0x10000) { |
3331 | if (!elf_get_view(state, descriptor, memory, memory_size, min_offset, |
3332 | max_offset - min_offset, error_callback, data, |
3333 | &debug_view)) |
3334 | goto fail; |
3335 | debug_view_valid = 1; |
3336 | } else { |
3337 | memset(&split_debug_view[0], 0, sizeof split_debug_view); |
3338 | for (i = 0; i < (int)DEBUG_MAX; ++i) { |
3339 | struct debug_section_info *dsec; |
3340 | |
3341 | if (sections[i].size != 0) |
3342 | dsec = §ions[i]; |
3343 | else if (zsections[i].size != 0) |
3344 | dsec = &zsections[i]; |
3345 | else |
3346 | continue; |
3347 | |
3348 | if (!elf_get_view(state, descriptor, memory, memory_size, dsec->offset, |
3349 | dsec->size, error_callback, data, &split_debug_view[i])) |
3350 | goto fail; |
3351 | split_debug_view_valid[i] = 1; |
3352 | |
3353 | if (sections[i].size != 0) |
3354 | sections[i].data = |
3355 | ((const unsigned char *)split_debug_view[i].view.data); |
3356 | else |
3357 | zsections[i].data = |
3358 | ((const unsigned char *)split_debug_view[i].view.data); |
3359 | } |
3360 | } |
3361 | |
3362 | if (descriptor >= 0) { |
3363 | if (!backtrace_close(descriptor, error_callback, data)) goto fail; |
3364 | descriptor = -1; |
3365 | } |
3366 | |
3367 | using_debug_view = 0; |
3368 | if (debug_view_valid) { |
3369 | for (i = 0; i < (int)DEBUG_MAX; ++i) { |
3370 | if (sections[i].size == 0) |
3371 | sections[i].data = NULL; |
3372 | else { |
3373 | sections[i].data = ((const unsigned char *)debug_view.view.data + |
3374 | (sections[i].offset - min_offset)); |
3375 | ++using_debug_view; |
3376 | } |
3377 | |
3378 | if (zsections[i].size == 0) |
3379 | zsections[i].data = NULL; |
3380 | else |
3381 | zsections[i].data = ((const unsigned char *)debug_view.view.data + |
3382 | (zsections[i].offset - min_offset)); |
3383 | } |
3384 | } |
3385 | |
3386 | zdebug_table = NULL; |
3387 | for (i = 0; i < (int)DEBUG_MAX; ++i) { |
3388 | if (sections[i].size == 0 && zsections[i].size > 0) { |
3389 | unsigned char *uncompressed_data; |
3390 | size_t uncompressed_size; |
3391 | |
3392 | if (zdebug_table == NULL) { |
3393 | zdebug_table = ((uint16_t *)backtrace_alloc(state, ZDEBUG_TABLE_SIZE, |
3394 | error_callback, data)); |
3395 | if (zdebug_table == NULL) goto fail; |
3396 | } |
3397 | |
3398 | uncompressed_data = NULL; |
3399 | uncompressed_size = 0; |
3400 | if (!elf_uncompress_zdebug(state, zsections[i].data, zsections[i].size, |
3401 | zdebug_table, error_callback, data, |
3402 | &uncompressed_data, &uncompressed_size)) |
3403 | goto fail; |
3404 | sections[i].data = uncompressed_data; |
3405 | sections[i].size = uncompressed_size; |
3406 | sections[i].compressed = 0; |
3407 | |
3408 | if (split_debug_view_valid[i]) { |
3409 | elf_release_view(state, &split_debug_view[i], error_callback, data); |
3410 | split_debug_view_valid[i] = 0; |
3411 | } |
3412 | } |
3413 | } |
3414 | |
3415 | for (i = 0; i < (int)DEBUG_MAX; ++i) { |
3416 | unsigned char *uncompressed_data; |
3417 | size_t uncompressed_size; |
3418 | |
3419 | if (sections[i].size == 0 || !sections[i].compressed) continue; |
3420 | |
3421 | if (zdebug_table == NULL) { |
3422 | zdebug_table = ((uint16_t *)backtrace_alloc(state, ZDEBUG_TABLE_SIZE, |
3423 | error_callback, data)); |
3424 | if (zdebug_table == NULL) goto fail; |
3425 | } |
3426 | |
3427 | uncompressed_data = NULL; |
3428 | uncompressed_size = 0; |
3429 | if (!elf_uncompress_chdr(state, sections[i].data, sections[i].size, |
3430 | zdebug_table, error_callback, data, |
3431 | &uncompressed_data, &uncompressed_size)) |
3432 | goto fail; |
3433 | sections[i].data = uncompressed_data; |
3434 | sections[i].size = uncompressed_size; |
3435 | sections[i].compressed = 0; |
3436 | |
3437 | if (debug_view_valid) |
3438 | --using_debug_view; |
3439 | else if (split_debug_view_valid[i]) { |
3440 | elf_release_view(state, &split_debug_view[i], error_callback, data); |
3441 | split_debug_view_valid[i] = 0; |
3442 | } |
3443 | } |
3444 | |
3445 | if (zdebug_table != NULL) |
3446 | backtrace_free(state, zdebug_table, ZDEBUG_TABLE_SIZE, error_callback, |
3447 | data); |
3448 | |
3449 | if (debug_view_valid && using_debug_view == 0) { |
3450 | elf_release_view(state, &debug_view, error_callback, data); |
3451 | debug_view_valid = 0; |
3452 | } |
3453 | |
3454 | for (i = 0; i < (int)DEBUG_MAX; ++i) { |
3455 | dwarf_sections.data[i] = sections[i].data; |
3456 | dwarf_sections.size[i] = sections[i].size; |
3457 | } |
3458 | |
3459 | if (!backtrace_dwarf_add(state, base_address, &dwarf_sections, |
3460 | ehdr.e_ident[EI_DATA] == ELFDATA2MSB, |
3461 | fileline_altlink, error_callback, data, fileline_fn, |
3462 | fileline_entry)) |
3463 | goto fail; |
3464 | |
3465 | *found_dwarf = 1; |
3466 | |
3467 | return 1; |
3468 | |
3469 | fail: |
3470 | if (shdrs_view_valid) |
3471 | elf_release_view(state, &shdrs_view, error_callback, data); |
3472 | if (names_view_valid) |
3473 | elf_release_view(state, &names_view, error_callback, data); |
3474 | if (symtab_view_valid) |
3475 | elf_release_view(state, &symtab_view, error_callback, data); |
3476 | if (strtab_view_valid) |
3477 | elf_release_view(state, &strtab_view, error_callback, data); |
3478 | if (debuglink_view_valid) |
3479 | elf_release_view(state, &debuglink_view, error_callback, data); |
3480 | if (debugaltlink_view_valid) |
3481 | elf_release_view(state, &debugaltlink_view, error_callback, data); |
3482 | if (gnu_debugdata_view_valid) |
3483 | elf_release_view(state, &gnu_debugdata_view, error_callback, data); |
3484 | if (buildid_view_valid) |
3485 | elf_release_view(state, &buildid_view, error_callback, data); |
3486 | if (debug_view_valid) |
3487 | elf_release_view(state, &debug_view, error_callback, data); |
3488 | for (i = 0; i < (int)DEBUG_MAX; ++i) { |
3489 | if (split_debug_view_valid[i]) |
3490 | elf_release_view(state, &split_debug_view[i], error_callback, data); |
3491 | } |
3492 | if (opd) elf_release_view(state, &opd->view, error_callback, data); |
3493 | if (descriptor >= 0) backtrace_close(descriptor, error_callback, data); |
3494 | return 0; |
3495 | } |
3496 | |
3497 | struct phdr_data { |
3498 | struct backtrace_state *state; |
3499 | backtrace_error_callback error_callback; |
3500 | void *data; |
3501 | fileline *fileline_fn; |
3502 | int *found_sym; |
3503 | int *found_dwarf; |
3504 | const char *exe_filename; |
3505 | int exe_descriptor; |
3506 | }; |
3507 | |
3508 | static int |
3509 | #ifdef __i386__ |
3510 | __attribute__((__force_align_arg_pointer__)) |
3511 | #endif |
3512 | phdr_callback(struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, |
3513 | void *pdata) { |
3514 | struct phdr_data *pd = (struct phdr_data *)pdata; |
3515 | const char *filename; |
3516 | int descriptor; |
3517 | int does_not_exist; |
3518 | fileline elf_fileline_fn; |
3519 | int found_dwarf; |
3520 | |
3521 | if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0') { |
3522 | if (pd->exe_descriptor == -1) return 0; |
3523 | filename = pd->exe_filename; |
3524 | descriptor = pd->exe_descriptor; |
3525 | pd->exe_descriptor = -1; |
3526 | } else { |
3527 | if (pd->exe_descriptor != -1) { |
3528 | backtrace_close(pd->exe_descriptor, pd->error_callback, pd->data); |
3529 | pd->exe_descriptor = -1; |
3530 | } |
3531 | |
3532 | filename = info->dlpi_name; |
3533 | descriptor = backtrace_open(info->dlpi_name, pd->error_callback, pd->data, |
3534 | &does_not_exist); |
3535 | if (descriptor < 0) return 0; |
3536 | } |
3537 | |
3538 | if (elf_add(pd->state, filename, descriptor, NULL, 0, info->dlpi_addr, |
3539 | pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym, |
3540 | &found_dwarf, NULL, 0, 0, NULL, 0)) { |
3541 | if (found_dwarf) { |
3542 | *pd->found_dwarf = 1; |
3543 | *pd->fileline_fn = elf_fileline_fn; |
3544 | } |
3545 | } |
3546 | |
3547 | return 0; |
3548 | } |
3549 | |
3550 | int backtrace_initialize(struct backtrace_state *state, const char *filename, |
3551 | int descriptor, |
3552 | backtrace_error_callback error_callback, void *data, |
3553 | fileline *fileline_fn) { |
3554 | int ret; |
3555 | int found_sym; |
3556 | int found_dwarf; |
3557 | fileline elf_fileline_fn = elf_nodebug; |
3558 | struct phdr_data pd; |
3559 | |
3560 | ret = |
3561 | elf_add(state, filename, descriptor, NULL, 0, 0, error_callback, data, |
3562 | &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, NULL, 0); |
3563 | if (!ret) return 0; |
3564 | |
3565 | pd.state = state; |
3566 | pd.error_callback = error_callback; |
3567 | pd.data = data; |
3568 | pd.fileline_fn = &elf_fileline_fn; |
3569 | pd.found_sym = &found_sym; |
3570 | pd.found_dwarf = &found_dwarf; |
3571 | pd.exe_filename = filename; |
3572 | pd.exe_descriptor = ret < 0 ? descriptor : -1; |
3573 | |
3574 | dl_iterate_phdr(phdr_callback, (void *)&pd); |
3575 | |
3576 | if (!state->threaded) { |
3577 | if (found_sym) |
3578 | state->syminfo_fn = elf_syminfo; |
3579 | else if (state->syminfo_fn == NULL) |
3580 | state->syminfo_fn = elf_nosyms; |
3581 | } else { |
3582 | if (found_sym) |
3583 | backtrace_atomic_store_pointer(&state->syminfo_fn, elf_syminfo); |
3584 | else |
3585 | (void)__sync_bool_compare_and_swap(&state->syminfo_fn, NULL, elf_nosyms); |
3586 | } |
3587 | |
3588 | if (!state->threaded) |
3589 | *fileline_fn = state->fileline_fn; |
3590 | else |
3591 | *fileline_fn = backtrace_atomic_load_pointer(&state->fileline_fn); |
3592 | |
3593 | if (*fileline_fn == NULL || *fileline_fn == elf_nodebug) |
3594 | *fileline_fn = elf_fileline_fn; |
3595 | |
3596 | return 1; |
3597 | } |
3598 | |
3599 | // mmapio.c: |
3600 | #include <errno.h> |
3601 | #include <sys/mman.h> |
3602 | #include <sys/types.h> |
3603 | #include <unistd.h> |
3604 | |
3605 | #ifndef HAVE_DECL_GETPAGESIZE |
3606 | extern int getpagesize(void); |
3607 | #endif |
3608 | |
3609 | #ifndef MAP_FAILED |
3610 | #define MAP_FAILED ((void *)-1) |
3611 | #endif |
3612 | |
3613 | int backtrace_get_view(struct backtrace_state *state ATTRIBUTE_UNUSED, |
3614 | int descriptor, off_t offset, uint64_t size, |
3615 | backtrace_error_callback error_callback, void *data, |
3616 | struct backtrace_view *view) { |
3617 | size_t pagesize; |
3618 | unsigned int inpage; |
3619 | off_t pageoff; |
3620 | void *map; |
3621 | |
3622 | if ((uint64_t)(size_t)size != size) { |
3623 | error_callback(data, "file size too large", 0); |
3624 | return 0; |
3625 | } |
3626 | |
3627 | pagesize = getpagesize(); |
3628 | inpage = offset % pagesize; |
3629 | pageoff = offset - inpage; |
3630 | |
3631 | size += inpage; |
3632 | size = (size + (pagesize - 1)) & ~(pagesize - 1); |
3633 | |
3634 | map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff); |
3635 | if (map == MAP_FAILED) { |
3636 | error_callback(data, "mmap", errno); |
3637 | return 0; |
3638 | } |
3639 | |
3640 | view->data = (char *)map + inpage; |
3641 | view->base = map; |
3642 | view->len = size; |
3643 | |
3644 | return 1; |
3645 | } |
3646 | |
3647 | void backtrace_release_view(struct backtrace_state *state ATTRIBUTE_UNUSED, |
3648 | struct backtrace_view *view, |
3649 | backtrace_error_callback error_callback, |
3650 | void *data) { |
3651 | union { |
3652 | const void *cv; |
3653 | void *v; |
3654 | } const_cast; |
3655 | |
3656 | const_cast.cv = view->base; |
3657 | if (munmap(const_cast.v, view->len) < 0) |
3658 | error_callback(data, "munmap", errno); |
3659 | } |
3660 | |
3661 | // mmap.c: |
3662 | #include <errno.h> |
3663 | #include <stdlib.h> |
3664 | #include <string.h> |
3665 | #include <sys/mman.h> |
3666 | #include <sys/types.h> |
3667 | #include <unistd.h> |
3668 | |
3669 | #ifndef HAVE_DECL_GETPAGESIZE |
3670 | extern int getpagesize(void); |
3671 | #endif |
3672 | |
3673 | #ifndef MAP_ANONYMOUS |
3674 | #define MAP_ANONYMOUS MAP_ANON |
3675 | #endif |
3676 | |
3677 | #ifndef MAP_FAILED |
3678 | #define MAP_FAILED ((void *)-1) |
3679 | #endif |
3680 | |
3681 | struct backtrace_freelist_struct { |
3682 | struct backtrace_freelist_struct *next; |
3683 | |
3684 | size_t size; |
3685 | }; |
3686 | |
3687 | static void backtrace_free_locked(struct backtrace_state *state, void *addr, |
3688 | size_t size) { |
3689 | if (size >= sizeof(struct backtrace_freelist_struct)) { |
3690 | size_t c; |
3691 | struct backtrace_freelist_struct **ppsmall; |
3692 | struct backtrace_freelist_struct **pp; |
3693 | struct backtrace_freelist_struct *p; |
3694 | |
3695 | c = 0; |
3696 | ppsmall = NULL; |
3697 | for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) { |
3698 | if (ppsmall == NULL || (*pp)->size < (*ppsmall)->size) ppsmall = pp; |
3699 | ++c; |
3700 | } |
3701 | if (c >= 16) { |
3702 | if (size <= (*ppsmall)->size) return; |
3703 | *ppsmall = (*ppsmall)->next; |
3704 | } |
3705 | |
3706 | p = (struct backtrace_freelist_struct *)addr; |
3707 | p->next = state->freelist; |
3708 | p->size = size; |
3709 | state->freelist = p; |
3710 | } |
3711 | } |
3712 | |
3713 | void *backtrace_alloc(struct backtrace_state *state, size_t size, |
3714 | backtrace_error_callback error_callback, void *data) { |
3715 | void *ret; |
3716 | int locked; |
3717 | struct backtrace_freelist_struct **pp; |
3718 | size_t pagesize; |
3719 | size_t asksize; |
3720 | void *page; |
3721 | |
3722 | ret = NULL; |
3723 | |
3724 | if (!state->threaded) |
3725 | locked = 1; |
3726 | else |
3727 | locked = __sync_lock_test_and_set(&state->lock_alloc, 1) == 0; |
3728 | |
3729 | if (locked) { |
3730 | for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) { |
3731 | if ((*pp)->size >= size) { |
3732 | struct backtrace_freelist_struct *p; |
3733 | |
3734 | p = *pp; |
3735 | *pp = p->next; |
3736 | |
3737 | size = (size + 7) & ~(size_t)7; |
3738 | if (size < p->size) |
3739 | backtrace_free_locked(state, (char *)p + size, p->size - size); |
3740 | |
3741 | ret = (void *)p; |
3742 | |
3743 | break; |
3744 | } |
3745 | } |
3746 | |
3747 | if (state->threaded) __sync_lock_release(&state->lock_alloc); |
3748 | } |
3749 | |
3750 | if (ret == NULL) { |
3751 | pagesize = getpagesize(); |
3752 | asksize = (size + pagesize - 1) & ~(pagesize - 1); |
3753 | page = mmap(NULL, asksize, PROT_READ | PROT_WRITE, |
3754 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
3755 | if (page == MAP_FAILED) { |
3756 | if (error_callback) error_callback(data, "mmap", errno); |
3757 | } else { |
3758 | size = (size + 7) & ~(size_t)7; |
3759 | if (size < asksize) |
3760 | backtrace_free(state, (char *)page + size, asksize - size, |
3761 | error_callback, data); |
3762 | |
3763 | ret = page; |
3764 | } |
3765 | } |
3766 | |
3767 | return ret; |
3768 | } |
3769 | |
3770 | void backtrace_free(struct backtrace_state *state, void *addr, size_t size, |
3771 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, |
3772 | void *data ATTRIBUTE_UNUSED) { |
3773 | int locked; |
3774 | |
3775 | if (size >= 16 * 4096) { |
3776 | size_t pagesize; |
3777 | |
3778 | pagesize = getpagesize(); |
3779 | if (((uintptr_t)addr & (pagesize - 1)) == 0 && |
3780 | (size & (pagesize - 1)) == 0) { |
3781 | if (munmap(addr, size) == 0) return; |
3782 | } |
3783 | } |
3784 | |
3785 | if (!state->threaded) |
3786 | locked = 1; |
3787 | else |
3788 | locked = __sync_lock_test_and_set(&state->lock_alloc, 1) == 0; |
3789 | |
3790 | if (locked) { |
3791 | backtrace_free_locked(state, addr, size); |
3792 | |
3793 | if (state->threaded) __sync_lock_release(&state->lock_alloc); |
3794 | } |
3795 | } |
3796 | |
3797 | void *backtrace_vector_grow(struct backtrace_state *state, size_t size, |
3798 | backtrace_error_callback error_callback, void *data, |
3799 | struct backtrace_vector *vec) { |
3800 | void *ret; |
3801 | |
3802 | if (size > vec->alc) { |
3803 | size_t pagesize; |
3804 | size_t alc; |
3805 | void *base; |
3806 | |
3807 | pagesize = getpagesize(); |
3808 | alc = vec->size + size; |
3809 | if (vec->size == 0) |
3810 | alc = 16 * size; |
3811 | else if (alc < pagesize) { |
3812 | alc *= 2; |
3813 | if (alc > pagesize) alc = pagesize; |
3814 | } else { |
3815 | alc *= 2; |
3816 | alc = (alc + pagesize - 1) & ~(pagesize - 1); |
3817 | } |
3818 | base = backtrace_alloc(state, alc, error_callback, data); |
3819 | if (base == NULL) return NULL; |
3820 | if (vec->base != NULL) { |
3821 | memcpy(base, vec->base, vec->size); |
3822 | backtrace_free(state, vec->base, vec->size + vec->alc, error_callback, |
3823 | data); |
3824 | } |
3825 | vec->base = base; |
3826 | vec->alc = alc - vec->size; |
3827 | } |
3828 | |
3829 | ret = (char *)vec->base + vec->size; |
3830 | vec->size += size; |
3831 | vec->alc -= size; |
3832 | return ret; |
3833 | } |
3834 | |
3835 | void *backtrace_vector_finish(struct backtrace_state *state ATTRIBUTE_UNUSED, |
3836 | struct backtrace_vector *vec, |
3837 | backtrace_error_callback error_callback |
3838 | ATTRIBUTE_UNUSED, |
3839 | void *data ATTRIBUTE_UNUSED) { |
3840 | void *ret; |
3841 | |
3842 | ret = vec->base; |
3843 | vec->base = (char *)vec->base + vec->size; |
3844 | vec->size = 0; |
3845 | return ret; |
3846 | } |
3847 | |
3848 | int backtrace_vector_release(struct backtrace_state *state, |
3849 | struct backtrace_vector *vec, |
3850 | backtrace_error_callback error_callback, |
3851 | void *data) { |
3852 | size_t size; |
3853 | size_t alc; |
3854 | size_t aligned; |
3855 | |
3856 | size = vec->size; |
3857 | alc = vec->alc; |
3858 | aligned = (size + 7) & ~(size_t)7; |
3859 | alc -= aligned - size; |
3860 | |
3861 | backtrace_free(state, (char *)vec->base + aligned, alc, error_callback, data); |
3862 | vec->alc = 0; |
3863 | if (vec->size == 0) vec->base = NULL; |
3864 | return 1; |
3865 | } |