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
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY 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
44typedef 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
56typedef 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
83typedef 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
98typedef 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
108typedef 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
128typedef 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
138static 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
153struct 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
163struct 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
173struct 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
185static int
186coff_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
198static void
199coff_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
209static uint32_t
210coff_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
222static uint16_t
223coff_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
233static size_t
234coff_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
247static int
248coff_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
264static int
265coff_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
275static int
276coff_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
293static int
294coff_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
322static int
323coff_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
331static int
332coff_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
466static void
467coff_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
510static int
511coff_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
528static void
529coff_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
580static int
581coff_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
888int
889backtrace_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}
936