(root)/
gcc-13.2.0/
libbacktrace/
pecoff.c
       1  /* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
       2     Copyright (C) 2015-2023 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  }