]> git.lizzy.rs Git - rust.git/blob - src/libbacktrace/pecoff.c
Make fields and macro defs exported
[rust.git] / src / libbacktrace / pecoff.c
1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2    Copyright (C) 2015 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 /* An index of sections we care about.  */
137
138 enum debug_section
139 {
140   DEBUG_INFO,
141   DEBUG_LINE,
142   DEBUG_ABBREV,
143   DEBUG_RANGES,
144   DEBUG_STR,
145   DEBUG_MAX
146 };
147
148 /* Names of sections, indexed by enum debug_section.  */
149
150 static const char * const debug_section_names[DEBUG_MAX] =
151 {
152   ".debug_info",
153   ".debug_line",
154   ".debug_abbrev",
155   ".debug_ranges",
156   ".debug_str"
157 };
158
159 /* Information we gather for the sections we care about.  */
160
161 struct debug_section_info
162 {
163   /* Section file offset.  */
164   off_t offset;
165   /* Section size.  */
166   size_t size;
167   /* Section contents, after read from file.  */
168   const unsigned char *data;
169 };
170
171 /* Information we keep for an coff symbol.  */
172
173 struct coff_symbol
174 {
175   /* The name of the symbol.  */
176   const char *name;
177   /* The address of the symbol.  */
178   uintptr_t address;
179 };
180
181 /* Information to pass to coff_syminfo.  */
182
183 struct coff_syminfo_data
184 {
185   /* Symbols for the next module.  */
186   struct coff_syminfo_data *next;
187   /* The COFF symbols, sorted by address.  */
188   struct coff_symbol *symbols;
189   /* The number of symbols.  */
190   size_t count;
191 };
192
193 /* A dummy callback function used when we can't find any debug info.  */
194
195 static int
196 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
197               uintptr_t pc ATTRIBUTE_UNUSED,
198               backtrace_full_callback callback ATTRIBUTE_UNUSED,
199               backtrace_error_callback error_callback, void *data)
200 {
201   error_callback (data, "no debug info in PE/COFF executable", -1);
202   return 0;
203 }
204
205 /* A dummy callback function used when we can't find a symbol
206    table.  */
207
208 static void
209 coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
210              uintptr_t addr ATTRIBUTE_UNUSED,
211              backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
212              backtrace_error_callback error_callback, void *data)
213 {
214   error_callback (data, "no symbol table in PE/COFF executable", -1);
215 }
216
217 /* Read a potentially unaligned 4 byte word at P, using native endianness.  */
218
219 static uint32_t
220 coff_read4 (const unsigned char *p)
221 {
222   uint32_t res;
223
224   memcpy (&res, p, 4);
225   return res;
226 }
227
228 /* Read a potentially unaligned 2 byte word at P, using native endianness.
229    All 2 byte word in symbols are always aligned, but for coherency all
230    fields are declared as char arrays.  */
231
232 static uint16_t
233 coff_read2 (const unsigned char *p)
234 {
235   uint16_t res;
236
237   memcpy (&res, p, sizeof (res));
238   return res;
239 }
240
241 /* Return the length (without the trailing 0) of a COFF short name.  */
242
243 static size_t
244 coff_short_name_len (const char *name)
245 {
246   int i;
247
248   for (i = 0; i < 8; i++)
249     if (name[i] == 0)
250       return i;
251   return 8;
252 }
253
254 /* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
255    string).  */
256
257 static int
258 coff_short_name_eq (const char *name, const char *cname)
259 {
260   int i;
261
262   for (i = 0; i < 8; i++)
263     {
264       if (name[i] != cname[i])
265         return 0;
266       if (name[i] == 0)
267         return 1;
268     }
269   return name[8] == 0;
270 }
271
272 /* Return true iff NAME is the same as string at offset OFF.  */
273
274 static int
275 coff_long_name_eq (const char *name, unsigned int off,
276                    struct backtrace_view *str_view)
277 {
278   if (off >= str_view->len)
279     return 0;
280   return strcmp (name, (const char *)str_view->data + off) == 0;
281 }
282
283 /* Compare struct coff_symbol for qsort.  */
284
285 static int
286 coff_symbol_compare (const void *v1, const void *v2)
287 {
288   const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
289   const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
290
291   if (e1->address < e2->address)
292     return -1;
293   else if (e1->address > e2->address)
294     return 1;
295   else
296     return 0;
297 }
298
299 /* Convert SYM to internal (and aligned) format ISYM, using string table
300    from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
301    Return -1 in case of error (invalid section number or string index).  */
302
303 static int
304 coff_expand_symbol (b_coff_internal_symbol *isym,
305                     const b_coff_external_symbol *sym,
306                     uint16_t sects_num,
307                     const unsigned char *strtab, size_t strtab_size)
308 {
309   isym->type = coff_read2 (sym->type);
310   isym->sec = coff_read2 (sym->section_number);
311   isym->sc = sym->storage_class;
312
313   if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
314     return -1;
315   if (sym->name.short_name[0] != 0)
316     isym->name = sym->name.short_name;
317   else
318     {
319       uint32_t off = coff_read4 (sym->name.long_name.off);
320
321       if (off >= strtab_size)
322         return -1;
323       isym->name = (const char *) strtab + off;
324     }
325   return 0;
326 }
327
328 /* Return true iff SYM is a defined symbol for a function.  Data symbols
329    aren't considered because they aren't easily identified (same type as
330    section names, presence of symbols defined by the linker script).  */
331
332 static int
333 coff_is_function_symbol (const b_coff_internal_symbol *isym)
334 {
335   return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
336     && isym->sec > 0;
337 }
338
339 /* Initialize the symbol table info for coff_syminfo.  */
340
341 static int
342 coff_initialize_syminfo (struct backtrace_state *state,
343                          uintptr_t base_address,
344                          const b_coff_section_header *sects, size_t sects_num,
345                          const b_coff_external_symbol *syms, size_t syms_size,
346                          const unsigned char *strtab, size_t strtab_size,
347                          backtrace_error_callback error_callback,
348                          void *data, struct coff_syminfo_data *sdata)
349 {
350   size_t syms_count;
351   char *coff_symstr;
352   size_t coff_symstr_len;
353   size_t coff_symbol_count;
354   size_t coff_symbol_size;
355   struct coff_symbol *coff_symbols;
356   struct coff_symbol *coff_sym;
357   char *coff_str;
358   size_t i;
359
360   syms_count = syms_size / SYM_SZ;
361
362   /* We only care about function symbols.  Count them.  Also count size of
363      strings for in-symbol names.  */
364   coff_symbol_count = 0;
365   coff_symstr_len = 0;
366   for (i = 0; i < syms_count; ++i)
367     {
368       const b_coff_external_symbol *asym = &syms[i];
369       b_coff_internal_symbol isym;
370
371       if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
372         {
373           error_callback (data, "invalid section or offset in coff symbol", 0);
374           return 0;
375         }
376       if (coff_is_function_symbol (&isym))
377         {
378           ++coff_symbol_count;
379           if (asym->name.short_name[0] != 0)
380             coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
381         }
382
383       i += asym->number_of_aux_symbols;
384     }
385
386   coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
387   coff_symbols = ((struct coff_symbol *)
388                   backtrace_alloc (state, coff_symbol_size, error_callback,
389                                    data));
390   if (coff_symbols == NULL)
391     return 0;
392
393   /* Allocate memory for symbols strings.  */
394   if (coff_symstr_len > 0)
395     {
396       coff_symstr = ((char *)
397                      backtrace_alloc (state, coff_symstr_len, error_callback,
398                                       data));
399       if (coff_symstr == NULL)
400         {
401           backtrace_free (state, coff_symbols, coff_symbol_size,
402                           error_callback, data);
403           return 0;
404         }
405     }
406   else
407     coff_symstr = NULL;
408
409   /* Copy symbols.  */
410   coff_sym = coff_symbols;
411   coff_str = coff_symstr;
412   for (i = 0; i < syms_count; ++i)
413     {
414       const b_coff_external_symbol *asym = &syms[i];
415       b_coff_internal_symbol isym;
416
417       if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
418         {
419           /* Should not fail, as it was already tested in the previous
420              loop.  */
421           abort ();
422         }
423       if (coff_is_function_symbol (&isym))
424         {
425           const char *name;
426           int16_t secnum;
427
428           if (asym->name.short_name[0] != 0)
429             {
430               size_t len = coff_short_name_len (isym.name);
431               name = coff_str;
432               memcpy (coff_str, isym.name, len);
433               coff_str[len] = 0;
434               coff_str += len + 1;
435             }
436           else
437             name = isym.name;
438
439           /* Strip leading '_'.  */
440           if (name[0] == '_')
441             name++;
442
443           /* Symbol value is section relative, so we need to read the address
444              of its section.  */
445           secnum = coff_read2 (asym->section_number);
446
447           coff_sym->name = name;
448           coff_sym->address = (coff_read4 (asym->value)
449                                + sects[secnum - 1].virtual_address
450                                + base_address);
451           coff_sym++;
452         }
453
454       i += asym->number_of_aux_symbols;
455     }
456
457   /* End of symbols marker.  */
458   coff_sym->name = NULL;
459   coff_sym->address = -1;
460
461   backtrace_qsort (coff_symbols, coff_symbol_count,
462                    sizeof (struct coff_symbol), coff_symbol_compare);
463
464   sdata->next = NULL;
465   sdata->symbols = coff_symbols;
466   sdata->count = coff_symbol_count;
467
468   return 1;
469 }
470
471 /* Add EDATA to the list in STATE.  */
472
473 static void
474 coff_add_syminfo_data (struct backtrace_state *state,
475                        struct coff_syminfo_data *sdata)
476 {
477   if (!state->threaded)
478     {
479       struct coff_syminfo_data **pp;
480
481       for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
482            *pp != NULL;
483            pp = &(*pp)->next)
484         ;
485       *pp = sdata;
486     }
487   else
488     {
489       while (1)
490         {
491           struct coff_syminfo_data **pp;
492
493           pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
494
495           while (1)
496             {
497               struct coff_syminfo_data *p;
498
499               p = backtrace_atomic_load_pointer (pp);
500
501               if (p == NULL)
502                 break;
503
504               pp = &p->next;
505             }
506
507           if (__sync_bool_compare_and_swap (pp, NULL, sdata))
508             break;
509         }
510     }
511 }
512
513 /* Compare an ADDR against an elf_symbol for bsearch.  We allocate one
514    extra entry in the array so that this can look safely at the next
515    entry.  */
516
517 static int
518 coff_symbol_search (const void *vkey, const void *ventry)
519 {
520   const uintptr_t *key = (const uintptr_t *) vkey;
521   const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
522   uintptr_t addr;
523
524   addr = *key;
525   if (addr < entry->address)
526     return -1;
527   else if (addr >= entry[1].address)
528     return 1;
529   else
530     return 0;
531 }
532
533 /* Return the symbol name and value for an ADDR.  */
534
535 static void
536 coff_syminfo (struct backtrace_state *state, uintptr_t addr,
537               backtrace_syminfo_callback callback,
538               backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
539               void *data)
540 {
541   struct coff_syminfo_data *sdata;
542   struct coff_symbol *sym = NULL;
543
544   if (!state->threaded)
545     {
546       for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
547            sdata != NULL;
548            sdata = sdata->next)
549         {
550           sym = ((struct coff_symbol *)
551                  bsearch (&addr, sdata->symbols, sdata->count,
552                           sizeof (struct coff_symbol), coff_symbol_search));
553           if (sym != NULL)
554             break;
555         }
556     }
557   else
558     {
559       struct coff_syminfo_data **pp;
560
561       pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
562       while (1)
563         {
564           sdata = backtrace_atomic_load_pointer (pp);
565           if (sdata == NULL)
566             break;
567
568           sym = ((struct coff_symbol *)
569                  bsearch (&addr, sdata->symbols, sdata->count,
570                           sizeof (struct coff_symbol), coff_symbol_search));
571           if (sym != NULL)
572             break;
573
574           pp = &sdata->next;
575         }
576     }
577
578   if (sym == NULL)
579     callback (data, addr, NULL, 0, 0);
580   else
581     callback (data, addr, sym->name, sym->address, 0);
582 }
583
584 /* Add the backtrace data for one PE/COFF file.  Returns 1 on success,
585    0 on failure (in both cases descriptor is closed).  */
586
587 static int
588 coff_add (struct backtrace_state *state, int descriptor,
589           backtrace_error_callback error_callback, void *data,
590           fileline *fileline_fn, int *found_sym, int *found_dwarf)
591 {
592   struct backtrace_view fhdr_view;
593   off_t fhdr_off;
594   int magic_ok;
595   b_coff_file_header fhdr;
596   off_t opt_sects_off;
597   size_t opt_sects_size;
598   unsigned int sects_num;
599   struct backtrace_view sects_view;
600   int sects_view_valid;
601   const b_coff_optional_header *opt_hdr;
602   const b_coff_section_header *sects;
603   struct backtrace_view str_view;
604   int str_view_valid;
605   size_t str_size;
606   off_t str_off;
607   struct backtrace_view syms_view;
608   off_t syms_off;
609   size_t syms_size;
610   int syms_view_valid;
611   unsigned int syms_num;
612   unsigned int i;
613   struct debug_section_info sections[DEBUG_MAX];
614   off_t min_offset;
615   off_t max_offset;
616   struct backtrace_view debug_view;
617   int debug_view_valid;
618   uintptr_t image_base;
619
620   *found_sym = 0;
621   *found_dwarf = 0;
622
623   sects_view_valid = 0;
624   syms_view_valid = 0;
625   str_view_valid = 0;
626   debug_view_valid = 0;
627
628   /* Map the MS-DOS stub (if any) and extract file header offset.  */
629   if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
630                            data, &fhdr_view))
631     goto fail;
632
633   {
634     const char *vptr = (const char *)fhdr_view.data;
635
636     if (vptr[0] == 'M' && vptr[1] == 'Z')
637       memcpy (&fhdr_off, vptr + 0x3c, 4);
638     else
639       fhdr_off = 0;
640   }
641
642   backtrace_release_view (state, &fhdr_view, error_callback, data);
643
644   /* Map the coff file header.  */
645   if (!backtrace_get_view (state, descriptor, fhdr_off,
646                            sizeof (b_coff_file_header) + 4,
647                            error_callback, data, &fhdr_view))
648     goto fail;
649
650   if (fhdr_off != 0)
651     {
652       const char *magic = (const char *) fhdr_view.data;
653       magic_ok = memcmp (magic, "PE\0", 4) == 0;
654       fhdr_off += 4;
655
656       memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
657     }
658   else
659     {
660       memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
661       /* TODO: test fhdr.machine for coff but non-PE platforms.  */
662       magic_ok = 0;
663     }
664   backtrace_release_view (state, &fhdr_view, error_callback, data);
665
666   if (!magic_ok)
667     {
668       error_callback (data, "executable file is not COFF", 0);
669       goto fail;
670     }
671
672   sects_num = fhdr.number_of_sections;
673   syms_num = fhdr.number_of_symbols;
674
675   opt_sects_off = fhdr_off + sizeof (fhdr);
676   opt_sects_size = (fhdr.size_of_optional_header
677                     + sects_num * sizeof (b_coff_section_header));
678
679   /* To translate PC to file/line when using DWARF, we need to find
680      the .debug_info and .debug_line sections.  */
681
682   /* Read the optional header and the section headers.  */
683
684   if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
685                            error_callback, data, &sects_view))
686     goto fail;
687   sects_view_valid = 1;
688   opt_hdr = (const b_coff_optional_header *) sects_view.data;
689   sects = (const b_coff_section_header *)
690     (sects_view.data + fhdr.size_of_optional_header);
691
692   if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
693     {
694       if (opt_hdr->magic == PE_MAGIC)
695         image_base = opt_hdr->u.pe.image_base;
696       else if (opt_hdr->magic == PEP_MAGIC)
697         image_base = opt_hdr->u.pep.image_base;
698       else
699         {
700           error_callback (data, "bad magic in PE optional header", 0);
701           goto fail;
702         }
703     }
704   else
705     image_base = 0;
706
707   /* Read the symbol table and the string table.  */
708
709   if (fhdr.pointer_to_symbol_table == 0)
710     {
711       /* No symbol table, no string table.  */
712       str_off = 0;
713       str_size = 0;
714       syms_num = 0;
715       syms_size = 0;
716     }
717   else
718     {
719       /* Symbol table is followed by the string table.  The string table
720          starts with its length (on 4 bytes).
721          Map the symbol table and the length of the string table.  */
722       syms_off = fhdr.pointer_to_symbol_table;
723       syms_size = syms_num * SYM_SZ;
724
725       if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
726                                error_callback, data, &syms_view))
727         goto fail;
728       syms_view_valid = 1;
729
730       memcpy (&str_size, syms_view.data + syms_size, 4);
731
732       str_off = syms_off + syms_size;
733
734       if (str_size > 4)
735         {
736           /* Map string table (including the length word).  */
737
738           if (!backtrace_get_view (state, descriptor, str_off, str_size,
739                                    error_callback, data, &str_view))
740             goto fail;
741           str_view_valid = 1;
742         }
743     }
744
745   memset (sections, 0, sizeof sections);
746
747   /* Look for the symbol table.  */
748   for (i = 0; i < sects_num; ++i)
749     {
750       const b_coff_section_header *s = sects + i;
751       unsigned int str_off;
752       int j;
753
754       if (s->name[0] == '/')
755         {
756           /* Extended section name.  */
757           str_off = atoi (s->name + 1);
758         }
759       else
760         str_off = 0;
761
762       for (j = 0; j < (int) DEBUG_MAX; ++j)
763         {
764           const char *dbg_name = debug_section_names[j];
765           int match;
766
767           if (str_off != 0)
768             match = coff_long_name_eq (dbg_name, str_off, &str_view);
769           else
770             match = coff_short_name_eq (dbg_name, s->name);
771           if (match)
772             {
773               sections[j].offset = s->pointer_to_raw_data;
774               sections[j].size = s->virtual_size <= s->size_of_raw_data ?
775                 s->virtual_size : s->size_of_raw_data;
776               break;
777             }
778         }
779     }
780
781   if (syms_num != 0)
782     {
783       struct coff_syminfo_data *sdata;
784
785       sdata = ((struct coff_syminfo_data *)
786                backtrace_alloc (state, sizeof *sdata, error_callback, data));
787       if (sdata == NULL)
788         goto fail;
789
790       if (!coff_initialize_syminfo (state, image_base,
791                                     sects, sects_num,
792                                     syms_view.data, syms_size,
793                                     str_view.data, str_size,
794                                     error_callback, data, sdata))
795         {
796           backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
797           goto fail;
798         }
799
800       *found_sym = 1;
801
802       coff_add_syminfo_data (state, sdata);
803     }
804
805   backtrace_release_view (state, &sects_view, error_callback, data);
806   sects_view_valid = 0;
807   backtrace_release_view (state, &syms_view, error_callback, data);
808   syms_view_valid = 0;
809
810   /* Read all the debug sections in a single view, since they are
811      probably adjacent in the file.  We never release this view.  */
812
813   min_offset = 0;
814   max_offset = 0;
815   for (i = 0; i < (int) DEBUG_MAX; ++i)
816     {
817       off_t end;
818
819       if (sections[i].size == 0)
820         continue;
821       if (min_offset == 0 || sections[i].offset < min_offset)
822         min_offset = sections[i].offset;
823       end = sections[i].offset + sections[i].size;
824       if (end > max_offset)
825         max_offset = end;
826     }
827   if (min_offset == 0 || max_offset == 0)
828     {
829       if (!backtrace_close (descriptor, error_callback, data))
830         goto fail;
831       *fileline_fn = coff_nodebug;
832       return 1;
833     }
834
835   if (!backtrace_get_view (state, descriptor, min_offset,
836                            max_offset - min_offset,
837                            error_callback, data, &debug_view))
838     goto fail;
839   debug_view_valid = 1;
840
841   /* We've read all we need from the executable.  */
842   if (!backtrace_close (descriptor, error_callback, data))
843     goto fail;
844   descriptor = -1;
845
846   for (i = 0; i < (int) DEBUG_MAX; ++i)
847     {
848       if (sections[i].size == 0)
849         sections[i].data = NULL;
850       else
851         sections[i].data = ((const unsigned char *) debug_view.data
852                             + (sections[i].offset - min_offset));
853     }
854
855   if (!backtrace_dwarf_add (state, /* base_address */ 0,
856                             sections[DEBUG_INFO].data,
857                             sections[DEBUG_INFO].size,
858                             sections[DEBUG_LINE].data,
859                             sections[DEBUG_LINE].size,
860                             sections[DEBUG_ABBREV].data,
861                             sections[DEBUG_ABBREV].size,
862                             sections[DEBUG_RANGES].data,
863                             sections[DEBUG_RANGES].size,
864                             sections[DEBUG_STR].data,
865                             sections[DEBUG_STR].size,
866                             0, /* FIXME */
867                             error_callback, data, fileline_fn))
868     goto fail;
869
870   *found_dwarf = 1;
871
872   return 1;
873
874  fail:
875   if (sects_view_valid)
876     backtrace_release_view (state, &sects_view, error_callback, data);
877   if (str_view_valid)
878     backtrace_release_view (state, &str_view, error_callback, data);
879   if (syms_view_valid)
880     backtrace_release_view (state, &syms_view, error_callback, data);
881   if (debug_view_valid)
882     backtrace_release_view (state, &debug_view, error_callback, data);
883   if (descriptor != -1)
884     backtrace_close (descriptor, error_callback, data);
885   return 0;
886 }
887
888 /* Initialize the backtrace data we need from an ELF executable.  At
889    the ELF level, all we need to do is find the debug info
890    sections.  */
891
892 int
893 backtrace_initialize (struct backtrace_state *state, int descriptor,
894                       backtrace_error_callback error_callback,
895                       void *data, fileline *fileline_fn)
896 {
897   int ret;
898   int found_sym;
899   int found_dwarf;
900   fileline coff_fileline_fn;
901
902   ret = coff_add (state, descriptor, error_callback, data,
903                   &coff_fileline_fn, &found_sym, &found_dwarf);
904   if (!ret)
905     return 0;
906
907   if (!state->threaded)
908     {
909       if (found_sym)
910         state->syminfo_fn = coff_syminfo;
911       else if (state->syminfo_fn == NULL)
912         state->syminfo_fn = coff_nosyms;
913     }
914   else
915     {
916       if (found_sym)
917         backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
918       else
919         __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, coff_nosyms);
920     }
921
922   if (!state->threaded)
923     {
924       if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
925         *fileline_fn = coff_fileline_fn;
926     }
927   else
928     {
929       fileline current_fn;
930
931       current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
932       if (current_fn == NULL || current_fn == coff_nodebug)
933         *fileline_fn = coff_fileline_fn;
934     }
935
936   return 1;
937 }