aarch64: rcpc3: Add +rcpc3 architectural feature support flag
[platform/upstream/binutils.git] / libbacktrace / pecoff.c
1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2    Copyright (C) 2015-2021 Free Software Foundation, Inc.
3    Adapted from elf.c by Tristan Gingold, AdaCore.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9     (1) Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer.
11
12     (2) Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions and the following disclaimer in
14     the documentation and/or other materials provided with the
15     distribution.
16
17     (3) The name of the author may not be used to
18     endorse or promote products derived from this software without
19     specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.  */
32
33 #include "config.h"
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38
39 #include "backtrace.h"
40 #include "internal.h"
41
42 /* Coff file header.  */
43
44 typedef struct {
45   uint16_t machine;
46   uint16_t number_of_sections;
47   uint32_t time_date_stamp;
48   uint32_t pointer_to_symbol_table;
49   uint32_t number_of_symbols;
50   uint16_t size_of_optional_header;
51   uint16_t characteristics;
52 } b_coff_file_header;
53
54 /* Coff optional header.  */
55
56 typedef struct {
57   uint16_t magic;
58   uint8_t  major_linker_version;
59   uint8_t  minor_linker_version;
60   uint32_t size_of_code;
61   uint32_t size_of_initialized_data;
62   uint32_t size_of_uninitialized_data;
63   uint32_t address_of_entry_point;
64   uint32_t base_of_code;
65   union {
66     struct {
67       uint32_t base_of_data;
68       uint32_t image_base;
69     } pe;
70     struct {
71       uint64_t image_base;
72     } pep;
73   } u;
74 } b_coff_optional_header;
75
76 /* Values of magic in optional header.  */
77
78 #define PE_MAGIC 0x10b          /* PE32 executable.  */
79 #define PEP_MAGIC 0x20b         /* PE32+ executable (for 64bit targets).  */
80
81 /* Coff section header.  */
82
83 typedef struct {
84   char name[8];
85   uint32_t virtual_size;
86   uint32_t virtual_address;
87   uint32_t size_of_raw_data;
88   uint32_t pointer_to_raw_data;
89   uint32_t pointer_to_relocations;
90   uint32_t pointer_to_line_numbers;
91   uint16_t number_of_relocations;
92   uint16_t number_of_line_numbers;
93   uint32_t characteristics;
94 } b_coff_section_header;
95
96 /* Coff symbol name.  */
97
98 typedef union {
99   char short_name[8];
100   struct {
101     unsigned char zeroes[4];
102     unsigned char off[4];
103   } long_name;
104 } b_coff_name;
105
106 /* Coff symbol (external representation which is unaligned).  */
107
108 typedef struct {
109   b_coff_name name;
110   unsigned char value[4];
111   unsigned char section_number[2];
112   unsigned char type[2];
113   unsigned char storage_class;
114   unsigned char number_of_aux_symbols;
115 } b_coff_external_symbol;
116
117 /* Symbol types.  */
118
119 #define N_TBSHFT 4                      /* Shift for the derived type.  */
120 #define IMAGE_SYM_DTYPE_FUNCTION 2      /* Function derived type.  */
121
122 /* Size of a coff symbol.  */
123
124 #define SYM_SZ 18
125
126 /* Coff symbol, internal representation (aligned).  */
127
128 typedef struct {
129   const char *name;
130   uint32_t value;
131   int16_t sec;
132   uint16_t type;
133   uint16_t sc;
134 } b_coff_internal_symbol;
135
136 /* Names of sections, indexed by enum dwarf_section in internal.h.  */
137
138 static const char * const debug_section_names[DEBUG_MAX] =
139 {
140   ".debug_info",
141   ".debug_line",
142   ".debug_abbrev",
143   ".debug_ranges",
144   ".debug_str",
145   ".debug_addr",
146   ".debug_str_offsets",
147   ".debug_line_str",
148   ".debug_rnglists"
149 };
150
151 /* Information we gather for the sections we care about.  */
152
153 struct debug_section_info
154 {
155   /* Section file offset.  */
156   off_t offset;
157   /* Section size.  */
158   size_t size;
159 };
160
161 /* Information we keep for an coff symbol.  */
162
163 struct coff_symbol
164 {
165   /* The name of the symbol.  */
166   const char *name;
167   /* The address of the symbol.  */
168   uintptr_t address;
169 };
170
171 /* Information to pass to coff_syminfo.  */
172
173 struct coff_syminfo_data
174 {
175   /* Symbols for the next module.  */
176   struct coff_syminfo_data *next;
177   /* The COFF symbols, sorted by address.  */
178   struct coff_symbol *symbols;
179   /* The number of symbols.  */
180   size_t count;
181 };
182
183 /* A dummy callback function used when we can't find any debug info.  */
184
185 static int
186 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
187               uintptr_t pc ATTRIBUTE_UNUSED,
188               backtrace_full_callback callback ATTRIBUTE_UNUSED,
189               backtrace_error_callback error_callback, void *data)
190 {
191   error_callback (data, "no debug info in PE/COFF executable", -1);
192   return 0;
193 }
194
195 /* A dummy callback function used when we can't find a symbol
196    table.  */
197
198 static void
199 coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
200              uintptr_t addr ATTRIBUTE_UNUSED,
201              backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
202              backtrace_error_callback error_callback, void *data)
203 {
204   error_callback (data, "no symbol table in PE/COFF executable", -1);
205 }
206
207 /* Read a potentially unaligned 4 byte word at P, using native endianness.  */
208
209 static uint32_t
210 coff_read4 (const unsigned char *p)
211 {
212   uint32_t res;
213
214   memcpy (&res, p, 4);
215   return res;
216 }
217
218 /* Read a potentially unaligned 2 byte word at P, using native endianness.
219    All 2 byte word in symbols are always aligned, but for coherency all
220    fields are declared as char arrays.  */
221
222 static uint16_t
223 coff_read2 (const unsigned char *p)
224 {
225   uint16_t res;
226
227   memcpy (&res, p, sizeof (res));
228   return res;
229 }
230
231 /* Return the length (without the trailing 0) of a COFF short name.  */
232
233 static size_t
234 coff_short_name_len (const char *name)
235 {
236   int i;
237
238   for (i = 0; i < 8; i++)
239     if (name[i] == 0)
240       return i;
241   return 8;
242 }
243
244 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
245    string).  */
246
247 static int
248 coff_short_name_eq (const char *name, const char *cname)
249 {
250   int i;
251
252   for (i = 0; i < 8; i++)
253     {
254       if (name[i] != cname[i])
255         return 0;
256       if (name[i] == 0)
257         return 1;
258     }
259   return name[8] == 0;
260 }
261
262 /* Return true iff NAME is the same as string at offset OFF.  */
263
264 static int
265 coff_long_name_eq (const char *name, unsigned int off,
266                    struct backtrace_view *str_view)
267 {
268   if (off >= str_view->len)
269     return 0;
270   return strcmp (name, (const char *)str_view->data + off) == 0;
271 }
272
273 /* Compare struct coff_symbol for qsort.  */
274
275 static int
276 coff_symbol_compare (const void *v1, const void *v2)
277 {
278   const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
279   const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
280
281   if (e1->address < e2->address)
282     return -1;
283   else if (e1->address > e2->address)
284     return 1;
285   else
286     return 0;
287 }
288
289 /* Convert SYM to internal (and aligned) format ISYM, using string table
290    from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
291    Return -1 in case of error (invalid section number or string index).  */
292
293 static int
294 coff_expand_symbol (b_coff_internal_symbol *isym,
295                     const b_coff_external_symbol *sym,
296                     uint16_t sects_num,
297                     const unsigned char *strtab, size_t strtab_size)
298 {
299   isym->type = coff_read2 (sym->type);
300   isym->sec = coff_read2 (sym->section_number);
301   isym->sc = sym->storage_class;
302
303   if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
304     return -1;
305   if (sym->name.short_name[0] != 0)
306     isym->name = sym->name.short_name;
307   else
308     {
309       uint32_t off = coff_read4 (sym->name.long_name.off);
310
311       if (off >= strtab_size)
312         return -1;
313       isym->name = (const char *) strtab + off;
314     }
315   return 0;
316 }
317
318 /* Return true iff SYM is a defined symbol for a function.  Data symbols
319    aren't considered because they aren't easily identified (same type as
320    section names, presence of symbols defined by the linker script).  */
321
322 static int
323 coff_is_function_symbol (const b_coff_internal_symbol *isym)
324 {
325   return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
326     && isym->sec > 0;
327 }
328
329 /* Initialize the symbol table info for coff_syminfo.  */
330
331 static int
332 coff_initialize_syminfo (struct backtrace_state *state,
333                          uintptr_t base_address, int is_64,
334                          const b_coff_section_header *sects, size_t sects_num,
335                          const b_coff_external_symbol *syms, size_t syms_size,
336                          const unsigned char *strtab, size_t strtab_size,
337                          backtrace_error_callback error_callback,
338                          void *data, struct coff_syminfo_data *sdata)
339 {
340   size_t syms_count;
341   char *coff_symstr;
342   size_t coff_symstr_len;
343   size_t coff_symbol_count;
344   size_t coff_symbol_size;
345   struct coff_symbol *coff_symbols;
346   struct coff_symbol *coff_sym;
347   char *coff_str;
348   size_t i;
349
350   syms_count = syms_size / SYM_SZ;
351
352   /* We only care about function symbols.  Count them.  Also count size of
353      strings for in-symbol names.  */
354   coff_symbol_count = 0;
355   coff_symstr_len = 0;
356   for (i = 0; i < syms_count; ++i)
357     {
358       const b_coff_external_symbol *asym = &syms[i];
359       b_coff_internal_symbol isym;
360
361       if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
362         {
363           error_callback (data, "invalid section or offset in coff symbol", 0);
364           return 0;
365         }
366       if (coff_is_function_symbol (&isym))
367         {
368           ++coff_symbol_count;
369           if (asym->name.short_name[0] != 0)
370             coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
371         }
372
373       i += asym->number_of_aux_symbols;
374     }
375
376   coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
377   coff_symbols = ((struct coff_symbol *)
378                   backtrace_alloc (state, coff_symbol_size, error_callback,
379                                    data));
380   if (coff_symbols == NULL)
381     return 0;
382
383   /* Allocate memory for symbols strings.  */
384   if (coff_symstr_len > 0)
385     {
386       coff_symstr = ((char *)
387                      backtrace_alloc (state, coff_symstr_len, error_callback,
388                                       data));
389       if (coff_symstr == NULL)
390         {
391           backtrace_free (state, coff_symbols, coff_symbol_size,
392                           error_callback, data);
393           return 0;
394         }
395     }
396   else
397     coff_symstr = NULL;
398
399   /* Copy symbols.  */
400   coff_sym = coff_symbols;
401   coff_str = coff_symstr;
402   for (i = 0; i < syms_count; ++i)
403     {
404       const b_coff_external_symbol *asym = &syms[i];
405       b_coff_internal_symbol isym;
406
407       if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
408         {
409           /* Should not fail, as it was already tested in the previous
410              loop.  */
411           abort ();
412         }
413       if (coff_is_function_symbol (&isym))
414         {
415           const char *name;
416           int16_t secnum;
417
418           if (asym->name.short_name[0] != 0)
419             {
420               size_t len = coff_short_name_len (isym.name);
421               name = coff_str;
422               memcpy (coff_str, isym.name, len);
423               coff_str[len] = 0;
424               coff_str += len + 1;
425             }
426           else
427             name = isym.name;
428
429           if (!is_64)
430             {
431               /* Strip leading '_'.  */
432               if (name[0] == '_')
433                 name++;
434             }
435
436           /* Symbol value is section relative, so we need to read the address
437              of its section.  */
438           secnum = coff_read2 (asym->section_number);
439
440           coff_sym->name = name;
441           coff_sym->address = (coff_read4 (asym->value)
442                                + sects[secnum - 1].virtual_address
443                                + base_address);
444           coff_sym++;
445         }
446
447       i += asym->number_of_aux_symbols;
448     }
449
450   /* End of symbols marker.  */
451   coff_sym->name = NULL;
452   coff_sym->address = -1;
453
454   backtrace_qsort (coff_symbols, coff_symbol_count,
455                    sizeof (struct coff_symbol), coff_symbol_compare);
456
457   sdata->next = NULL;
458   sdata->symbols = coff_symbols;
459   sdata->count = coff_symbol_count;
460
461   return 1;
462 }
463
464 /* Add EDATA to the list in STATE.  */
465
466 static void
467 coff_add_syminfo_data (struct backtrace_state *state,
468                        struct coff_syminfo_data *sdata)
469 {
470   if (!state->threaded)
471     {
472       struct coff_syminfo_data **pp;
473
474       for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
475            *pp != NULL;
476            pp = &(*pp)->next)
477         ;
478       *pp = sdata;
479     }
480   else
481     {
482       while (1)
483         {
484           struct coff_syminfo_data **pp;
485
486           pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
487
488           while (1)
489             {
490               struct coff_syminfo_data *p;
491
492               p = backtrace_atomic_load_pointer (pp);
493
494               if (p == NULL)
495                 break;
496
497               pp = &p->next;
498             }
499
500           if (__sync_bool_compare_and_swap (pp, NULL, sdata))
501             break;
502         }
503     }
504 }
505
506 /* Compare an ADDR against an elf_symbol for bsearch.  We allocate one
507    extra entry in the array so that this can look safely at the next
508    entry.  */
509
510 static int
511 coff_symbol_search (const void *vkey, const void *ventry)
512 {
513   const uintptr_t *key = (const uintptr_t *) vkey;
514   const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
515   uintptr_t addr;
516
517   addr = *key;
518   if (addr < entry->address)
519     return -1;
520   else if (addr >= entry[1].address)
521     return 1;
522   else
523     return 0;
524 }
525
526 /* Return the symbol name and value for an ADDR.  */
527
528 static void
529 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
530               backtrace_syminfo_callback callback,
531               backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
532               void *data)
533 {
534   struct coff_syminfo_data *sdata;
535   struct coff_symbol *sym = NULL;
536
537   if (!state->threaded)
538     {
539       for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
540            sdata != NULL;
541            sdata = sdata->next)
542         {
543           sym = ((struct coff_symbol *)
544                  bsearch (&addr, sdata->symbols, sdata->count,
545                           sizeof (struct coff_symbol), coff_symbol_search));
546           if (sym != NULL)
547             break;
548         }
549     }
550   else
551     {
552       struct coff_syminfo_data **pp;
553
554       pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
555       while (1)
556         {
557           sdata = backtrace_atomic_load_pointer (pp);
558           if (sdata == NULL)
559             break;
560
561           sym = ((struct coff_symbol *)
562                  bsearch (&addr, sdata->symbols, sdata->count,
563                           sizeof (struct coff_symbol), coff_symbol_search));
564           if (sym != NULL)
565             break;
566
567           pp = &sdata->next;
568         }
569     }
570
571   if (sym == NULL)
572     callback (data, addr, NULL, 0, 0);
573   else
574     callback (data, addr, sym->name, sym->address, 0);
575 }
576
577 /* Add the backtrace data for one PE/COFF file.  Returns 1 on success,
578    0 on failure (in both cases descriptor is closed).  */
579
580 static int
581 coff_add (struct backtrace_state *state, int descriptor,
582           backtrace_error_callback error_callback, void *data,
583           fileline *fileline_fn, int *found_sym, int *found_dwarf)
584 {
585   struct backtrace_view fhdr_view;
586   off_t fhdr_off;
587   int magic_ok;
588   b_coff_file_header fhdr;
589   off_t opt_sects_off;
590   size_t opt_sects_size;
591   unsigned int sects_num;
592   struct backtrace_view sects_view;
593   int sects_view_valid;
594   const b_coff_optional_header *opt_hdr;
595   const b_coff_section_header *sects;
596   struct backtrace_view str_view;
597   int str_view_valid;
598   size_t str_size;
599   off_t str_off;
600   struct backtrace_view syms_view;
601   off_t syms_off;
602   size_t syms_size;
603   int syms_view_valid;
604   unsigned int syms_num;
605   unsigned int i;
606   struct debug_section_info sections[DEBUG_MAX];
607   off_t min_offset;
608   off_t max_offset;
609   struct backtrace_view debug_view;
610   int debug_view_valid;
611   int is_64;
612   uintptr_t image_base;
613   struct dwarf_sections dwarf_sections;
614
615   *found_sym = 0;
616   *found_dwarf = 0;
617
618   sects_view_valid = 0;
619   syms_view_valid = 0;
620   str_view_valid = 0;
621   debug_view_valid = 0;
622
623   /* Map the MS-DOS stub (if any) and extract file header offset.  */
624   if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
625                            data, &fhdr_view))
626     goto fail;
627
628   {
629     const unsigned char *vptr = fhdr_view.data;
630
631     if (vptr[0] == 'M' && vptr[1] == 'Z')
632       fhdr_off = coff_read4 (vptr + 0x3c);
633     else
634       fhdr_off = 0;
635   }
636
637   backtrace_release_view (state, &fhdr_view, error_callback, data);
638
639   /* Map the coff file header.  */
640   if (!backtrace_get_view (state, descriptor, fhdr_off,
641                            sizeof (b_coff_file_header) + 4,
642                            error_callback, data, &fhdr_view))
643     goto fail;
644
645   if (fhdr_off != 0)
646     {
647       const char *magic = (const char *) fhdr_view.data;
648       magic_ok = memcmp (magic, "PE\0", 4) == 0;
649       fhdr_off += 4;
650
651       memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
652     }
653   else
654     {
655       memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
656       /* TODO: test fhdr.machine for coff but non-PE platforms.  */
657       magic_ok = 0;
658     }
659   backtrace_release_view (state, &fhdr_view, error_callback, data);
660
661   if (!magic_ok)
662     {
663       error_callback (data, "executable file is not COFF", 0);
664       goto fail;
665     }
666
667   sects_num = fhdr.number_of_sections;
668   syms_num = fhdr.number_of_symbols;
669
670   opt_sects_off = fhdr_off + sizeof (fhdr);
671   opt_sects_size = (fhdr.size_of_optional_header
672                     + sects_num * sizeof (b_coff_section_header));
673
674   /* To translate PC to file/line when using DWARF, we need to find
675      the .debug_info and .debug_line sections.  */
676
677   /* Read the optional header and the section headers.  */
678
679   if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
680                            error_callback, data, &sects_view))
681     goto fail;
682   sects_view_valid = 1;
683   opt_hdr = (const b_coff_optional_header *) sects_view.data;
684   sects = (const b_coff_section_header *)
685     (sects_view.data + fhdr.size_of_optional_header);
686
687   is_64 = 0;
688   if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
689     {
690       if (opt_hdr->magic == PE_MAGIC)
691         image_base = opt_hdr->u.pe.image_base;
692       else if (opt_hdr->magic == PEP_MAGIC)
693         {
694           image_base = opt_hdr->u.pep.image_base;
695           is_64 = 1;
696         }
697       else
698         {
699           error_callback (data, "bad magic in PE optional header", 0);
700           goto fail;
701         }
702     }
703   else
704     image_base = 0;
705
706   /* Read the symbol table and the string table.  */
707
708   if (fhdr.pointer_to_symbol_table == 0)
709     {
710       /* No symbol table, no string table.  */
711       str_off = 0;
712       str_size = 0;
713       syms_num = 0;
714       syms_size = 0;
715     }
716   else
717     {
718       /* Symbol table is followed by the string table.  The string table
719          starts with its length (on 4 bytes).
720          Map the symbol table and the length of the string table.  */
721       syms_off = fhdr.pointer_to_symbol_table;
722       syms_size = syms_num * SYM_SZ;
723
724       if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
725                                error_callback, data, &syms_view))
726         goto fail;
727       syms_view_valid = 1;
728
729       str_size = coff_read4 (syms_view.data + syms_size);
730
731       str_off = syms_off + syms_size;
732
733       if (str_size > 4)
734         {
735           /* Map string table (including the length word).  */
736
737           if (!backtrace_get_view (state, descriptor, str_off, str_size,
738                                    error_callback, data, &str_view))
739             goto fail;
740           str_view_valid = 1;
741         }
742     }
743
744   memset (sections, 0, sizeof sections);
745
746   /* Look for the symbol table.  */
747   for (i = 0; i < sects_num; ++i)
748     {
749       const b_coff_section_header *s = sects + i;
750       unsigned int str_off;
751       int j;
752
753       if (s->name[0] == '/')
754         {
755           /* Extended section name.  */
756           str_off = atoi (s->name + 1);
757         }
758       else
759         str_off = 0;
760
761       for (j = 0; j < (int) DEBUG_MAX; ++j)
762         {
763           const char *dbg_name = debug_section_names[j];
764           int match;
765
766           if (str_off != 0)
767             match = coff_long_name_eq (dbg_name, str_off, &str_view);
768           else
769             match = coff_short_name_eq (dbg_name, s->name);
770           if (match)
771             {
772               sections[j].offset = s->pointer_to_raw_data;
773               sections[j].size = s->virtual_size <= s->size_of_raw_data ?
774                 s->virtual_size : s->size_of_raw_data;
775               break;
776             }
777         }
778     }
779
780   if (syms_num != 0)
781     {
782       struct coff_syminfo_data *sdata;
783
784       sdata = ((struct coff_syminfo_data *)
785                backtrace_alloc (state, sizeof *sdata, error_callback, data));
786       if (sdata == NULL)
787         goto fail;
788
789       if (!coff_initialize_syminfo (state, image_base, is_64,
790                                     sects, sects_num,
791                                     syms_view.data, syms_size,
792                                     str_view.data, str_size,
793                                     error_callback, data, sdata))
794         {
795           backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
796           goto fail;
797         }
798
799       *found_sym = 1;
800
801       coff_add_syminfo_data (state, sdata);
802     }
803
804   backtrace_release_view (state, &sects_view, error_callback, data);
805   sects_view_valid = 0;
806   if (syms_view_valid)
807     {
808       backtrace_release_view (state, &syms_view, error_callback, data);
809       syms_view_valid = 0;
810     }
811
812   /* Read all the debug sections in a single view, since they are
813      probably adjacent in the file.  We never release this view.  */
814
815   min_offset = 0;
816   max_offset = 0;
817   for (i = 0; i < (int) DEBUG_MAX; ++i)
818     {
819       off_t end;
820
821       if (sections[i].size == 0)
822         continue;
823       if (min_offset == 0 || sections[i].offset < min_offset)
824         min_offset = sections[i].offset;
825       end = sections[i].offset + sections[i].size;
826       if (end > max_offset)
827         max_offset = end;
828     }
829   if (min_offset == 0 || max_offset == 0)
830     {
831       if (!backtrace_close (descriptor, error_callback, data))
832         goto fail;
833       *fileline_fn = coff_nodebug;
834       return 1;
835     }
836
837   if (!backtrace_get_view (state, descriptor, min_offset,
838                            max_offset - min_offset,
839                            error_callback, data, &debug_view))
840     goto fail;
841   debug_view_valid = 1;
842
843   /* We've read all we need from the executable.  */
844   if (!backtrace_close (descriptor, error_callback, data))
845     goto fail;
846   descriptor = -1;
847
848   for (i = 0; i < (int) DEBUG_MAX; ++i)
849     {
850       size_t size = sections[i].size;
851       dwarf_sections.size[i] = size;
852       if (size == 0)
853         dwarf_sections.data[i] = NULL;
854       else
855         dwarf_sections.data[i] = ((const unsigned char *) debug_view.data
856                                   + (sections[i].offset - min_offset));
857     }
858
859   if (!backtrace_dwarf_add (state, /* base_address */ 0, &dwarf_sections,
860                             0, /* FIXME: is_bigendian */
861                             NULL, /* altlink */
862                             error_callback, data, fileline_fn,
863                             NULL /* returned fileline_entry */))
864     goto fail;
865
866   *found_dwarf = 1;
867
868   return 1;
869
870  fail:
871   if (sects_view_valid)
872     backtrace_release_view (state, &sects_view, error_callback, data);
873   if (str_view_valid)
874     backtrace_release_view (state, &str_view, error_callback, data);
875   if (syms_view_valid)
876     backtrace_release_view (state, &syms_view, error_callback, data);
877   if (debug_view_valid)
878     backtrace_release_view (state, &debug_view, error_callback, data);
879   if (descriptor != -1)
880     backtrace_close (descriptor, error_callback, data);
881   return 0;
882 }
883
884 /* Initialize the backtrace data we need from an ELF executable.  At
885    the ELF level, all we need to do is find the debug info
886    sections.  */
887
888 int
889 backtrace_initialize (struct backtrace_state *state,
890                       const char *filename ATTRIBUTE_UNUSED, int descriptor,
891                       backtrace_error_callback error_callback,
892                       void *data, fileline *fileline_fn)
893 {
894   int ret;
895   int found_sym;
896   int found_dwarf;
897   fileline coff_fileline_fn;
898
899   ret = coff_add (state, descriptor, error_callback, data,
900                   &coff_fileline_fn, &found_sym, &found_dwarf);
901   if (!ret)
902     return 0;
903
904   if (!state->threaded)
905     {
906       if (found_sym)
907         state->syminfo_fn = coff_syminfo;
908       else if (state->syminfo_fn == NULL)
909         state->syminfo_fn = coff_nosyms;
910     }
911   else
912     {
913       if (found_sym)
914         backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
915       else
916         (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
917                                              coff_nosyms);
918     }
919
920   if (!state->threaded)
921     {
922       if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
923         *fileline_fn = coff_fileline_fn;
924     }
925   else
926     {
927       fileline current_fn;
928
929       current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
930       if (current_fn == NULL || current_fn == coff_nodebug)
931         *fileline_fn = coff_fileline_fn;
932     }
933
934   return 1;
935 }