1 /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
2    Copyright (C) 2015-2019 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
coff_nodebug(struct backtrace_state * state ATTRIBUTE_UNUSED,uintptr_t pc ATTRIBUTE_UNUSED,backtrace_full_callback callback ATTRIBUTE_UNUSED,backtrace_error_callback error_callback,void * data)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
coff_nosyms(struct backtrace_state * state ATTRIBUTE_UNUSED,uintptr_t addr ATTRIBUTE_UNUSED,backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,backtrace_error_callback error_callback,void * data)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
coff_read4(const unsigned char * p)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
coff_read2(const unsigned char * p)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
coff_short_name_len(const char * name)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
coff_short_name_eq(const char * name,const char * cname)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
coff_long_name_eq(const char * name,unsigned int off,struct backtrace_view * str_view)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
coff_symbol_compare(const void * v1,const void * v2)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
coff_expand_symbol(b_coff_internal_symbol * isym,const b_coff_external_symbol * sym,uint16_t sects_num,const unsigned char * strtab,size_t strtab_size)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
coff_is_function_symbol(const b_coff_internal_symbol * isym)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
coff_initialize_syminfo(struct backtrace_state * state,uintptr_t base_address,const b_coff_section_header * sects,size_t sects_num,const b_coff_external_symbol * syms,size_t syms_size,const unsigned char * strtab,size_t strtab_size,backtrace_error_callback error_callback,void * data,struct coff_syminfo_data * sdata)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
coff_add_syminfo_data(struct backtrace_state * state,struct coff_syminfo_data * sdata)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
coff_symbol_search(const void * vkey,const void * ventry)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
coff_syminfo(struct backtrace_state * state,uintptr_t addr,backtrace_syminfo_callback callback,backtrace_error_callback error_callback ATTRIBUTE_UNUSED,void * data)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
coff_add(struct backtrace_state * state,int descriptor,backtrace_error_callback error_callback,void * data,fileline * fileline_fn,int * found_sym,int * found_dwarf)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 unsigned char *vptr = fhdr_view.data;
635 
636     if (vptr[0] == 'M' && vptr[1] == 'Z')
637       fhdr_off = coff_read4 (vptr + 0x3c);
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       str_size = coff_read4 (syms_view.data + syms_size);
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   if (syms_view_valid)
808     {
809       backtrace_release_view (state, &syms_view, error_callback, data);
810       syms_view_valid = 0;
811     }
812 
813   /* Read all the debug sections in a single view, since they are
814      probably adjacent in the file.  We never release this view.  */
815 
816   min_offset = 0;
817   max_offset = 0;
818   for (i = 0; i < (int) DEBUG_MAX; ++i)
819     {
820       off_t end;
821 
822       if (sections[i].size == 0)
823 	continue;
824       if (min_offset == 0 || sections[i].offset < min_offset)
825 	min_offset = sections[i].offset;
826       end = sections[i].offset + sections[i].size;
827       if (end > max_offset)
828 	max_offset = end;
829     }
830   if (min_offset == 0 || max_offset == 0)
831     {
832       if (!backtrace_close (descriptor, error_callback, data))
833 	goto fail;
834       *fileline_fn = coff_nodebug;
835       return 1;
836     }
837 
838   if (!backtrace_get_view (state, descriptor, min_offset,
839 			   max_offset - min_offset,
840 			   error_callback, data, &debug_view))
841     goto fail;
842   debug_view_valid = 1;
843 
844   /* We've read all we need from the executable.  */
845   if (!backtrace_close (descriptor, error_callback, data))
846     goto fail;
847   descriptor = -1;
848 
849   for (i = 0; i < (int) DEBUG_MAX; ++i)
850     {
851       if (sections[i].size == 0)
852 	sections[i].data = NULL;
853       else
854 	sections[i].data = ((const unsigned char *) debug_view.data
855 			    + (sections[i].offset - min_offset));
856     }
857 
858   if (!backtrace_dwarf_add (state, /* base_address */ 0,
859 			    sections[DEBUG_INFO].data,
860 			    sections[DEBUG_INFO].size,
861 			    sections[DEBUG_LINE].data,
862 			    sections[DEBUG_LINE].size,
863 			    sections[DEBUG_ABBREV].data,
864 			    sections[DEBUG_ABBREV].size,
865 			    sections[DEBUG_RANGES].data,
866 			    sections[DEBUG_RANGES].size,
867 			    sections[DEBUG_STR].data,
868 			    sections[DEBUG_STR].size,
869 			    0, /* FIXME */
870 			    NULL,
871 			    error_callback, data, fileline_fn,
872 			    NULL))
873     goto fail;
874 
875   *found_dwarf = 1;
876 
877   return 1;
878 
879  fail:
880   if (sects_view_valid)
881     backtrace_release_view (state, &sects_view, error_callback, data);
882   if (str_view_valid)
883     backtrace_release_view (state, &str_view, error_callback, data);
884   if (syms_view_valid)
885     backtrace_release_view (state, &syms_view, error_callback, data);
886   if (debug_view_valid)
887     backtrace_release_view (state, &debug_view, error_callback, data);
888   if (descriptor != -1)
889     backtrace_close (descriptor, error_callback, data);
890   return 0;
891 }
892 
893 /* Initialize the backtrace data we need from an ELF executable.  At
894    the ELF level, all we need to do is find the debug info
895    sections.  */
896 
897 int
backtrace_initialize(struct backtrace_state * state,const char * filename ATTRIBUTE_UNUSED,int descriptor,backtrace_error_callback error_callback,void * data,fileline * fileline_fn)898 backtrace_initialize (struct backtrace_state *state,
899 		      const char *filename ATTRIBUTE_UNUSED, int descriptor,
900 		      backtrace_error_callback error_callback,
901 		      void *data, fileline *fileline_fn)
902 {
903   int ret;
904   int found_sym;
905   int found_dwarf;
906   fileline coff_fileline_fn;
907 
908   ret = coff_add (state, descriptor, error_callback, data,
909 		  &coff_fileline_fn, &found_sym, &found_dwarf);
910   if (!ret)
911     return 0;
912 
913   if (!state->threaded)
914     {
915       if (found_sym)
916 	state->syminfo_fn = coff_syminfo;
917       else if (state->syminfo_fn == NULL)
918 	state->syminfo_fn = coff_nosyms;
919     }
920   else
921     {
922       if (found_sym)
923 	backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
924       else
925 	(void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
926 					     coff_nosyms);
927     }
928 
929   if (!state->threaded)
930     {
931       if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
932 	*fileline_fn = coff_fileline_fn;
933     }
934   else
935     {
936       fileline current_fn;
937 
938       current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
939       if (current_fn == NULL || current_fn == coff_nodebug)
940 	*fileline_fn = coff_fileline_fn;
941     }
942 
943   return 1;
944 }
945