163d1a8abSmrg /* dwarf.c -- Get file/line information from DWARF for backtraces.
2*ec02198aSmrg    Copyright (C) 2012-2020 Free Software Foundation, Inc.
363d1a8abSmrg    Written by Ian Lance Taylor, Google.
463d1a8abSmrg 
563d1a8abSmrg Redistribution and use in source and binary forms, with or without
663d1a8abSmrg modification, are permitted provided that the following conditions are
763d1a8abSmrg met:
863d1a8abSmrg 
963d1a8abSmrg     (1) Redistributions of source code must retain the above copyright
1063d1a8abSmrg     notice, this list of conditions and the following disclaimer.
1163d1a8abSmrg 
1263d1a8abSmrg     (2) Redistributions in binary form must reproduce the above copyright
1363d1a8abSmrg     notice, this list of conditions and the following disclaimer in
1463d1a8abSmrg     the documentation and/or other materials provided with the
1563d1a8abSmrg     distribution.
1663d1a8abSmrg 
1763d1a8abSmrg     (3) The name of the author may not be used to
1863d1a8abSmrg     endorse or promote products derived from this software without
1963d1a8abSmrg     specific prior written permission.
2063d1a8abSmrg 
2163d1a8abSmrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2263d1a8abSmrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2363d1a8abSmrg WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2463d1a8abSmrg DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2563d1a8abSmrg INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2663d1a8abSmrg (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2763d1a8abSmrg SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2863d1a8abSmrg HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2963d1a8abSmrg STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3063d1a8abSmrg IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3163d1a8abSmrg POSSIBILITY OF SUCH DAMAGE.  */
3263d1a8abSmrg 
3363d1a8abSmrg #include "config.h"
3463d1a8abSmrg 
3563d1a8abSmrg #include <errno.h>
3663d1a8abSmrg #include <stdlib.h>
3763d1a8abSmrg #include <string.h>
3863d1a8abSmrg #include <sys/types.h>
3963d1a8abSmrg 
4063d1a8abSmrg #include "dwarf2.h"
4163d1a8abSmrg #include "filenames.h"
4263d1a8abSmrg 
4363d1a8abSmrg #include "backtrace.h"
4463d1a8abSmrg #include "internal.h"
4563d1a8abSmrg 
4663d1a8abSmrg #if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
4763d1a8abSmrg 
4863d1a8abSmrg /* If strnlen is not declared, provide our own version.  */
4963d1a8abSmrg 
5063d1a8abSmrg static size_t
xstrnlen(const char * s,size_t maxlen)5163d1a8abSmrg xstrnlen (const char *s, size_t maxlen)
5263d1a8abSmrg {
5363d1a8abSmrg   size_t i;
5463d1a8abSmrg 
5563d1a8abSmrg   for (i = 0; i < maxlen; ++i)
5663d1a8abSmrg     if (s[i] == '\0')
5763d1a8abSmrg       break;
5863d1a8abSmrg   return i;
5963d1a8abSmrg }
6063d1a8abSmrg 
6163d1a8abSmrg #define strnlen xstrnlen
6263d1a8abSmrg 
6363d1a8abSmrg #endif
6463d1a8abSmrg 
6563d1a8abSmrg /* A buffer to read DWARF info.  */
6663d1a8abSmrg 
6763d1a8abSmrg struct dwarf_buf
6863d1a8abSmrg {
6963d1a8abSmrg   /* Buffer name for error messages.  */
7063d1a8abSmrg   const char *name;
7163d1a8abSmrg   /* Start of the buffer.  */
7263d1a8abSmrg   const unsigned char *start;
7363d1a8abSmrg   /* Next byte to read.  */
7463d1a8abSmrg   const unsigned char *buf;
7563d1a8abSmrg   /* The number of bytes remaining.  */
7663d1a8abSmrg   size_t left;
7763d1a8abSmrg   /* Whether the data is big-endian.  */
7863d1a8abSmrg   int is_bigendian;
7963d1a8abSmrg   /* Error callback routine.  */
8063d1a8abSmrg   backtrace_error_callback error_callback;
8163d1a8abSmrg   /* Data for error_callback.  */
8263d1a8abSmrg   void *data;
8363d1a8abSmrg   /* Non-zero if we've reported an underflow error.  */
8463d1a8abSmrg   int reported_underflow;
8563d1a8abSmrg };
8663d1a8abSmrg 
8763d1a8abSmrg /* A single attribute in a DWARF abbreviation.  */
8863d1a8abSmrg 
8963d1a8abSmrg struct attr
9063d1a8abSmrg {
9163d1a8abSmrg   /* The attribute name.  */
9263d1a8abSmrg   enum dwarf_attribute name;
9363d1a8abSmrg   /* The attribute form.  */
9463d1a8abSmrg   enum dwarf_form form;
95*ec02198aSmrg   /* The attribute value, for DW_FORM_implicit_const.  */
96*ec02198aSmrg   int64_t val;
9763d1a8abSmrg };
9863d1a8abSmrg 
9963d1a8abSmrg /* A single DWARF abbreviation.  */
10063d1a8abSmrg 
10163d1a8abSmrg struct abbrev
10263d1a8abSmrg {
10363d1a8abSmrg   /* The abbrev code--the number used to refer to the abbrev.  */
10463d1a8abSmrg   uint64_t code;
10563d1a8abSmrg   /* The entry tag.  */
10663d1a8abSmrg   enum dwarf_tag tag;
10763d1a8abSmrg   /* Non-zero if this abbrev has child entries.  */
10863d1a8abSmrg   int has_children;
10963d1a8abSmrg   /* The number of attributes.  */
11063d1a8abSmrg   size_t num_attrs;
11163d1a8abSmrg   /* The attributes.  */
11263d1a8abSmrg   struct attr *attrs;
11363d1a8abSmrg };
11463d1a8abSmrg 
11563d1a8abSmrg /* The DWARF abbreviations for a compilation unit.  This structure
11663d1a8abSmrg    only exists while reading the compilation unit.  Most DWARF readers
11763d1a8abSmrg    seem to a hash table to map abbrev ID's to abbrev entries.
11863d1a8abSmrg    However, we primarily care about GCC, and GCC simply issues ID's in
11963d1a8abSmrg    numerical order starting at 1.  So we simply keep a sorted vector,
12063d1a8abSmrg    and try to just look up the code.  */
12163d1a8abSmrg 
12263d1a8abSmrg struct abbrevs
12363d1a8abSmrg {
12463d1a8abSmrg   /* The number of abbrevs in the vector.  */
12563d1a8abSmrg   size_t num_abbrevs;
12663d1a8abSmrg   /* The abbrevs, sorted by the code field.  */
12763d1a8abSmrg   struct abbrev *abbrevs;
12863d1a8abSmrg };
12963d1a8abSmrg 
13063d1a8abSmrg /* The different kinds of attribute values.  */
13163d1a8abSmrg 
13263d1a8abSmrg enum attr_val_encoding
13363d1a8abSmrg {
1340fc04c29Smrg   /* No attribute value.  */
1350fc04c29Smrg   ATTR_VAL_NONE,
13663d1a8abSmrg   /* An address.  */
13763d1a8abSmrg   ATTR_VAL_ADDRESS,
138*ec02198aSmrg   /* An index into the .debug_addr section, whose value is relative to
139*ec02198aSmrg    * the DW_AT_addr_base attribute of the compilation unit.  */
140*ec02198aSmrg   ATTR_VAL_ADDRESS_INDEX,
14163d1a8abSmrg   /* A unsigned integer.  */
14263d1a8abSmrg   ATTR_VAL_UINT,
14363d1a8abSmrg   /* A sigd integer.  */
14463d1a8abSmrg   ATTR_VAL_SINT,
14563d1a8abSmrg   /* A string.  */
14663d1a8abSmrg   ATTR_VAL_STRING,
147*ec02198aSmrg   /* An index into the .debug_str_offsets section.  */
148*ec02198aSmrg   ATTR_VAL_STRING_INDEX,
14963d1a8abSmrg   /* An offset to other data in the containing unit.  */
15063d1a8abSmrg   ATTR_VAL_REF_UNIT,
151*ec02198aSmrg   /* An offset to other data within the .debug_info section.  */
15263d1a8abSmrg   ATTR_VAL_REF_INFO,
153*ec02198aSmrg   /* An offset to other data within the alt .debug_info section.  */
1540fc04c29Smrg   ATTR_VAL_REF_ALT_INFO,
15563d1a8abSmrg   /* An offset to data in some other section.  */
15663d1a8abSmrg   ATTR_VAL_REF_SECTION,
15763d1a8abSmrg   /* A type signature.  */
15863d1a8abSmrg   ATTR_VAL_REF_TYPE,
159*ec02198aSmrg   /* An index into the .debug_rnglists section.  */
160*ec02198aSmrg   ATTR_VAL_RNGLISTS_INDEX,
16163d1a8abSmrg   /* A block of data (not represented).  */
16263d1a8abSmrg   ATTR_VAL_BLOCK,
16363d1a8abSmrg   /* An expression (not represented).  */
16463d1a8abSmrg   ATTR_VAL_EXPR,
16563d1a8abSmrg };
16663d1a8abSmrg 
16763d1a8abSmrg /* An attribute value.  */
16863d1a8abSmrg 
16963d1a8abSmrg struct attr_val
17063d1a8abSmrg {
17163d1a8abSmrg   /* How the value is stored in the field u.  */
17263d1a8abSmrg   enum attr_val_encoding encoding;
17363d1a8abSmrg   union
17463d1a8abSmrg   {
175*ec02198aSmrg     /* ATTR_VAL_ADDRESS*, ATTR_VAL_UINT, ATTR_VAL_REF*.  */
17663d1a8abSmrg     uint64_t uint;
17763d1a8abSmrg     /* ATTR_VAL_SINT.  */
17863d1a8abSmrg     int64_t sint;
17963d1a8abSmrg     /* ATTR_VAL_STRING.  */
18063d1a8abSmrg     const char *string;
18163d1a8abSmrg     /* ATTR_VAL_BLOCK not stored.  */
18263d1a8abSmrg   } u;
18363d1a8abSmrg };
18463d1a8abSmrg 
18563d1a8abSmrg /* The line number program header.  */
18663d1a8abSmrg 
18763d1a8abSmrg struct line_header
18863d1a8abSmrg {
18963d1a8abSmrg   /* The version of the line number information.  */
19063d1a8abSmrg   int version;
191*ec02198aSmrg   /* Address size.  */
192*ec02198aSmrg   int addrsize;
19363d1a8abSmrg   /* The minimum instruction length.  */
19463d1a8abSmrg   unsigned int min_insn_len;
19563d1a8abSmrg   /* The maximum number of ops per instruction.  */
19663d1a8abSmrg   unsigned int max_ops_per_insn;
19763d1a8abSmrg   /* The line base for special opcodes.  */
19863d1a8abSmrg   int line_base;
19963d1a8abSmrg   /* The line range for special opcodes.  */
20063d1a8abSmrg   unsigned int line_range;
20163d1a8abSmrg   /* The opcode base--the first special opcode.  */
20263d1a8abSmrg   unsigned int opcode_base;
20363d1a8abSmrg   /* Opcode lengths, indexed by opcode - 1.  */
20463d1a8abSmrg   const unsigned char *opcode_lengths;
20563d1a8abSmrg   /* The number of directory entries.  */
20663d1a8abSmrg   size_t dirs_count;
20763d1a8abSmrg   /* The directory entries.  */
20863d1a8abSmrg   const char **dirs;
20963d1a8abSmrg   /* The number of filenames.  */
21063d1a8abSmrg   size_t filenames_count;
21163d1a8abSmrg   /* The filenames.  */
21263d1a8abSmrg   const char **filenames;
21363d1a8abSmrg };
21463d1a8abSmrg 
215*ec02198aSmrg /* A format description from a line header.  */
216*ec02198aSmrg 
217*ec02198aSmrg struct line_header_format
218*ec02198aSmrg {
219*ec02198aSmrg   int lnct;		/* LNCT code.  */
220*ec02198aSmrg   enum dwarf_form form;	/* Form of entry data.  */
221*ec02198aSmrg };
222*ec02198aSmrg 
22363d1a8abSmrg /* Map a single PC value to a file/line.  We will keep a vector of
22463d1a8abSmrg    these sorted by PC value.  Each file/line will be correct from the
22563d1a8abSmrg    PC up to the PC of the next entry if there is one.  We allocate one
22663d1a8abSmrg    extra entry at the end so that we can use bsearch.  */
22763d1a8abSmrg 
22863d1a8abSmrg struct line
22963d1a8abSmrg {
23063d1a8abSmrg   /* PC.  */
23163d1a8abSmrg   uintptr_t pc;
23263d1a8abSmrg   /* File name.  Many entries in the array are expected to point to
23363d1a8abSmrg      the same file name.  */
23463d1a8abSmrg   const char *filename;
23563d1a8abSmrg   /* Line number.  */
23663d1a8abSmrg   int lineno;
23763d1a8abSmrg   /* Index of the object in the original array read from the DWARF
23863d1a8abSmrg      section, before it has been sorted.  The index makes it possible
23963d1a8abSmrg      to use Quicksort and maintain stability.  */
24063d1a8abSmrg   int idx;
24163d1a8abSmrg };
24263d1a8abSmrg 
24363d1a8abSmrg /* A growable vector of line number information.  This is used while
24463d1a8abSmrg    reading the line numbers.  */
24563d1a8abSmrg 
24663d1a8abSmrg struct line_vector
24763d1a8abSmrg {
24863d1a8abSmrg   /* Memory.  This is an array of struct line.  */
24963d1a8abSmrg   struct backtrace_vector vec;
25063d1a8abSmrg   /* Number of valid mappings.  */
25163d1a8abSmrg   size_t count;
25263d1a8abSmrg };
25363d1a8abSmrg 
25463d1a8abSmrg /* A function described in the debug info.  */
25563d1a8abSmrg 
25663d1a8abSmrg struct function
25763d1a8abSmrg {
25863d1a8abSmrg   /* The name of the function.  */
25963d1a8abSmrg   const char *name;
26063d1a8abSmrg   /* If this is an inlined function, the filename of the call
26163d1a8abSmrg      site.  */
26263d1a8abSmrg   const char *caller_filename;
26363d1a8abSmrg   /* If this is an inlined function, the line number of the call
26463d1a8abSmrg      site.  */
26563d1a8abSmrg   int caller_lineno;
26663d1a8abSmrg   /* Map PC ranges to inlined functions.  */
26763d1a8abSmrg   struct function_addrs *function_addrs;
26863d1a8abSmrg   size_t function_addrs_count;
26963d1a8abSmrg };
27063d1a8abSmrg 
27163d1a8abSmrg /* An address range for a function.  This maps a PC value to a
27263d1a8abSmrg    specific function.  */
27363d1a8abSmrg 
27463d1a8abSmrg struct function_addrs
27563d1a8abSmrg {
27663d1a8abSmrg   /* Range is LOW <= PC < HIGH.  */
27763d1a8abSmrg   uint64_t low;
27863d1a8abSmrg   uint64_t high;
27963d1a8abSmrg   /* Function for this address range.  */
28063d1a8abSmrg   struct function *function;
28163d1a8abSmrg };
28263d1a8abSmrg 
28363d1a8abSmrg /* A growable vector of function address ranges.  */
28463d1a8abSmrg 
28563d1a8abSmrg struct function_vector
28663d1a8abSmrg {
28763d1a8abSmrg   /* Memory.  This is an array of struct function_addrs.  */
28863d1a8abSmrg   struct backtrace_vector vec;
28963d1a8abSmrg   /* Number of address ranges present.  */
29063d1a8abSmrg   size_t count;
29163d1a8abSmrg };
29263d1a8abSmrg 
29363d1a8abSmrg /* A DWARF compilation unit.  This only holds the information we need
29463d1a8abSmrg    to map a PC to a file and line.  */
29563d1a8abSmrg 
29663d1a8abSmrg struct unit
29763d1a8abSmrg {
29863d1a8abSmrg   /* The first entry for this compilation unit.  */
29963d1a8abSmrg   const unsigned char *unit_data;
30063d1a8abSmrg   /* The length of the data for this compilation unit.  */
30163d1a8abSmrg   size_t unit_data_len;
30263d1a8abSmrg   /* The offset of UNIT_DATA from the start of the information for
30363d1a8abSmrg      this compilation unit.  */
30463d1a8abSmrg   size_t unit_data_offset;
3050fc04c29Smrg   /* Offset of the start of the compilation unit from the start of the
3060fc04c29Smrg      .debug_info section.  */
3070fc04c29Smrg   size_t low_offset;
3080fc04c29Smrg   /* Offset of the end of the compilation unit from the start of the
3090fc04c29Smrg      .debug_info section.  */
3100fc04c29Smrg   size_t high_offset;
31163d1a8abSmrg   /* DWARF version.  */
31263d1a8abSmrg   int version;
31363d1a8abSmrg   /* Whether unit is DWARF64.  */
31463d1a8abSmrg   int is_dwarf64;
31563d1a8abSmrg   /* Address size.  */
31663d1a8abSmrg   int addrsize;
31763d1a8abSmrg   /* Offset into line number information.  */
31863d1a8abSmrg   off_t lineoff;
319*ec02198aSmrg   /* Offset of compilation unit in .debug_str_offsets.  */
320*ec02198aSmrg   uint64_t str_offsets_base;
321*ec02198aSmrg   /* Offset of compilation unit in .debug_addr.  */
322*ec02198aSmrg   uint64_t addr_base;
323*ec02198aSmrg   /* Offset of compilation unit in .debug_rnglists.  */
324*ec02198aSmrg   uint64_t rnglists_base;
32563d1a8abSmrg   /* Primary source file.  */
32663d1a8abSmrg   const char *filename;
32763d1a8abSmrg   /* Compilation command working directory.  */
32863d1a8abSmrg   const char *comp_dir;
32963d1a8abSmrg   /* Absolute file name, only set if needed.  */
33063d1a8abSmrg   const char *abs_filename;
33163d1a8abSmrg   /* The abbreviations for this unit.  */
33263d1a8abSmrg   struct abbrevs abbrevs;
33363d1a8abSmrg 
33463d1a8abSmrg   /* The fields above this point are read in during initialization and
33563d1a8abSmrg      may be accessed freely.  The fields below this point are read in
33663d1a8abSmrg      as needed, and therefore require care, as different threads may
33763d1a8abSmrg      try to initialize them simultaneously.  */
33863d1a8abSmrg 
33963d1a8abSmrg   /* PC to line number mapping.  This is NULL if the values have not
34063d1a8abSmrg      been read.  This is (struct line *) -1 if there was an error
34163d1a8abSmrg      reading the values.  */
34263d1a8abSmrg   struct line *lines;
34363d1a8abSmrg   /* Number of entries in lines.  */
34463d1a8abSmrg   size_t lines_count;
34563d1a8abSmrg   /* PC ranges to function.  */
34663d1a8abSmrg   struct function_addrs *function_addrs;
34763d1a8abSmrg   size_t function_addrs_count;
34863d1a8abSmrg };
34963d1a8abSmrg 
35063d1a8abSmrg /* An address range for a compilation unit.  This maps a PC value to a
35163d1a8abSmrg    specific compilation unit.  Note that we invert the representation
35263d1a8abSmrg    in DWARF: instead of listing the units and attaching a list of
35363d1a8abSmrg    ranges, we list the ranges and have each one point to the unit.
35463d1a8abSmrg    This lets us do a binary search to find the unit.  */
35563d1a8abSmrg 
35663d1a8abSmrg struct unit_addrs
35763d1a8abSmrg {
35863d1a8abSmrg   /* Range is LOW <= PC < HIGH.  */
35963d1a8abSmrg   uint64_t low;
36063d1a8abSmrg   uint64_t high;
36163d1a8abSmrg   /* Compilation unit for this address range.  */
36263d1a8abSmrg   struct unit *u;
36363d1a8abSmrg };
36463d1a8abSmrg 
36563d1a8abSmrg /* A growable vector of compilation unit address ranges.  */
36663d1a8abSmrg 
36763d1a8abSmrg struct unit_addrs_vector
36863d1a8abSmrg {
36963d1a8abSmrg   /* Memory.  This is an array of struct unit_addrs.  */
37063d1a8abSmrg   struct backtrace_vector vec;
37163d1a8abSmrg   /* Number of address ranges present.  */
37263d1a8abSmrg   size_t count;
37363d1a8abSmrg };
37463d1a8abSmrg 
3750fc04c29Smrg /* A growable vector of compilation unit pointer.  */
3760fc04c29Smrg 
3770fc04c29Smrg struct unit_vector
3780fc04c29Smrg {
3790fc04c29Smrg   struct backtrace_vector vec;
3800fc04c29Smrg   size_t count;
3810fc04c29Smrg };
3820fc04c29Smrg 
38363d1a8abSmrg /* The information we need to map a PC to a file and line.  */
38463d1a8abSmrg 
38563d1a8abSmrg struct dwarf_data
38663d1a8abSmrg {
38763d1a8abSmrg   /* The data for the next file we know about.  */
38863d1a8abSmrg   struct dwarf_data *next;
3890fc04c29Smrg   /* The data for .gnu_debugaltlink.  */
3900fc04c29Smrg   struct dwarf_data *altlink;
39163d1a8abSmrg   /* The base address for this file.  */
39263d1a8abSmrg   uintptr_t base_address;
39363d1a8abSmrg   /* A sorted list of address ranges.  */
39463d1a8abSmrg   struct unit_addrs *addrs;
39563d1a8abSmrg   /* Number of address ranges in list.  */
39663d1a8abSmrg   size_t addrs_count;
3970fc04c29Smrg   /* A sorted list of units.  */
3980fc04c29Smrg   struct unit **units;
3990fc04c29Smrg   /* Number of units in the list.  */
4000fc04c29Smrg   size_t units_count;
401*ec02198aSmrg   /* The unparsed DWARF debug data.  */
402*ec02198aSmrg   struct dwarf_sections dwarf_sections;
40363d1a8abSmrg   /* Whether the data is big-endian or not.  */
40463d1a8abSmrg   int is_bigendian;
40563d1a8abSmrg   /* A vector used for function addresses.  We keep this here so that
40663d1a8abSmrg      we can grow the vector as we read more functions.  */
40763d1a8abSmrg   struct function_vector fvec;
40863d1a8abSmrg };
40963d1a8abSmrg 
41063d1a8abSmrg /* Report an error for a DWARF buffer.  */
41163d1a8abSmrg 
41263d1a8abSmrg static void
dwarf_buf_error(struct dwarf_buf * buf,const char * msg)41363d1a8abSmrg dwarf_buf_error (struct dwarf_buf *buf, const char *msg)
41463d1a8abSmrg {
41563d1a8abSmrg   char b[200];
41663d1a8abSmrg 
41763d1a8abSmrg   snprintf (b, sizeof b, "%s in %s at %d",
41863d1a8abSmrg 	    msg, buf->name, (int) (buf->buf - buf->start));
41963d1a8abSmrg   buf->error_callback (buf->data, b, 0);
42063d1a8abSmrg }
42163d1a8abSmrg 
42263d1a8abSmrg /* Require at least COUNT bytes in BUF.  Return 1 if all is well, 0 on
42363d1a8abSmrg    error.  */
42463d1a8abSmrg 
42563d1a8abSmrg static int
require(struct dwarf_buf * buf,size_t count)42663d1a8abSmrg require (struct dwarf_buf *buf, size_t count)
42763d1a8abSmrg {
42863d1a8abSmrg   if (buf->left >= count)
42963d1a8abSmrg     return 1;
43063d1a8abSmrg 
43163d1a8abSmrg   if (!buf->reported_underflow)
43263d1a8abSmrg     {
43363d1a8abSmrg       dwarf_buf_error (buf, "DWARF underflow");
43463d1a8abSmrg       buf->reported_underflow = 1;
43563d1a8abSmrg     }
43663d1a8abSmrg 
43763d1a8abSmrg   return 0;
43863d1a8abSmrg }
43963d1a8abSmrg 
44063d1a8abSmrg /* Advance COUNT bytes in BUF.  Return 1 if all is well, 0 on
44163d1a8abSmrg    error.  */
44263d1a8abSmrg 
44363d1a8abSmrg static int
advance(struct dwarf_buf * buf,size_t count)44463d1a8abSmrg advance (struct dwarf_buf *buf, size_t count)
44563d1a8abSmrg {
44663d1a8abSmrg   if (!require (buf, count))
44763d1a8abSmrg     return 0;
44863d1a8abSmrg   buf->buf += count;
44963d1a8abSmrg   buf->left -= count;
45063d1a8abSmrg   return 1;
45163d1a8abSmrg }
45263d1a8abSmrg 
4530fc04c29Smrg /* Read one zero-terminated string from BUF and advance past the string.  */
4540fc04c29Smrg 
4550fc04c29Smrg static const char *
read_string(struct dwarf_buf * buf)4560fc04c29Smrg read_string (struct dwarf_buf *buf)
4570fc04c29Smrg {
4580fc04c29Smrg   const char *p = (const char *)buf->buf;
4590fc04c29Smrg   size_t len = strnlen (p, buf->left);
4600fc04c29Smrg 
4610fc04c29Smrg   /* - If len == left, we ran out of buffer before finding the zero terminator.
4620fc04c29Smrg        Generate an error by advancing len + 1.
4630fc04c29Smrg      - If len < left, advance by len + 1 to skip past the zero terminator.  */
4640fc04c29Smrg   size_t count = len + 1;
4650fc04c29Smrg 
4660fc04c29Smrg   if (!advance (buf, count))
4670fc04c29Smrg     return NULL;
4680fc04c29Smrg 
4690fc04c29Smrg   return p;
4700fc04c29Smrg }
4710fc04c29Smrg 
47263d1a8abSmrg /* Read one byte from BUF and advance 1 byte.  */
47363d1a8abSmrg 
47463d1a8abSmrg static unsigned char
read_byte(struct dwarf_buf * buf)47563d1a8abSmrg read_byte (struct dwarf_buf *buf)
47663d1a8abSmrg {
47763d1a8abSmrg   const unsigned char *p = buf->buf;
47863d1a8abSmrg 
47963d1a8abSmrg   if (!advance (buf, 1))
48063d1a8abSmrg     return 0;
48163d1a8abSmrg   return p[0];
48263d1a8abSmrg }
48363d1a8abSmrg 
48463d1a8abSmrg /* Read a signed char from BUF and advance 1 byte.  */
48563d1a8abSmrg 
48663d1a8abSmrg static signed char
read_sbyte(struct dwarf_buf * buf)48763d1a8abSmrg read_sbyte (struct dwarf_buf *buf)
48863d1a8abSmrg {
48963d1a8abSmrg   const unsigned char *p = buf->buf;
49063d1a8abSmrg 
49163d1a8abSmrg   if (!advance (buf, 1))
49263d1a8abSmrg     return 0;
49363d1a8abSmrg   return (*p ^ 0x80) - 0x80;
49463d1a8abSmrg }
49563d1a8abSmrg 
49663d1a8abSmrg /* Read a uint16 from BUF and advance 2 bytes.  */
49763d1a8abSmrg 
49863d1a8abSmrg static uint16_t
read_uint16(struct dwarf_buf * buf)49963d1a8abSmrg read_uint16 (struct dwarf_buf *buf)
50063d1a8abSmrg {
50163d1a8abSmrg   const unsigned char *p = buf->buf;
50263d1a8abSmrg 
50363d1a8abSmrg   if (!advance (buf, 2))
50463d1a8abSmrg     return 0;
50563d1a8abSmrg   if (buf->is_bigendian)
50663d1a8abSmrg     return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
50763d1a8abSmrg   else
50863d1a8abSmrg     return ((uint16_t) p[1] << 8) | (uint16_t) p[0];
50963d1a8abSmrg }
51063d1a8abSmrg 
511*ec02198aSmrg /* Read a 24 bit value from BUF and advance 3 bytes.  */
512*ec02198aSmrg 
513*ec02198aSmrg static uint32_t
read_uint24(struct dwarf_buf * buf)514*ec02198aSmrg read_uint24 (struct dwarf_buf *buf)
515*ec02198aSmrg {
516*ec02198aSmrg   const unsigned char *p = buf->buf;
517*ec02198aSmrg 
518*ec02198aSmrg   if (!advance (buf, 3))
519*ec02198aSmrg     return 0;
520*ec02198aSmrg   if (buf->is_bigendian)
521*ec02198aSmrg     return (((uint32_t) p[0] << 16) | ((uint32_t) p[1] << 8)
522*ec02198aSmrg 	    | (uint32_t) p[2]);
523*ec02198aSmrg   else
524*ec02198aSmrg     return (((uint32_t) p[2] << 16) | ((uint32_t) p[1] << 8)
525*ec02198aSmrg 	    | (uint32_t) p[0]);
526*ec02198aSmrg }
527*ec02198aSmrg 
52863d1a8abSmrg /* Read a uint32 from BUF and advance 4 bytes.  */
52963d1a8abSmrg 
53063d1a8abSmrg static uint32_t
read_uint32(struct dwarf_buf * buf)53163d1a8abSmrg read_uint32 (struct dwarf_buf *buf)
53263d1a8abSmrg {
53363d1a8abSmrg   const unsigned char *p = buf->buf;
53463d1a8abSmrg 
53563d1a8abSmrg   if (!advance (buf, 4))
53663d1a8abSmrg     return 0;
53763d1a8abSmrg   if (buf->is_bigendian)
53863d1a8abSmrg     return (((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16)
53963d1a8abSmrg 	    | ((uint32_t) p[2] << 8) | (uint32_t) p[3]);
54063d1a8abSmrg   else
54163d1a8abSmrg     return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16)
54263d1a8abSmrg 	    | ((uint32_t) p[1] << 8) | (uint32_t) p[0]);
54363d1a8abSmrg }
54463d1a8abSmrg 
54563d1a8abSmrg /* Read a uint64 from BUF and advance 8 bytes.  */
54663d1a8abSmrg 
54763d1a8abSmrg static uint64_t
read_uint64(struct dwarf_buf * buf)54863d1a8abSmrg read_uint64 (struct dwarf_buf *buf)
54963d1a8abSmrg {
55063d1a8abSmrg   const unsigned char *p = buf->buf;
55163d1a8abSmrg 
55263d1a8abSmrg   if (!advance (buf, 8))
55363d1a8abSmrg     return 0;
55463d1a8abSmrg   if (buf->is_bigendian)
55563d1a8abSmrg     return (((uint64_t) p[0] << 56) | ((uint64_t) p[1] << 48)
55663d1a8abSmrg 	    | ((uint64_t) p[2] << 40) | ((uint64_t) p[3] << 32)
55763d1a8abSmrg 	    | ((uint64_t) p[4] << 24) | ((uint64_t) p[5] << 16)
55863d1a8abSmrg 	    | ((uint64_t) p[6] << 8) | (uint64_t) p[7]);
55963d1a8abSmrg   else
56063d1a8abSmrg     return (((uint64_t) p[7] << 56) | ((uint64_t) p[6] << 48)
56163d1a8abSmrg 	    | ((uint64_t) p[5] << 40) | ((uint64_t) p[4] << 32)
56263d1a8abSmrg 	    | ((uint64_t) p[3] << 24) | ((uint64_t) p[2] << 16)
56363d1a8abSmrg 	    | ((uint64_t) p[1] << 8) | (uint64_t) p[0]);
56463d1a8abSmrg }
56563d1a8abSmrg 
56663d1a8abSmrg /* Read an offset from BUF and advance the appropriate number of
56763d1a8abSmrg    bytes.  */
56863d1a8abSmrg 
56963d1a8abSmrg static uint64_t
read_offset(struct dwarf_buf * buf,int is_dwarf64)57063d1a8abSmrg read_offset (struct dwarf_buf *buf, int is_dwarf64)
57163d1a8abSmrg {
57263d1a8abSmrg   if (is_dwarf64)
57363d1a8abSmrg     return read_uint64 (buf);
57463d1a8abSmrg   else
57563d1a8abSmrg     return read_uint32 (buf);
57663d1a8abSmrg }
57763d1a8abSmrg 
57863d1a8abSmrg /* Read an address from BUF and advance the appropriate number of
57963d1a8abSmrg    bytes.  */
58063d1a8abSmrg 
58163d1a8abSmrg static uint64_t
read_address(struct dwarf_buf * buf,int addrsize)58263d1a8abSmrg read_address (struct dwarf_buf *buf, int addrsize)
58363d1a8abSmrg {
58463d1a8abSmrg   switch (addrsize)
58563d1a8abSmrg     {
58663d1a8abSmrg     case 1:
58763d1a8abSmrg       return read_byte (buf);
58863d1a8abSmrg     case 2:
58963d1a8abSmrg       return read_uint16 (buf);
59063d1a8abSmrg     case 4:
59163d1a8abSmrg       return read_uint32 (buf);
59263d1a8abSmrg     case 8:
59363d1a8abSmrg       return read_uint64 (buf);
59463d1a8abSmrg     default:
59563d1a8abSmrg       dwarf_buf_error (buf, "unrecognized address size");
59663d1a8abSmrg       return 0;
59763d1a8abSmrg     }
59863d1a8abSmrg }
59963d1a8abSmrg 
60063d1a8abSmrg /* Return whether a value is the highest possible address, given the
60163d1a8abSmrg    address size.  */
60263d1a8abSmrg 
60363d1a8abSmrg static int
is_highest_address(uint64_t address,int addrsize)60463d1a8abSmrg is_highest_address (uint64_t address, int addrsize)
60563d1a8abSmrg {
60663d1a8abSmrg   switch (addrsize)
60763d1a8abSmrg     {
60863d1a8abSmrg     case 1:
60963d1a8abSmrg       return address == (unsigned char) -1;
61063d1a8abSmrg     case 2:
61163d1a8abSmrg       return address == (uint16_t) -1;
61263d1a8abSmrg     case 4:
61363d1a8abSmrg       return address == (uint32_t) -1;
61463d1a8abSmrg     case 8:
61563d1a8abSmrg       return address == (uint64_t) -1;
61663d1a8abSmrg     default:
61763d1a8abSmrg       return 0;
61863d1a8abSmrg     }
61963d1a8abSmrg }
62063d1a8abSmrg 
62163d1a8abSmrg /* Read an unsigned LEB128 number.  */
62263d1a8abSmrg 
62363d1a8abSmrg static uint64_t
read_uleb128(struct dwarf_buf * buf)62463d1a8abSmrg read_uleb128 (struct dwarf_buf *buf)
62563d1a8abSmrg {
62663d1a8abSmrg   uint64_t ret;
62763d1a8abSmrg   unsigned int shift;
62863d1a8abSmrg   int overflow;
62963d1a8abSmrg   unsigned char b;
63063d1a8abSmrg 
63163d1a8abSmrg   ret = 0;
63263d1a8abSmrg   shift = 0;
63363d1a8abSmrg   overflow = 0;
63463d1a8abSmrg   do
63563d1a8abSmrg     {
63663d1a8abSmrg       const unsigned char *p;
63763d1a8abSmrg 
63863d1a8abSmrg       p = buf->buf;
63963d1a8abSmrg       if (!advance (buf, 1))
64063d1a8abSmrg 	return 0;
64163d1a8abSmrg       b = *p;
64263d1a8abSmrg       if (shift < 64)
64363d1a8abSmrg 	ret |= ((uint64_t) (b & 0x7f)) << shift;
64463d1a8abSmrg       else if (!overflow)
64563d1a8abSmrg 	{
64663d1a8abSmrg 	  dwarf_buf_error (buf, "LEB128 overflows uint64_t");
64763d1a8abSmrg 	  overflow = 1;
64863d1a8abSmrg 	}
64963d1a8abSmrg       shift += 7;
65063d1a8abSmrg     }
65163d1a8abSmrg   while ((b & 0x80) != 0);
65263d1a8abSmrg 
65363d1a8abSmrg   return ret;
65463d1a8abSmrg }
65563d1a8abSmrg 
65663d1a8abSmrg /* Read a signed LEB128 number.  */
65763d1a8abSmrg 
65863d1a8abSmrg static int64_t
read_sleb128(struct dwarf_buf * buf)65963d1a8abSmrg read_sleb128 (struct dwarf_buf *buf)
66063d1a8abSmrg {
66163d1a8abSmrg   uint64_t val;
66263d1a8abSmrg   unsigned int shift;
66363d1a8abSmrg   int overflow;
66463d1a8abSmrg   unsigned char b;
66563d1a8abSmrg 
66663d1a8abSmrg   val = 0;
66763d1a8abSmrg   shift = 0;
66863d1a8abSmrg   overflow = 0;
66963d1a8abSmrg   do
67063d1a8abSmrg     {
67163d1a8abSmrg       const unsigned char *p;
67263d1a8abSmrg 
67363d1a8abSmrg       p = buf->buf;
67463d1a8abSmrg       if (!advance (buf, 1))
67563d1a8abSmrg 	return 0;
67663d1a8abSmrg       b = *p;
67763d1a8abSmrg       if (shift < 64)
67863d1a8abSmrg 	val |= ((uint64_t) (b & 0x7f)) << shift;
67963d1a8abSmrg       else if (!overflow)
68063d1a8abSmrg 	{
68163d1a8abSmrg 	  dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
68263d1a8abSmrg 	  overflow = 1;
68363d1a8abSmrg 	}
68463d1a8abSmrg       shift += 7;
68563d1a8abSmrg     }
68663d1a8abSmrg   while ((b & 0x80) != 0);
68763d1a8abSmrg 
68863d1a8abSmrg   if ((b & 0x40) != 0 && shift < 64)
68963d1a8abSmrg     val |= ((uint64_t) -1) << shift;
69063d1a8abSmrg 
69163d1a8abSmrg   return (int64_t) val;
69263d1a8abSmrg }
69363d1a8abSmrg 
69463d1a8abSmrg /* Return the length of an LEB128 number.  */
69563d1a8abSmrg 
69663d1a8abSmrg static size_t
leb128_len(const unsigned char * p)69763d1a8abSmrg leb128_len (const unsigned char *p)
69863d1a8abSmrg {
69963d1a8abSmrg   size_t ret;
70063d1a8abSmrg 
70163d1a8abSmrg   ret = 1;
70263d1a8abSmrg   while ((*p & 0x80) != 0)
70363d1a8abSmrg     {
70463d1a8abSmrg       ++p;
70563d1a8abSmrg       ++ret;
70663d1a8abSmrg     }
70763d1a8abSmrg   return ret;
70863d1a8abSmrg }
70963d1a8abSmrg 
7100fc04c29Smrg /* Read initial_length from BUF and advance the appropriate number of bytes.  */
7110fc04c29Smrg 
7120fc04c29Smrg static uint64_t
read_initial_length(struct dwarf_buf * buf,int * is_dwarf64)7130fc04c29Smrg read_initial_length (struct dwarf_buf *buf, int *is_dwarf64)
7140fc04c29Smrg {
7150fc04c29Smrg   uint64_t len;
7160fc04c29Smrg 
7170fc04c29Smrg   len = read_uint32 (buf);
7180fc04c29Smrg   if (len == 0xffffffff)
7190fc04c29Smrg     {
7200fc04c29Smrg       len = read_uint64 (buf);
7210fc04c29Smrg       *is_dwarf64 = 1;
7220fc04c29Smrg     }
7230fc04c29Smrg   else
7240fc04c29Smrg     *is_dwarf64 = 0;
7250fc04c29Smrg 
7260fc04c29Smrg   return len;
7270fc04c29Smrg }
7280fc04c29Smrg 
72963d1a8abSmrg /* Free an abbreviations structure.  */
73063d1a8abSmrg 
73163d1a8abSmrg static void
free_abbrevs(struct backtrace_state * state,struct abbrevs * abbrevs,backtrace_error_callback error_callback,void * data)73263d1a8abSmrg free_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs,
73363d1a8abSmrg 	      backtrace_error_callback error_callback, void *data)
73463d1a8abSmrg {
73563d1a8abSmrg   size_t i;
73663d1a8abSmrg 
73763d1a8abSmrg   for (i = 0; i < abbrevs->num_abbrevs; ++i)
73863d1a8abSmrg     backtrace_free (state, abbrevs->abbrevs[i].attrs,
73963d1a8abSmrg 		    abbrevs->abbrevs[i].num_attrs * sizeof (struct attr),
74063d1a8abSmrg 		    error_callback, data);
74163d1a8abSmrg   backtrace_free (state, abbrevs->abbrevs,
74263d1a8abSmrg 		  abbrevs->num_abbrevs * sizeof (struct abbrev),
74363d1a8abSmrg 		  error_callback, data);
74463d1a8abSmrg   abbrevs->num_abbrevs = 0;
74563d1a8abSmrg   abbrevs->abbrevs = NULL;
74663d1a8abSmrg }
74763d1a8abSmrg 
74863d1a8abSmrg /* Read an attribute value.  Returns 1 on success, 0 on failure.  If
74963d1a8abSmrg    the value can be represented as a uint64_t, sets *VAL and sets
75063d1a8abSmrg    *IS_VALID to 1.  We don't try to store the value of other attribute
75163d1a8abSmrg    forms, because we don't care about them.  */
75263d1a8abSmrg 
75363d1a8abSmrg static int
read_attribute(enum dwarf_form form,uint64_t implicit_val,struct dwarf_buf * buf,int is_dwarf64,int version,int addrsize,const struct dwarf_sections * dwarf_sections,struct dwarf_data * altlink,struct attr_val * val)754*ec02198aSmrg read_attribute (enum dwarf_form form, uint64_t implicit_val,
755*ec02198aSmrg 		struct dwarf_buf *buf, int is_dwarf64, int version,
756*ec02198aSmrg 		int addrsize, const struct dwarf_sections *dwarf_sections,
7570fc04c29Smrg 		struct dwarf_data *altlink, struct attr_val *val)
75863d1a8abSmrg {
75963d1a8abSmrg   /* Avoid warnings about val.u.FIELD may be used uninitialized if
76063d1a8abSmrg      this function is inlined.  The warnings aren't valid but can
76163d1a8abSmrg      occur because the different fields are set and used
76263d1a8abSmrg      conditionally.  */
76363d1a8abSmrg   memset (val, 0, sizeof *val);
76463d1a8abSmrg 
76563d1a8abSmrg   switch (form)
76663d1a8abSmrg     {
76763d1a8abSmrg     case DW_FORM_addr:
76863d1a8abSmrg       val->encoding = ATTR_VAL_ADDRESS;
76963d1a8abSmrg       val->u.uint = read_address (buf, addrsize);
77063d1a8abSmrg       return 1;
77163d1a8abSmrg     case DW_FORM_block2:
77263d1a8abSmrg       val->encoding = ATTR_VAL_BLOCK;
77363d1a8abSmrg       return advance (buf, read_uint16 (buf));
77463d1a8abSmrg     case DW_FORM_block4:
77563d1a8abSmrg       val->encoding = ATTR_VAL_BLOCK;
77663d1a8abSmrg       return advance (buf, read_uint32 (buf));
77763d1a8abSmrg     case DW_FORM_data2:
77863d1a8abSmrg       val->encoding = ATTR_VAL_UINT;
77963d1a8abSmrg       val->u.uint = read_uint16 (buf);
78063d1a8abSmrg       return 1;
78163d1a8abSmrg     case DW_FORM_data4:
78263d1a8abSmrg       val->encoding = ATTR_VAL_UINT;
78363d1a8abSmrg       val->u.uint = read_uint32 (buf);
78463d1a8abSmrg       return 1;
78563d1a8abSmrg     case DW_FORM_data8:
78663d1a8abSmrg       val->encoding = ATTR_VAL_UINT;
78763d1a8abSmrg       val->u.uint = read_uint64 (buf);
78863d1a8abSmrg       return 1;
789*ec02198aSmrg     case DW_FORM_data16:
790*ec02198aSmrg       val->encoding = ATTR_VAL_BLOCK;
791*ec02198aSmrg       return advance (buf, 16);
79263d1a8abSmrg     case DW_FORM_string:
79363d1a8abSmrg       val->encoding = ATTR_VAL_STRING;
7940fc04c29Smrg       val->u.string = read_string (buf);
7950fc04c29Smrg       return val->u.string == NULL ? 0 : 1;
79663d1a8abSmrg     case DW_FORM_block:
79763d1a8abSmrg       val->encoding = ATTR_VAL_BLOCK;
79863d1a8abSmrg       return advance (buf, read_uleb128 (buf));
79963d1a8abSmrg     case DW_FORM_block1:
80063d1a8abSmrg       val->encoding = ATTR_VAL_BLOCK;
80163d1a8abSmrg       return advance (buf, read_byte (buf));
80263d1a8abSmrg     case DW_FORM_data1:
80363d1a8abSmrg       val->encoding = ATTR_VAL_UINT;
80463d1a8abSmrg       val->u.uint = read_byte (buf);
80563d1a8abSmrg       return 1;
80663d1a8abSmrg     case DW_FORM_flag:
80763d1a8abSmrg       val->encoding = ATTR_VAL_UINT;
80863d1a8abSmrg       val->u.uint = read_byte (buf);
80963d1a8abSmrg       return 1;
81063d1a8abSmrg     case DW_FORM_sdata:
81163d1a8abSmrg       val->encoding = ATTR_VAL_SINT;
81263d1a8abSmrg       val->u.sint = read_sleb128 (buf);
81363d1a8abSmrg       return 1;
81463d1a8abSmrg     case DW_FORM_strp:
81563d1a8abSmrg       {
81663d1a8abSmrg 	uint64_t offset;
81763d1a8abSmrg 
81863d1a8abSmrg 	offset = read_offset (buf, is_dwarf64);
819*ec02198aSmrg 	if (offset >= dwarf_sections->size[DEBUG_STR])
82063d1a8abSmrg 	  {
82163d1a8abSmrg 	    dwarf_buf_error (buf, "DW_FORM_strp out of range");
82263d1a8abSmrg 	    return 0;
82363d1a8abSmrg 	  }
82463d1a8abSmrg 	val->encoding = ATTR_VAL_STRING;
825*ec02198aSmrg 	val->u.string =
826*ec02198aSmrg 	  (const char *) dwarf_sections->data[DEBUG_STR] + offset;
827*ec02198aSmrg 	return 1;
828*ec02198aSmrg       }
829*ec02198aSmrg     case DW_FORM_line_strp:
830*ec02198aSmrg       {
831*ec02198aSmrg 	uint64_t offset;
832*ec02198aSmrg 
833*ec02198aSmrg 	offset = read_offset (buf, is_dwarf64);
834*ec02198aSmrg 	if (offset >= dwarf_sections->size[DEBUG_LINE_STR])
835*ec02198aSmrg 	  {
836*ec02198aSmrg 	    dwarf_buf_error (buf, "DW_FORM_line_strp out of range");
837*ec02198aSmrg 	    return 0;
838*ec02198aSmrg 	  }
839*ec02198aSmrg 	val->encoding = ATTR_VAL_STRING;
840*ec02198aSmrg 	val->u.string =
841*ec02198aSmrg 	  (const char *) dwarf_sections->data[DEBUG_LINE_STR] + offset;
84263d1a8abSmrg 	return 1;
84363d1a8abSmrg       }
84463d1a8abSmrg     case DW_FORM_udata:
84563d1a8abSmrg       val->encoding = ATTR_VAL_UINT;
84663d1a8abSmrg       val->u.uint = read_uleb128 (buf);
84763d1a8abSmrg       return 1;
84863d1a8abSmrg     case DW_FORM_ref_addr:
84963d1a8abSmrg       val->encoding = ATTR_VAL_REF_INFO;
85063d1a8abSmrg       if (version == 2)
85163d1a8abSmrg 	val->u.uint = read_address (buf, addrsize);
85263d1a8abSmrg       else
85363d1a8abSmrg 	val->u.uint = read_offset (buf, is_dwarf64);
85463d1a8abSmrg       return 1;
85563d1a8abSmrg     case DW_FORM_ref1:
85663d1a8abSmrg       val->encoding = ATTR_VAL_REF_UNIT;
85763d1a8abSmrg       val->u.uint = read_byte (buf);
85863d1a8abSmrg       return 1;
85963d1a8abSmrg     case DW_FORM_ref2:
86063d1a8abSmrg       val->encoding = ATTR_VAL_REF_UNIT;
86163d1a8abSmrg       val->u.uint = read_uint16 (buf);
86263d1a8abSmrg       return 1;
86363d1a8abSmrg     case DW_FORM_ref4:
86463d1a8abSmrg       val->encoding = ATTR_VAL_REF_UNIT;
86563d1a8abSmrg       val->u.uint = read_uint32 (buf);
86663d1a8abSmrg       return 1;
86763d1a8abSmrg     case DW_FORM_ref8:
86863d1a8abSmrg       val->encoding = ATTR_VAL_REF_UNIT;
86963d1a8abSmrg       val->u.uint = read_uint64 (buf);
87063d1a8abSmrg       return 1;
87163d1a8abSmrg     case DW_FORM_ref_udata:
87263d1a8abSmrg       val->encoding = ATTR_VAL_REF_UNIT;
87363d1a8abSmrg       val->u.uint = read_uleb128 (buf);
87463d1a8abSmrg       return 1;
87563d1a8abSmrg     case DW_FORM_indirect:
87663d1a8abSmrg       {
87763d1a8abSmrg 	uint64_t form;
87863d1a8abSmrg 
87963d1a8abSmrg 	form = read_uleb128 (buf);
880*ec02198aSmrg 	if (form == DW_FORM_implicit_const)
881*ec02198aSmrg 	  {
882*ec02198aSmrg 	    dwarf_buf_error (buf,
883*ec02198aSmrg 			     "DW_FORM_indirect to DW_FORM_implicit_const");
884*ec02198aSmrg 	    return 0;
885*ec02198aSmrg 	  }
886*ec02198aSmrg 	return read_attribute ((enum dwarf_form) form, 0, buf, is_dwarf64,
887*ec02198aSmrg 			       version, addrsize, dwarf_sections, altlink,
888*ec02198aSmrg 			       val);
88963d1a8abSmrg       }
89063d1a8abSmrg     case DW_FORM_sec_offset:
89163d1a8abSmrg       val->encoding = ATTR_VAL_REF_SECTION;
89263d1a8abSmrg       val->u.uint = read_offset (buf, is_dwarf64);
89363d1a8abSmrg       return 1;
89463d1a8abSmrg     case DW_FORM_exprloc:
89563d1a8abSmrg       val->encoding = ATTR_VAL_EXPR;
89663d1a8abSmrg       return advance (buf, read_uleb128 (buf));
89763d1a8abSmrg     case DW_FORM_flag_present:
89863d1a8abSmrg       val->encoding = ATTR_VAL_UINT;
89963d1a8abSmrg       val->u.uint = 1;
90063d1a8abSmrg       return 1;
90163d1a8abSmrg     case DW_FORM_ref_sig8:
90263d1a8abSmrg       val->encoding = ATTR_VAL_REF_TYPE;
90363d1a8abSmrg       val->u.uint = read_uint64 (buf);
90463d1a8abSmrg       return 1;
905*ec02198aSmrg     case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2:
906*ec02198aSmrg     case DW_FORM_strx3: case DW_FORM_strx4:
907*ec02198aSmrg       {
908*ec02198aSmrg 	uint64_t offset;
909*ec02198aSmrg 
910*ec02198aSmrg 	switch (form)
911*ec02198aSmrg 	  {
912*ec02198aSmrg 	  case DW_FORM_strx:
913*ec02198aSmrg 	    offset = read_uleb128 (buf);
914*ec02198aSmrg 	    break;
915*ec02198aSmrg 	  case DW_FORM_strx1:
916*ec02198aSmrg 	    offset = read_byte (buf);
917*ec02198aSmrg 	    break;
918*ec02198aSmrg 	  case DW_FORM_strx2:
919*ec02198aSmrg 	    offset = read_uint16 (buf);
920*ec02198aSmrg 	    break;
921*ec02198aSmrg 	  case DW_FORM_strx3:
922*ec02198aSmrg 	    offset = read_uint24 (buf);
923*ec02198aSmrg 	    break;
924*ec02198aSmrg 	  case DW_FORM_strx4:
925*ec02198aSmrg 	    offset = read_uint32 (buf);
926*ec02198aSmrg 	    break;
927*ec02198aSmrg 	  default:
928*ec02198aSmrg 	    /* This case can't happen.  */
929*ec02198aSmrg 	    return 0;
930*ec02198aSmrg 	  }
931*ec02198aSmrg 	val->encoding = ATTR_VAL_STRING_INDEX;
932*ec02198aSmrg 	val->u.uint = offset;
933*ec02198aSmrg 	return 1;
934*ec02198aSmrg       }
935*ec02198aSmrg     case DW_FORM_addrx: case DW_FORM_addrx1: case DW_FORM_addrx2:
936*ec02198aSmrg     case DW_FORM_addrx3: case DW_FORM_addrx4:
937*ec02198aSmrg       {
938*ec02198aSmrg 	uint64_t offset;
939*ec02198aSmrg 
940*ec02198aSmrg 	switch (form)
941*ec02198aSmrg 	  {
942*ec02198aSmrg 	  case DW_FORM_addrx:
943*ec02198aSmrg 	    offset = read_uleb128 (buf);
944*ec02198aSmrg 	    break;
945*ec02198aSmrg 	  case DW_FORM_addrx1:
946*ec02198aSmrg 	    offset = read_byte (buf);
947*ec02198aSmrg 	    break;
948*ec02198aSmrg 	  case DW_FORM_addrx2:
949*ec02198aSmrg 	    offset = read_uint16 (buf);
950*ec02198aSmrg 	    break;
951*ec02198aSmrg 	  case DW_FORM_addrx3:
952*ec02198aSmrg 	    offset = read_uint24 (buf);
953*ec02198aSmrg 	    break;
954*ec02198aSmrg 	  case DW_FORM_addrx4:
955*ec02198aSmrg 	    offset = read_uint32 (buf);
956*ec02198aSmrg 	    break;
957*ec02198aSmrg 	  default:
958*ec02198aSmrg 	    /* This case can't happen.  */
959*ec02198aSmrg 	    return 0;
960*ec02198aSmrg 	  }
961*ec02198aSmrg 	val->encoding = ATTR_VAL_ADDRESS_INDEX;
962*ec02198aSmrg 	val->u.uint = offset;
963*ec02198aSmrg 	return 1;
964*ec02198aSmrg       }
965*ec02198aSmrg     case DW_FORM_ref_sup4:
966*ec02198aSmrg       val->encoding = ATTR_VAL_REF_SECTION;
967*ec02198aSmrg       val->u.uint = read_uint32 (buf);
968*ec02198aSmrg       return 1;
969*ec02198aSmrg     case DW_FORM_ref_sup8:
970*ec02198aSmrg       val->encoding = ATTR_VAL_REF_SECTION;
971*ec02198aSmrg       val->u.uint = read_uint64 (buf);
972*ec02198aSmrg       return 1;
973*ec02198aSmrg     case DW_FORM_implicit_const:
974*ec02198aSmrg       val->encoding = ATTR_VAL_UINT;
975*ec02198aSmrg       val->u.uint = implicit_val;
976*ec02198aSmrg       return 1;
977*ec02198aSmrg     case DW_FORM_loclistx:
978*ec02198aSmrg       /* We don't distinguish this from DW_FORM_sec_offset.  It
979*ec02198aSmrg        * shouldn't matter since we don't care about loclists.  */
980*ec02198aSmrg       val->encoding = ATTR_VAL_REF_SECTION;
981*ec02198aSmrg       val->u.uint = read_uleb128 (buf);
982*ec02198aSmrg       return 1;
983*ec02198aSmrg     case DW_FORM_rnglistx:
984*ec02198aSmrg       val->encoding = ATTR_VAL_RNGLISTS_INDEX;
985*ec02198aSmrg       val->u.uint = read_uleb128 (buf);
986*ec02198aSmrg       return 1;
98763d1a8abSmrg     case DW_FORM_GNU_addr_index:
98863d1a8abSmrg       val->encoding = ATTR_VAL_REF_SECTION;
98963d1a8abSmrg       val->u.uint = read_uleb128 (buf);
99063d1a8abSmrg       return 1;
99163d1a8abSmrg     case DW_FORM_GNU_str_index:
99263d1a8abSmrg       val->encoding = ATTR_VAL_REF_SECTION;
99363d1a8abSmrg       val->u.uint = read_uleb128 (buf);
99463d1a8abSmrg       return 1;
99563d1a8abSmrg     case DW_FORM_GNU_ref_alt:
99663d1a8abSmrg       val->u.uint = read_offset (buf, is_dwarf64);
9970fc04c29Smrg       if (altlink == NULL)
9980fc04c29Smrg 	{
9990fc04c29Smrg 	  val->encoding = ATTR_VAL_NONE;
10000fc04c29Smrg 	  return 1;
10010fc04c29Smrg 	}
10020fc04c29Smrg       val->encoding = ATTR_VAL_REF_ALT_INFO;
100363d1a8abSmrg       return 1;
1004*ec02198aSmrg     case DW_FORM_strp_sup: case DW_FORM_GNU_strp_alt:
10050fc04c29Smrg       {
10060fc04c29Smrg 	uint64_t offset;
1007*ec02198aSmrg 
10080fc04c29Smrg 	offset = read_offset (buf, is_dwarf64);
10090fc04c29Smrg 	if (altlink == NULL)
10100fc04c29Smrg 	  {
10110fc04c29Smrg 	    val->encoding = ATTR_VAL_NONE;
101263d1a8abSmrg 	    return 1;
10130fc04c29Smrg 	  }
1014*ec02198aSmrg 	if (offset >= altlink->dwarf_sections.size[DEBUG_STR])
10150fc04c29Smrg 	  {
1016*ec02198aSmrg 	    dwarf_buf_error (buf, "DW_FORM_strp_sup out of range");
10170fc04c29Smrg 	    return 0;
10180fc04c29Smrg 	  }
10190fc04c29Smrg 	val->encoding = ATTR_VAL_STRING;
1020*ec02198aSmrg 	val->u.string =
1021*ec02198aSmrg 	  (const char *) altlink->dwarf_sections.data[DEBUG_STR] + offset;
10220fc04c29Smrg 	return 1;
10230fc04c29Smrg       }
102463d1a8abSmrg     default:
102563d1a8abSmrg       dwarf_buf_error (buf, "unrecognized DWARF form");
102663d1a8abSmrg       return 0;
102763d1a8abSmrg     }
102863d1a8abSmrg }
102963d1a8abSmrg 
1030*ec02198aSmrg /* If we can determine the value of a string attribute, set *STRING to
1031*ec02198aSmrg    point to the string.  Return 1 on success, 0 on error.  If we don't
1032*ec02198aSmrg    know the value, we consider that a success, and we don't change
1033*ec02198aSmrg    *STRING.  An error is only reported for some sort of out of range
1034*ec02198aSmrg    offset.  */
1035*ec02198aSmrg 
1036*ec02198aSmrg static int
resolve_string(const struct dwarf_sections * dwarf_sections,int is_dwarf64,int is_bigendian,uint64_t str_offsets_base,const struct attr_val * val,backtrace_error_callback error_callback,void * data,const char ** string)1037*ec02198aSmrg resolve_string (const struct dwarf_sections *dwarf_sections, int is_dwarf64,
1038*ec02198aSmrg 		int is_bigendian, uint64_t str_offsets_base,
1039*ec02198aSmrg 		const struct attr_val *val,
1040*ec02198aSmrg 		backtrace_error_callback error_callback, void *data,
1041*ec02198aSmrg 		const char **string)
1042*ec02198aSmrg {
1043*ec02198aSmrg   switch (val->encoding)
1044*ec02198aSmrg     {
1045*ec02198aSmrg     case ATTR_VAL_STRING:
1046*ec02198aSmrg       *string = val->u.string;
1047*ec02198aSmrg       return 1;
1048*ec02198aSmrg 
1049*ec02198aSmrg     case ATTR_VAL_STRING_INDEX:
1050*ec02198aSmrg       {
1051*ec02198aSmrg 	uint64_t offset;
1052*ec02198aSmrg 	struct dwarf_buf offset_buf;
1053*ec02198aSmrg 
1054*ec02198aSmrg 	offset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base;
1055*ec02198aSmrg 	if (offset + (is_dwarf64 ? 8 : 4)
1056*ec02198aSmrg 	    >= dwarf_sections->size[DEBUG_STR_OFFSETS])
1057*ec02198aSmrg 	  {
1058*ec02198aSmrg 	    error_callback (data, "DW_FORM_strx value out of range", 0);
1059*ec02198aSmrg 	    return 0;
1060*ec02198aSmrg 	  }
1061*ec02198aSmrg 
1062*ec02198aSmrg 	offset_buf.name = ".debug_str_offsets";
1063*ec02198aSmrg 	offset_buf.start = dwarf_sections->data[DEBUG_STR_OFFSETS];
1064*ec02198aSmrg 	offset_buf.buf = dwarf_sections->data[DEBUG_STR_OFFSETS] + offset;
1065*ec02198aSmrg 	offset_buf.left = dwarf_sections->size[DEBUG_STR_OFFSETS] - offset;
1066*ec02198aSmrg 	offset_buf.is_bigendian = is_bigendian;
1067*ec02198aSmrg 	offset_buf.error_callback = error_callback;
1068*ec02198aSmrg 	offset_buf.data = data;
1069*ec02198aSmrg 	offset_buf.reported_underflow = 0;
1070*ec02198aSmrg 
1071*ec02198aSmrg 	offset = read_offset (&offset_buf, is_dwarf64);
1072*ec02198aSmrg 	if (offset >= dwarf_sections->size[DEBUG_STR])
1073*ec02198aSmrg 	  {
1074*ec02198aSmrg 	    dwarf_buf_error (&offset_buf, "DW_FORM_strx offset out of range");
1075*ec02198aSmrg 	    return 0;
1076*ec02198aSmrg 	  }
1077*ec02198aSmrg 	*string = (const char *) dwarf_sections->data[DEBUG_STR] + offset;
1078*ec02198aSmrg 	return 1;
1079*ec02198aSmrg       }
1080*ec02198aSmrg 
1081*ec02198aSmrg     default:
1082*ec02198aSmrg       return 1;
1083*ec02198aSmrg     }
1084*ec02198aSmrg }
1085*ec02198aSmrg 
1086*ec02198aSmrg /* Set *ADDRESS to the real address for a ATTR_VAL_ADDRESS_INDEX.
1087*ec02198aSmrg    Return 1 on success, 0 on error.  */
1088*ec02198aSmrg 
1089*ec02198aSmrg static int
resolve_addr_index(const struct dwarf_sections * dwarf_sections,uint64_t addr_base,int addrsize,int is_bigendian,uint64_t addr_index,backtrace_error_callback error_callback,void * data,uint64_t * address)1090*ec02198aSmrg resolve_addr_index (const struct dwarf_sections *dwarf_sections,
1091*ec02198aSmrg 		    uint64_t addr_base, int addrsize, int is_bigendian,
1092*ec02198aSmrg 		    uint64_t addr_index,
1093*ec02198aSmrg 		    backtrace_error_callback error_callback, void *data,
1094*ec02198aSmrg 		    uint64_t *address)
1095*ec02198aSmrg {
1096*ec02198aSmrg   uint64_t offset;
1097*ec02198aSmrg   struct dwarf_buf addr_buf;
1098*ec02198aSmrg 
1099*ec02198aSmrg   offset = addr_index * addrsize + addr_base;
1100*ec02198aSmrg   if (offset + addrsize >= dwarf_sections->size[DEBUG_ADDR])
1101*ec02198aSmrg     {
1102*ec02198aSmrg       error_callback (data, "DW_FORM_addrx value out of range", 0);
1103*ec02198aSmrg       return 0;
1104*ec02198aSmrg     }
1105*ec02198aSmrg 
1106*ec02198aSmrg   addr_buf.name = ".debug_addr";
1107*ec02198aSmrg   addr_buf.start = dwarf_sections->data[DEBUG_ADDR];
1108*ec02198aSmrg   addr_buf.buf = dwarf_sections->data[DEBUG_ADDR] + offset;
1109*ec02198aSmrg   addr_buf.left = dwarf_sections->size[DEBUG_ADDR] - offset;
1110*ec02198aSmrg   addr_buf.is_bigendian = is_bigendian;
1111*ec02198aSmrg   addr_buf.error_callback = error_callback;
1112*ec02198aSmrg   addr_buf.data = data;
1113*ec02198aSmrg   addr_buf.reported_underflow = 0;
1114*ec02198aSmrg 
1115*ec02198aSmrg   *address = read_address (&addr_buf, addrsize);
1116*ec02198aSmrg   return 1;
1117*ec02198aSmrg }
1118*ec02198aSmrg 
11190fc04c29Smrg /* Compare a unit offset against a unit for bsearch.  */
11200fc04c29Smrg 
11210fc04c29Smrg static int
units_search(const void * vkey,const void * ventry)11220fc04c29Smrg units_search (const void *vkey, const void *ventry)
11230fc04c29Smrg {
11240fc04c29Smrg   const size_t *key = (const size_t *) vkey;
11250fc04c29Smrg   const struct unit *entry = *((const struct unit *const *) ventry);
11260fc04c29Smrg   size_t offset;
11270fc04c29Smrg 
11280fc04c29Smrg   offset = *key;
11290fc04c29Smrg   if (offset < entry->low_offset)
11300fc04c29Smrg     return -1;
11310fc04c29Smrg   else if (offset >= entry->high_offset)
11320fc04c29Smrg     return 1;
11330fc04c29Smrg   else
11340fc04c29Smrg     return 0;
11350fc04c29Smrg }
11360fc04c29Smrg 
11370fc04c29Smrg /* Find a unit in PU containing OFFSET.  */
11380fc04c29Smrg 
11390fc04c29Smrg static struct unit *
find_unit(struct unit ** pu,size_t units_count,size_t offset)11400fc04c29Smrg find_unit (struct unit **pu, size_t units_count, size_t offset)
11410fc04c29Smrg {
11420fc04c29Smrg   struct unit **u;
11430fc04c29Smrg   u = bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search);
11440fc04c29Smrg   return u == NULL ? NULL : *u;
11450fc04c29Smrg }
11460fc04c29Smrg 
114763d1a8abSmrg /* Compare function_addrs for qsort.  When ranges are nested, make the
114863d1a8abSmrg    smallest one sort last.  */
114963d1a8abSmrg 
115063d1a8abSmrg static int
function_addrs_compare(const void * v1,const void * v2)115163d1a8abSmrg function_addrs_compare (const void *v1, const void *v2)
115263d1a8abSmrg {
115363d1a8abSmrg   const struct function_addrs *a1 = (const struct function_addrs *) v1;
115463d1a8abSmrg   const struct function_addrs *a2 = (const struct function_addrs *) v2;
115563d1a8abSmrg 
115663d1a8abSmrg   if (a1->low < a2->low)
115763d1a8abSmrg     return -1;
115863d1a8abSmrg   if (a1->low > a2->low)
115963d1a8abSmrg     return 1;
116063d1a8abSmrg   if (a1->high < a2->high)
116163d1a8abSmrg     return 1;
116263d1a8abSmrg   if (a1->high > a2->high)
116363d1a8abSmrg     return -1;
116463d1a8abSmrg   return strcmp (a1->function->name, a2->function->name);
116563d1a8abSmrg }
116663d1a8abSmrg 
116763d1a8abSmrg /* Compare a PC against a function_addrs for bsearch.  Note that if
116863d1a8abSmrg    there are multiple ranges containing PC, which one will be returned
116963d1a8abSmrg    is unpredictable.  We compensate for that in dwarf_fileline.  */
117063d1a8abSmrg 
117163d1a8abSmrg static int
function_addrs_search(const void * vkey,const void * ventry)117263d1a8abSmrg function_addrs_search (const void *vkey, const void *ventry)
117363d1a8abSmrg {
117463d1a8abSmrg   const uintptr_t *key = (const uintptr_t *) vkey;
117563d1a8abSmrg   const struct function_addrs *entry = (const struct function_addrs *) ventry;
117663d1a8abSmrg   uintptr_t pc;
117763d1a8abSmrg 
117863d1a8abSmrg   pc = *key;
117963d1a8abSmrg   if (pc < entry->low)
118063d1a8abSmrg     return -1;
118163d1a8abSmrg   else if (pc >= entry->high)
118263d1a8abSmrg     return 1;
118363d1a8abSmrg   else
118463d1a8abSmrg     return 0;
118563d1a8abSmrg }
118663d1a8abSmrg 
1187*ec02198aSmrg /* Add a new compilation unit address range to a vector.  This is
1188*ec02198aSmrg    called via add_ranges.  Returns 1 on success, 0 on failure.  */
118963d1a8abSmrg 
119063d1a8abSmrg static int
add_unit_addr(struct backtrace_state * state,void * rdata,uint64_t lowpc,uint64_t highpc,backtrace_error_callback error_callback,void * data,void * pvec)1191*ec02198aSmrg add_unit_addr (struct backtrace_state *state, void *rdata,
1192*ec02198aSmrg 	       uint64_t lowpc, uint64_t highpc,
119363d1a8abSmrg 	       backtrace_error_callback error_callback, void *data,
1194*ec02198aSmrg 	       void *pvec)
119563d1a8abSmrg {
1196*ec02198aSmrg   struct unit *u = (struct unit *) rdata;
1197*ec02198aSmrg   struct unit_addrs_vector *vec = (struct unit_addrs_vector *) pvec;
119863d1a8abSmrg   struct unit_addrs *p;
119963d1a8abSmrg 
120063d1a8abSmrg   /* Try to merge with the last entry.  */
120163d1a8abSmrg   if (vec->count > 0)
120263d1a8abSmrg     {
120363d1a8abSmrg       p = (struct unit_addrs *) vec->vec.base + (vec->count - 1);
1204*ec02198aSmrg       if ((lowpc == p->high || lowpc == p->high + 1)
1205*ec02198aSmrg 	  && u == p->u)
120663d1a8abSmrg 	{
1207*ec02198aSmrg 	  if (highpc > p->high)
1208*ec02198aSmrg 	    p->high = highpc;
120963d1a8abSmrg 	  return 1;
121063d1a8abSmrg 	}
121163d1a8abSmrg     }
121263d1a8abSmrg 
121363d1a8abSmrg   p = ((struct unit_addrs *)
121463d1a8abSmrg        backtrace_vector_grow (state, sizeof (struct unit_addrs),
121563d1a8abSmrg 			      error_callback, data, &vec->vec));
121663d1a8abSmrg   if (p == NULL)
121763d1a8abSmrg     return 0;
121863d1a8abSmrg 
1219*ec02198aSmrg   p->low = lowpc;
1220*ec02198aSmrg   p->high = highpc;
1221*ec02198aSmrg   p->u = u;
1222*ec02198aSmrg 
122363d1a8abSmrg   ++vec->count;
1224*ec02198aSmrg 
122563d1a8abSmrg   return 1;
122663d1a8abSmrg }
122763d1a8abSmrg 
122863d1a8abSmrg /* Compare unit_addrs for qsort.  When ranges are nested, make the
122963d1a8abSmrg    smallest one sort last.  */
123063d1a8abSmrg 
123163d1a8abSmrg static int
unit_addrs_compare(const void * v1,const void * v2)123263d1a8abSmrg unit_addrs_compare (const void *v1, const void *v2)
123363d1a8abSmrg {
123463d1a8abSmrg   const struct unit_addrs *a1 = (const struct unit_addrs *) v1;
123563d1a8abSmrg   const struct unit_addrs *a2 = (const struct unit_addrs *) v2;
123663d1a8abSmrg 
123763d1a8abSmrg   if (a1->low < a2->low)
123863d1a8abSmrg     return -1;
123963d1a8abSmrg   if (a1->low > a2->low)
124063d1a8abSmrg     return 1;
124163d1a8abSmrg   if (a1->high < a2->high)
124263d1a8abSmrg     return 1;
124363d1a8abSmrg   if (a1->high > a2->high)
124463d1a8abSmrg     return -1;
124563d1a8abSmrg   if (a1->u->lineoff < a2->u->lineoff)
124663d1a8abSmrg     return -1;
124763d1a8abSmrg   if (a1->u->lineoff > a2->u->lineoff)
124863d1a8abSmrg     return 1;
124963d1a8abSmrg   return 0;
125063d1a8abSmrg }
125163d1a8abSmrg 
125263d1a8abSmrg /* Compare a PC against a unit_addrs for bsearch.  Note that if there
125363d1a8abSmrg    are multiple ranges containing PC, which one will be returned is
125463d1a8abSmrg    unpredictable.  We compensate for that in dwarf_fileline.  */
125563d1a8abSmrg 
125663d1a8abSmrg static int
unit_addrs_search(const void * vkey,const void * ventry)125763d1a8abSmrg unit_addrs_search (const void *vkey, const void *ventry)
125863d1a8abSmrg {
125963d1a8abSmrg   const uintptr_t *key = (const uintptr_t *) vkey;
126063d1a8abSmrg   const struct unit_addrs *entry = (const struct unit_addrs *) ventry;
126163d1a8abSmrg   uintptr_t pc;
126263d1a8abSmrg 
126363d1a8abSmrg   pc = *key;
126463d1a8abSmrg   if (pc < entry->low)
126563d1a8abSmrg     return -1;
126663d1a8abSmrg   else if (pc >= entry->high)
126763d1a8abSmrg     return 1;
126863d1a8abSmrg   else
126963d1a8abSmrg     return 0;
127063d1a8abSmrg }
127163d1a8abSmrg 
127263d1a8abSmrg /* Sort the line vector by PC.  We want a stable sort here to maintain
127363d1a8abSmrg    the order of lines for the same PC values.  Since the sequence is
127463d1a8abSmrg    being sorted in place, their addresses cannot be relied on to
127563d1a8abSmrg    maintain stability.  That is the purpose of the index member.  */
127663d1a8abSmrg 
127763d1a8abSmrg static int
line_compare(const void * v1,const void * v2)127863d1a8abSmrg line_compare (const void *v1, const void *v2)
127963d1a8abSmrg {
128063d1a8abSmrg   const struct line *ln1 = (const struct line *) v1;
128163d1a8abSmrg   const struct line *ln2 = (const struct line *) v2;
128263d1a8abSmrg 
128363d1a8abSmrg   if (ln1->pc < ln2->pc)
128463d1a8abSmrg     return -1;
128563d1a8abSmrg   else if (ln1->pc > ln2->pc)
128663d1a8abSmrg     return 1;
128763d1a8abSmrg   else if (ln1->idx < ln2->idx)
128863d1a8abSmrg     return -1;
128963d1a8abSmrg   else if (ln1->idx > ln2->idx)
129063d1a8abSmrg     return 1;
129163d1a8abSmrg   else
129263d1a8abSmrg     return 0;
129363d1a8abSmrg }
129463d1a8abSmrg 
129563d1a8abSmrg /* Find a PC in a line vector.  We always allocate an extra entry at
129663d1a8abSmrg    the end of the lines vector, so that this routine can safely look
129763d1a8abSmrg    at the next entry.  Note that when there are multiple mappings for
129863d1a8abSmrg    the same PC value, this will return the last one.  */
129963d1a8abSmrg 
130063d1a8abSmrg static int
line_search(const void * vkey,const void * ventry)130163d1a8abSmrg line_search (const void *vkey, const void *ventry)
130263d1a8abSmrg {
130363d1a8abSmrg   const uintptr_t *key = (const uintptr_t *) vkey;
130463d1a8abSmrg   const struct line *entry = (const struct line *) ventry;
130563d1a8abSmrg   uintptr_t pc;
130663d1a8abSmrg 
130763d1a8abSmrg   pc = *key;
130863d1a8abSmrg   if (pc < entry->pc)
130963d1a8abSmrg     return -1;
131063d1a8abSmrg   else if (pc >= (entry + 1)->pc)
131163d1a8abSmrg     return 1;
131263d1a8abSmrg   else
131363d1a8abSmrg     return 0;
131463d1a8abSmrg }
131563d1a8abSmrg 
131663d1a8abSmrg /* Sort the abbrevs by the abbrev code.  This function is passed to
131763d1a8abSmrg    both qsort and bsearch.  */
131863d1a8abSmrg 
131963d1a8abSmrg static int
abbrev_compare(const void * v1,const void * v2)132063d1a8abSmrg abbrev_compare (const void *v1, const void *v2)
132163d1a8abSmrg {
132263d1a8abSmrg   const struct abbrev *a1 = (const struct abbrev *) v1;
132363d1a8abSmrg   const struct abbrev *a2 = (const struct abbrev *) v2;
132463d1a8abSmrg 
132563d1a8abSmrg   if (a1->code < a2->code)
132663d1a8abSmrg     return -1;
132763d1a8abSmrg   else if (a1->code > a2->code)
132863d1a8abSmrg     return 1;
132963d1a8abSmrg   else
133063d1a8abSmrg     {
133163d1a8abSmrg       /* This really shouldn't happen.  It means there are two
133263d1a8abSmrg 	 different abbrevs with the same code, and that means we don't
133363d1a8abSmrg 	 know which one lookup_abbrev should return.  */
133463d1a8abSmrg       return 0;
133563d1a8abSmrg     }
133663d1a8abSmrg }
133763d1a8abSmrg 
133863d1a8abSmrg /* Read the abbreviation table for a compilation unit.  Returns 1 on
133963d1a8abSmrg    success, 0 on failure.  */
134063d1a8abSmrg 
134163d1a8abSmrg static int
read_abbrevs(struct backtrace_state * state,uint64_t abbrev_offset,const unsigned char * dwarf_abbrev,size_t dwarf_abbrev_size,int is_bigendian,backtrace_error_callback error_callback,void * data,struct abbrevs * abbrevs)134263d1a8abSmrg read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
134363d1a8abSmrg 	      const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
134463d1a8abSmrg 	      int is_bigendian, backtrace_error_callback error_callback,
134563d1a8abSmrg 	      void *data, struct abbrevs *abbrevs)
134663d1a8abSmrg {
134763d1a8abSmrg   struct dwarf_buf abbrev_buf;
134863d1a8abSmrg   struct dwarf_buf count_buf;
134963d1a8abSmrg   size_t num_abbrevs;
135063d1a8abSmrg 
135163d1a8abSmrg   abbrevs->num_abbrevs = 0;
135263d1a8abSmrg   abbrevs->abbrevs = NULL;
135363d1a8abSmrg 
135463d1a8abSmrg   if (abbrev_offset >= dwarf_abbrev_size)
135563d1a8abSmrg     {
135663d1a8abSmrg       error_callback (data, "abbrev offset out of range", 0);
135763d1a8abSmrg       return 0;
135863d1a8abSmrg     }
135963d1a8abSmrg 
136063d1a8abSmrg   abbrev_buf.name = ".debug_abbrev";
136163d1a8abSmrg   abbrev_buf.start = dwarf_abbrev;
136263d1a8abSmrg   abbrev_buf.buf = dwarf_abbrev + abbrev_offset;
136363d1a8abSmrg   abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;
136463d1a8abSmrg   abbrev_buf.is_bigendian = is_bigendian;
136563d1a8abSmrg   abbrev_buf.error_callback = error_callback;
136663d1a8abSmrg   abbrev_buf.data = data;
136763d1a8abSmrg   abbrev_buf.reported_underflow = 0;
136863d1a8abSmrg 
136963d1a8abSmrg   /* Count the number of abbrevs in this list.  */
137063d1a8abSmrg 
137163d1a8abSmrg   count_buf = abbrev_buf;
137263d1a8abSmrg   num_abbrevs = 0;
137363d1a8abSmrg   while (read_uleb128 (&count_buf) != 0)
137463d1a8abSmrg     {
137563d1a8abSmrg       if (count_buf.reported_underflow)
137663d1a8abSmrg 	return 0;
137763d1a8abSmrg       ++num_abbrevs;
137863d1a8abSmrg       // Skip tag.
137963d1a8abSmrg       read_uleb128 (&count_buf);
138063d1a8abSmrg       // Skip has_children.
138163d1a8abSmrg       read_byte (&count_buf);
138263d1a8abSmrg       // Skip attributes.
138363d1a8abSmrg       while (read_uleb128 (&count_buf) != 0)
1384*ec02198aSmrg 	{
1385*ec02198aSmrg 	  uint64_t form;
1386*ec02198aSmrg 
1387*ec02198aSmrg 	  form = read_uleb128 (&count_buf);
1388*ec02198aSmrg 	  if ((enum dwarf_form) form == DW_FORM_implicit_const)
1389*ec02198aSmrg 	    read_sleb128 (&count_buf);
1390*ec02198aSmrg 	}
139163d1a8abSmrg       // Skip form of last attribute.
139263d1a8abSmrg       read_uleb128 (&count_buf);
139363d1a8abSmrg     }
139463d1a8abSmrg 
139563d1a8abSmrg   if (count_buf.reported_underflow)
139663d1a8abSmrg     return 0;
139763d1a8abSmrg 
139863d1a8abSmrg   if (num_abbrevs == 0)
139963d1a8abSmrg     return 1;
140063d1a8abSmrg 
140163d1a8abSmrg   abbrevs->abbrevs = ((struct abbrev *)
140263d1a8abSmrg 		      backtrace_alloc (state,
140363d1a8abSmrg 				       num_abbrevs * sizeof (struct abbrev),
140463d1a8abSmrg 				       error_callback, data));
140563d1a8abSmrg   if (abbrevs->abbrevs == NULL)
140663d1a8abSmrg     return 0;
14070fc04c29Smrg   abbrevs->num_abbrevs = num_abbrevs;
140863d1a8abSmrg   memset (abbrevs->abbrevs, 0, num_abbrevs * sizeof (struct abbrev));
140963d1a8abSmrg 
141063d1a8abSmrg   num_abbrevs = 0;
141163d1a8abSmrg   while (1)
141263d1a8abSmrg     {
141363d1a8abSmrg       uint64_t code;
141463d1a8abSmrg       struct abbrev a;
141563d1a8abSmrg       size_t num_attrs;
141663d1a8abSmrg       struct attr *attrs;
141763d1a8abSmrg 
141863d1a8abSmrg       if (abbrev_buf.reported_underflow)
141963d1a8abSmrg 	goto fail;
142063d1a8abSmrg 
142163d1a8abSmrg       code = read_uleb128 (&abbrev_buf);
142263d1a8abSmrg       if (code == 0)
142363d1a8abSmrg 	break;
142463d1a8abSmrg 
142563d1a8abSmrg       a.code = code;
142663d1a8abSmrg       a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf);
142763d1a8abSmrg       a.has_children = read_byte (&abbrev_buf);
142863d1a8abSmrg 
142963d1a8abSmrg       count_buf = abbrev_buf;
143063d1a8abSmrg       num_attrs = 0;
143163d1a8abSmrg       while (read_uleb128 (&count_buf) != 0)
143263d1a8abSmrg 	{
1433*ec02198aSmrg 	  uint64_t form;
1434*ec02198aSmrg 
143563d1a8abSmrg 	  ++num_attrs;
1436*ec02198aSmrg 	  form = read_uleb128 (&count_buf);
1437*ec02198aSmrg 	  if ((enum dwarf_form) form == DW_FORM_implicit_const)
1438*ec02198aSmrg 	    read_sleb128 (&count_buf);
143963d1a8abSmrg 	}
144063d1a8abSmrg 
144163d1a8abSmrg       if (num_attrs == 0)
144263d1a8abSmrg 	{
144363d1a8abSmrg 	  attrs = NULL;
144463d1a8abSmrg 	  read_uleb128 (&abbrev_buf);
144563d1a8abSmrg 	  read_uleb128 (&abbrev_buf);
144663d1a8abSmrg 	}
144763d1a8abSmrg       else
144863d1a8abSmrg 	{
144963d1a8abSmrg 	  attrs = ((struct attr *)
145063d1a8abSmrg 		   backtrace_alloc (state, num_attrs * sizeof *attrs,
145163d1a8abSmrg 				    error_callback, data));
145263d1a8abSmrg 	  if (attrs == NULL)
145363d1a8abSmrg 	    goto fail;
145463d1a8abSmrg 	  num_attrs = 0;
145563d1a8abSmrg 	  while (1)
145663d1a8abSmrg 	    {
145763d1a8abSmrg 	      uint64_t name;
145863d1a8abSmrg 	      uint64_t form;
145963d1a8abSmrg 
146063d1a8abSmrg 	      name = read_uleb128 (&abbrev_buf);
146163d1a8abSmrg 	      form = read_uleb128 (&abbrev_buf);
146263d1a8abSmrg 	      if (name == 0)
146363d1a8abSmrg 		break;
146463d1a8abSmrg 	      attrs[num_attrs].name = (enum dwarf_attribute) name;
146563d1a8abSmrg 	      attrs[num_attrs].form = (enum dwarf_form) form;
1466*ec02198aSmrg 	      if ((enum dwarf_form) form == DW_FORM_implicit_const)
1467*ec02198aSmrg 		attrs[num_attrs].val = read_sleb128 (&abbrev_buf);
1468*ec02198aSmrg 	      else
1469*ec02198aSmrg 		attrs[num_attrs].val = 0;
147063d1a8abSmrg 	      ++num_attrs;
147163d1a8abSmrg 	    }
147263d1a8abSmrg 	}
147363d1a8abSmrg 
147463d1a8abSmrg       a.num_attrs = num_attrs;
147563d1a8abSmrg       a.attrs = attrs;
147663d1a8abSmrg 
147763d1a8abSmrg       abbrevs->abbrevs[num_abbrevs] = a;
147863d1a8abSmrg       ++num_abbrevs;
147963d1a8abSmrg     }
148063d1a8abSmrg 
148163d1a8abSmrg   backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,
148263d1a8abSmrg 		   sizeof (struct abbrev), abbrev_compare);
148363d1a8abSmrg 
148463d1a8abSmrg   return 1;
148563d1a8abSmrg 
148663d1a8abSmrg  fail:
148763d1a8abSmrg   free_abbrevs (state, abbrevs, error_callback, data);
148863d1a8abSmrg   return 0;
148963d1a8abSmrg }
149063d1a8abSmrg 
149163d1a8abSmrg /* Return the abbrev information for an abbrev code.  */
149263d1a8abSmrg 
149363d1a8abSmrg static const struct abbrev *
lookup_abbrev(struct abbrevs * abbrevs,uint64_t code,backtrace_error_callback error_callback,void * data)149463d1a8abSmrg lookup_abbrev (struct abbrevs *abbrevs, uint64_t code,
149563d1a8abSmrg 	       backtrace_error_callback error_callback, void *data)
149663d1a8abSmrg {
149763d1a8abSmrg   struct abbrev key;
149863d1a8abSmrg   void *p;
149963d1a8abSmrg 
150063d1a8abSmrg   /* With GCC, where abbrevs are simply numbered in order, we should
150163d1a8abSmrg      be able to just look up the entry.  */
150263d1a8abSmrg   if (code - 1 < abbrevs->num_abbrevs
150363d1a8abSmrg       && abbrevs->abbrevs[code - 1].code == code)
150463d1a8abSmrg     return &abbrevs->abbrevs[code - 1];
150563d1a8abSmrg 
150663d1a8abSmrg   /* Otherwise we have to search.  */
150763d1a8abSmrg   memset (&key, 0, sizeof key);
150863d1a8abSmrg   key.code = code;
150963d1a8abSmrg   p = bsearch (&key, abbrevs->abbrevs, abbrevs->num_abbrevs,
151063d1a8abSmrg 	       sizeof (struct abbrev), abbrev_compare);
151163d1a8abSmrg   if (p == NULL)
151263d1a8abSmrg     {
151363d1a8abSmrg       error_callback (data, "invalid abbreviation code", 0);
151463d1a8abSmrg       return NULL;
151563d1a8abSmrg     }
151663d1a8abSmrg   return (const struct abbrev *) p;
151763d1a8abSmrg }
151863d1a8abSmrg 
1519*ec02198aSmrg /* This struct is used to gather address range information while
1520*ec02198aSmrg    reading attributes.  We use this while building a mapping from
1521*ec02198aSmrg    address ranges to compilation units and then again while mapping
1522*ec02198aSmrg    from address ranges to function entries.  Normally either
1523*ec02198aSmrg    lowpc/highpc is set or ranges is set.  */
1524*ec02198aSmrg 
1525*ec02198aSmrg struct pcrange {
1526*ec02198aSmrg   uint64_t lowpc;		/* The low PC value.  */
1527*ec02198aSmrg   int have_lowpc;		/* Whether a low PC value was found.  */
1528*ec02198aSmrg   int lowpc_is_addr_index;	/* Whether lowpc is in .debug_addr.  */
1529*ec02198aSmrg   uint64_t highpc;		/* The high PC value.  */
1530*ec02198aSmrg   int have_highpc;		/* Whether a high PC value was found.  */
1531*ec02198aSmrg   int highpc_is_relative;	/* Whether highpc is relative to lowpc.  */
1532*ec02198aSmrg   int highpc_is_addr_index;	/* Whether highpc is in .debug_addr.  */
1533*ec02198aSmrg   uint64_t ranges;		/* Offset in ranges section.  */
1534*ec02198aSmrg   int have_ranges;		/* Whether ranges is valid.  */
1535*ec02198aSmrg   int ranges_is_index;		/* Whether ranges is DW_FORM_rnglistx.  */
1536*ec02198aSmrg };
1537*ec02198aSmrg 
1538*ec02198aSmrg /* Update PCRANGE from an attribute value.  */
1539*ec02198aSmrg 
1540*ec02198aSmrg static void
update_pcrange(const struct attr * attr,const struct attr_val * val,struct pcrange * pcrange)1541*ec02198aSmrg update_pcrange (const struct attr* attr, const struct attr_val* val,
1542*ec02198aSmrg 		struct pcrange *pcrange)
1543*ec02198aSmrg {
1544*ec02198aSmrg   switch (attr->name)
1545*ec02198aSmrg     {
1546*ec02198aSmrg     case DW_AT_low_pc:
1547*ec02198aSmrg       if (val->encoding == ATTR_VAL_ADDRESS)
1548*ec02198aSmrg 	{
1549*ec02198aSmrg 	  pcrange->lowpc = val->u.uint;
1550*ec02198aSmrg 	  pcrange->have_lowpc = 1;
1551*ec02198aSmrg 	}
1552*ec02198aSmrg       else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)
1553*ec02198aSmrg 	{
1554*ec02198aSmrg 	  pcrange->lowpc = val->u.uint;
1555*ec02198aSmrg 	  pcrange->have_lowpc = 1;
1556*ec02198aSmrg 	  pcrange->lowpc_is_addr_index = 1;
1557*ec02198aSmrg 	}
1558*ec02198aSmrg       break;
1559*ec02198aSmrg 
1560*ec02198aSmrg     case DW_AT_high_pc:
1561*ec02198aSmrg       if (val->encoding == ATTR_VAL_ADDRESS)
1562*ec02198aSmrg 	{
1563*ec02198aSmrg 	  pcrange->highpc = val->u.uint;
1564*ec02198aSmrg 	  pcrange->have_highpc = 1;
1565*ec02198aSmrg 	}
1566*ec02198aSmrg       else if (val->encoding == ATTR_VAL_UINT)
1567*ec02198aSmrg 	{
1568*ec02198aSmrg 	  pcrange->highpc = val->u.uint;
1569*ec02198aSmrg 	  pcrange->have_highpc = 1;
1570*ec02198aSmrg 	  pcrange->highpc_is_relative = 1;
1571*ec02198aSmrg 	}
1572*ec02198aSmrg       else if (val->encoding == ATTR_VAL_ADDRESS_INDEX)
1573*ec02198aSmrg 	{
1574*ec02198aSmrg 	  pcrange->highpc = val->u.uint;
1575*ec02198aSmrg 	  pcrange->have_highpc = 1;
1576*ec02198aSmrg 	  pcrange->highpc_is_addr_index = 1;
1577*ec02198aSmrg 	}
1578*ec02198aSmrg       break;
1579*ec02198aSmrg 
1580*ec02198aSmrg     case DW_AT_ranges:
1581*ec02198aSmrg       if (val->encoding == ATTR_VAL_UINT
1582*ec02198aSmrg 	  || val->encoding == ATTR_VAL_REF_SECTION)
1583*ec02198aSmrg 	{
1584*ec02198aSmrg 	  pcrange->ranges = val->u.uint;
1585*ec02198aSmrg 	  pcrange->have_ranges = 1;
1586*ec02198aSmrg 	}
1587*ec02198aSmrg       else if (val->encoding == ATTR_VAL_RNGLISTS_INDEX)
1588*ec02198aSmrg 	{
1589*ec02198aSmrg 	  pcrange->ranges = val->u.uint;
1590*ec02198aSmrg 	  pcrange->have_ranges = 1;
1591*ec02198aSmrg 	  pcrange->ranges_is_index = 1;
1592*ec02198aSmrg 	}
1593*ec02198aSmrg       break;
1594*ec02198aSmrg 
1595*ec02198aSmrg     default:
1596*ec02198aSmrg       break;
1597*ec02198aSmrg     }
1598*ec02198aSmrg }
1599*ec02198aSmrg 
1600*ec02198aSmrg /* Call ADD_RANGE for a low/high PC pair.  Returns 1 on success, 0 on
1601*ec02198aSmrg   error.  */
160263d1a8abSmrg 
160363d1a8abSmrg static int
add_low_high_range(struct backtrace_state * state,const struct dwarf_sections * dwarf_sections,uintptr_t base_address,int is_bigendian,struct unit * u,const struct pcrange * pcrange,int (* add_range)(struct backtrace_state * state,void * rdata,uint64_t lowpc,uint64_t highpc,backtrace_error_callback error_callback,void * data,void * vec),void * rdata,backtrace_error_callback error_callback,void * data,void * vec)1604*ec02198aSmrg add_low_high_range (struct backtrace_state *state,
1605*ec02198aSmrg 		    const struct dwarf_sections *dwarf_sections,
1606*ec02198aSmrg 		    uintptr_t base_address, int is_bigendian,
1607*ec02198aSmrg 		    struct unit *u, const struct pcrange *pcrange,
1608*ec02198aSmrg 		    int (*add_range) (struct backtrace_state *state,
1609*ec02198aSmrg 				      void *rdata, uint64_t lowpc,
1610*ec02198aSmrg 				      uint64_t highpc,
1611*ec02198aSmrg 				      backtrace_error_callback error_callback,
1612*ec02198aSmrg 				      void *data, void *vec),
1613*ec02198aSmrg 		    void *rdata,
161463d1a8abSmrg 		    backtrace_error_callback error_callback, void *data,
1615*ec02198aSmrg 		    void *vec)
1616*ec02198aSmrg {
1617*ec02198aSmrg   uint64_t lowpc;
1618*ec02198aSmrg   uint64_t highpc;
1619*ec02198aSmrg 
1620*ec02198aSmrg   lowpc = pcrange->lowpc;
1621*ec02198aSmrg   if (pcrange->lowpc_is_addr_index)
1622*ec02198aSmrg     {
1623*ec02198aSmrg       if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize,
1624*ec02198aSmrg 			       is_bigendian, lowpc, error_callback, data,
1625*ec02198aSmrg 			       &lowpc))
1626*ec02198aSmrg 	return 0;
1627*ec02198aSmrg     }
1628*ec02198aSmrg 
1629*ec02198aSmrg   highpc = pcrange->highpc;
1630*ec02198aSmrg   if (pcrange->highpc_is_addr_index)
1631*ec02198aSmrg     {
1632*ec02198aSmrg       if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize,
1633*ec02198aSmrg 			       is_bigendian, highpc, error_callback, data,
1634*ec02198aSmrg 			       &highpc))
1635*ec02198aSmrg 	return 0;
1636*ec02198aSmrg     }
1637*ec02198aSmrg   if (pcrange->highpc_is_relative)
1638*ec02198aSmrg     highpc += lowpc;
1639*ec02198aSmrg 
1640*ec02198aSmrg   /* Add in the base address of the module when recording PC values,
1641*ec02198aSmrg      so that we can look up the PC directly.  */
1642*ec02198aSmrg   lowpc += base_address;
1643*ec02198aSmrg   highpc += base_address;
1644*ec02198aSmrg 
1645*ec02198aSmrg   return add_range (state, rdata, lowpc, highpc, error_callback, data, vec);
1646*ec02198aSmrg }
1647*ec02198aSmrg 
1648*ec02198aSmrg /* Call ADD_RANGE for each range read from .debug_ranges, as used in
1649*ec02198aSmrg    DWARF versions 2 through 4.  */
1650*ec02198aSmrg 
1651*ec02198aSmrg static int
add_ranges_from_ranges(struct backtrace_state * state,const struct dwarf_sections * dwarf_sections,uintptr_t base_address,int is_bigendian,struct unit * u,uint64_t base,const struct pcrange * pcrange,int (* add_range)(struct backtrace_state * state,void * rdata,uint64_t lowpc,uint64_t highpc,backtrace_error_callback error_callback,void * data,void * vec),void * rdata,backtrace_error_callback error_callback,void * data,void * vec)1652*ec02198aSmrg add_ranges_from_ranges (
1653*ec02198aSmrg     struct backtrace_state *state,
1654*ec02198aSmrg     const struct dwarf_sections *dwarf_sections,
1655*ec02198aSmrg     uintptr_t base_address, int is_bigendian,
1656*ec02198aSmrg     struct unit *u, uint64_t base,
1657*ec02198aSmrg     const struct pcrange *pcrange,
1658*ec02198aSmrg     int (*add_range) (struct backtrace_state *state, void *rdata,
1659*ec02198aSmrg 		      uint64_t lowpc, uint64_t highpc,
1660*ec02198aSmrg 		      backtrace_error_callback error_callback, void *data,
1661*ec02198aSmrg 		      void *vec),
1662*ec02198aSmrg     void *rdata,
1663*ec02198aSmrg     backtrace_error_callback error_callback, void *data,
1664*ec02198aSmrg     void *vec)
166563d1a8abSmrg {
166663d1a8abSmrg   struct dwarf_buf ranges_buf;
166763d1a8abSmrg 
1668*ec02198aSmrg   if (pcrange->ranges >= dwarf_sections->size[DEBUG_RANGES])
166963d1a8abSmrg     {
167063d1a8abSmrg       error_callback (data, "ranges offset out of range", 0);
167163d1a8abSmrg       return 0;
167263d1a8abSmrg     }
167363d1a8abSmrg 
167463d1a8abSmrg   ranges_buf.name = ".debug_ranges";
1675*ec02198aSmrg   ranges_buf.start = dwarf_sections->data[DEBUG_RANGES];
1676*ec02198aSmrg   ranges_buf.buf = dwarf_sections->data[DEBUG_RANGES] + pcrange->ranges;
1677*ec02198aSmrg   ranges_buf.left = dwarf_sections->size[DEBUG_RANGES] - pcrange->ranges;
167863d1a8abSmrg   ranges_buf.is_bigendian = is_bigendian;
167963d1a8abSmrg   ranges_buf.error_callback = error_callback;
168063d1a8abSmrg   ranges_buf.data = data;
168163d1a8abSmrg   ranges_buf.reported_underflow = 0;
168263d1a8abSmrg 
168363d1a8abSmrg   while (1)
168463d1a8abSmrg     {
168563d1a8abSmrg       uint64_t low;
168663d1a8abSmrg       uint64_t high;
168763d1a8abSmrg 
168863d1a8abSmrg       if (ranges_buf.reported_underflow)
168963d1a8abSmrg 	return 0;
169063d1a8abSmrg 
169163d1a8abSmrg       low = read_address (&ranges_buf, u->addrsize);
169263d1a8abSmrg       high = read_address (&ranges_buf, u->addrsize);
169363d1a8abSmrg 
169463d1a8abSmrg       if (low == 0 && high == 0)
169563d1a8abSmrg 	break;
169663d1a8abSmrg 
169763d1a8abSmrg       if (is_highest_address (low, u->addrsize))
169863d1a8abSmrg 	base = high;
169963d1a8abSmrg       else
170063d1a8abSmrg 	{
1701*ec02198aSmrg 	  if (!add_range (state, rdata,
1702*ec02198aSmrg 			  low + base + base_address,
1703*ec02198aSmrg 			  high + base + base_address,
1704*ec02198aSmrg 			  error_callback, data, vec))
170563d1a8abSmrg 	    return 0;
170663d1a8abSmrg 	}
170763d1a8abSmrg     }
170863d1a8abSmrg 
170963d1a8abSmrg   if (ranges_buf.reported_underflow)
171063d1a8abSmrg     return 0;
171163d1a8abSmrg 
171263d1a8abSmrg   return 1;
171363d1a8abSmrg }
171463d1a8abSmrg 
1715*ec02198aSmrg /* Call ADD_RANGE for each range read from .debug_rnglists, as used in
1716*ec02198aSmrg    DWARF version 5.  */
1717*ec02198aSmrg 
1718*ec02198aSmrg static int
add_ranges_from_rnglists(struct backtrace_state * state,const struct dwarf_sections * dwarf_sections,uintptr_t base_address,int is_bigendian,struct unit * u,uint64_t base,const struct pcrange * pcrange,int (* add_range)(struct backtrace_state * state,void * rdata,uint64_t lowpc,uint64_t highpc,backtrace_error_callback error_callback,void * data,void * vec),void * rdata,backtrace_error_callback error_callback,void * data,void * vec)1719*ec02198aSmrg add_ranges_from_rnglists (
1720*ec02198aSmrg     struct backtrace_state *state,
1721*ec02198aSmrg     const struct dwarf_sections *dwarf_sections,
1722*ec02198aSmrg     uintptr_t base_address, int is_bigendian,
1723*ec02198aSmrg     struct unit *u, uint64_t base,
1724*ec02198aSmrg     const struct pcrange *pcrange,
1725*ec02198aSmrg     int (*add_range) (struct backtrace_state *state, void *rdata,
1726*ec02198aSmrg 		      uint64_t lowpc, uint64_t highpc,
1727*ec02198aSmrg 		      backtrace_error_callback error_callback, void *data,
1728*ec02198aSmrg 		      void *vec),
1729*ec02198aSmrg     void *rdata,
1730*ec02198aSmrg     backtrace_error_callback error_callback, void *data,
1731*ec02198aSmrg     void *vec)
1732*ec02198aSmrg {
1733*ec02198aSmrg   uint64_t offset;
1734*ec02198aSmrg   struct dwarf_buf rnglists_buf;
1735*ec02198aSmrg 
1736*ec02198aSmrg   if (!pcrange->ranges_is_index)
1737*ec02198aSmrg     offset = pcrange->ranges;
1738*ec02198aSmrg   else
1739*ec02198aSmrg     offset = u->rnglists_base + pcrange->ranges * (u->is_dwarf64 ? 8 : 4);
1740*ec02198aSmrg   if (offset >= dwarf_sections->size[DEBUG_RNGLISTS])
1741*ec02198aSmrg     {
1742*ec02198aSmrg       error_callback (data, "rnglists offset out of range", 0);
1743*ec02198aSmrg       return 0;
1744*ec02198aSmrg     }
1745*ec02198aSmrg 
1746*ec02198aSmrg   rnglists_buf.name = ".debug_rnglists";
1747*ec02198aSmrg   rnglists_buf.start = dwarf_sections->data[DEBUG_RNGLISTS];
1748*ec02198aSmrg   rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;
1749*ec02198aSmrg   rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;
1750*ec02198aSmrg   rnglists_buf.is_bigendian = is_bigendian;
1751*ec02198aSmrg   rnglists_buf.error_callback = error_callback;
1752*ec02198aSmrg   rnglists_buf.data = data;
1753*ec02198aSmrg   rnglists_buf.reported_underflow = 0;
1754*ec02198aSmrg 
1755*ec02198aSmrg   if (pcrange->ranges_is_index)
1756*ec02198aSmrg     {
1757*ec02198aSmrg       offset = read_offset (&rnglists_buf, u->is_dwarf64);
1758*ec02198aSmrg       offset += u->rnglists_base;
1759*ec02198aSmrg       if (offset >= dwarf_sections->size[DEBUG_RNGLISTS])
1760*ec02198aSmrg 	{
1761*ec02198aSmrg 	  error_callback (data, "rnglists index offset out of range", 0);
1762*ec02198aSmrg 	  return 0;
1763*ec02198aSmrg 	}
1764*ec02198aSmrg       rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset;
1765*ec02198aSmrg       rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset;
1766*ec02198aSmrg     }
1767*ec02198aSmrg 
1768*ec02198aSmrg   while (1)
1769*ec02198aSmrg     {
1770*ec02198aSmrg       unsigned char rle;
1771*ec02198aSmrg 
1772*ec02198aSmrg       rle = read_byte (&rnglists_buf);
1773*ec02198aSmrg       if (rle == DW_RLE_end_of_list)
1774*ec02198aSmrg 	break;
1775*ec02198aSmrg       switch (rle)
1776*ec02198aSmrg 	{
1777*ec02198aSmrg 	case DW_RLE_base_addressx:
1778*ec02198aSmrg 	  {
1779*ec02198aSmrg 	    uint64_t index;
1780*ec02198aSmrg 
1781*ec02198aSmrg 	    index = read_uleb128 (&rnglists_buf);
1782*ec02198aSmrg 	    if (!resolve_addr_index (dwarf_sections, u->addr_base,
1783*ec02198aSmrg 				     u->addrsize, is_bigendian, index,
1784*ec02198aSmrg 				     error_callback, data, &base))
1785*ec02198aSmrg 	      return 0;
1786*ec02198aSmrg 	  }
1787*ec02198aSmrg 	  break;
1788*ec02198aSmrg 
1789*ec02198aSmrg 	case DW_RLE_startx_endx:
1790*ec02198aSmrg 	  {
1791*ec02198aSmrg 	    uint64_t index;
1792*ec02198aSmrg 	    uint64_t low;
1793*ec02198aSmrg 	    uint64_t high;
1794*ec02198aSmrg 
1795*ec02198aSmrg 	    index = read_uleb128 (&rnglists_buf);
1796*ec02198aSmrg 	    if (!resolve_addr_index (dwarf_sections, u->addr_base,
1797*ec02198aSmrg 				     u->addrsize, is_bigendian, index,
1798*ec02198aSmrg 				     error_callback, data, &low))
1799*ec02198aSmrg 	      return 0;
1800*ec02198aSmrg 	    index = read_uleb128 (&rnglists_buf);
1801*ec02198aSmrg 	    if (!resolve_addr_index (dwarf_sections, u->addr_base,
1802*ec02198aSmrg 				     u->addrsize, is_bigendian, index,
1803*ec02198aSmrg 				     error_callback, data, &high))
1804*ec02198aSmrg 	      return 0;
1805*ec02198aSmrg 	    if (!add_range (state, rdata, low + base_address,
1806*ec02198aSmrg 			    high + base_address, error_callback, data,
1807*ec02198aSmrg 			    vec))
1808*ec02198aSmrg 	      return 0;
1809*ec02198aSmrg 	  }
1810*ec02198aSmrg 	  break;
1811*ec02198aSmrg 
1812*ec02198aSmrg 	case DW_RLE_startx_length:
1813*ec02198aSmrg 	  {
1814*ec02198aSmrg 	    uint64_t index;
1815*ec02198aSmrg 	    uint64_t low;
1816*ec02198aSmrg 	    uint64_t length;
1817*ec02198aSmrg 
1818*ec02198aSmrg 	    index = read_uleb128 (&rnglists_buf);
1819*ec02198aSmrg 	    if (!resolve_addr_index (dwarf_sections, u->addr_base,
1820*ec02198aSmrg 				     u->addrsize, is_bigendian, index,
1821*ec02198aSmrg 				     error_callback, data, &low))
1822*ec02198aSmrg 	      return 0;
1823*ec02198aSmrg 	    length = read_uleb128 (&rnglists_buf);
1824*ec02198aSmrg 	    low += base_address;
1825*ec02198aSmrg 	    if (!add_range (state, rdata, low, low + length,
1826*ec02198aSmrg 			    error_callback, data, vec))
1827*ec02198aSmrg 	      return 0;
1828*ec02198aSmrg 	  }
1829*ec02198aSmrg 	  break;
1830*ec02198aSmrg 
1831*ec02198aSmrg 	case DW_RLE_offset_pair:
1832*ec02198aSmrg 	  {
1833*ec02198aSmrg 	    uint64_t low;
1834*ec02198aSmrg 	    uint64_t high;
1835*ec02198aSmrg 
1836*ec02198aSmrg 	    low = read_uleb128 (&rnglists_buf);
1837*ec02198aSmrg 	    high = read_uleb128 (&rnglists_buf);
1838*ec02198aSmrg 	    if (!add_range (state, rdata, low + base + base_address,
1839*ec02198aSmrg 			    high + base + base_address,
1840*ec02198aSmrg 			    error_callback, data, vec))
1841*ec02198aSmrg 	      return 0;
1842*ec02198aSmrg 	  }
1843*ec02198aSmrg 	  break;
1844*ec02198aSmrg 
1845*ec02198aSmrg 	case DW_RLE_base_address:
1846*ec02198aSmrg 	  base = read_address (&rnglists_buf, u->addrsize);
1847*ec02198aSmrg 	  break;
1848*ec02198aSmrg 
1849*ec02198aSmrg 	case DW_RLE_start_end:
1850*ec02198aSmrg 	  {
1851*ec02198aSmrg 	    uint64_t low;
1852*ec02198aSmrg 	    uint64_t high;
1853*ec02198aSmrg 
1854*ec02198aSmrg 	    low = read_address (&rnglists_buf, u->addrsize);
1855*ec02198aSmrg 	    high = read_address (&rnglists_buf, u->addrsize);
1856*ec02198aSmrg 	    if (!add_range (state, rdata, low + base_address,
1857*ec02198aSmrg 			    high + base_address, error_callback, data,
1858*ec02198aSmrg 			    vec))
1859*ec02198aSmrg 	      return 0;
1860*ec02198aSmrg 	  }
1861*ec02198aSmrg 	  break;
1862*ec02198aSmrg 
1863*ec02198aSmrg 	case DW_RLE_start_length:
1864*ec02198aSmrg 	  {
1865*ec02198aSmrg 	    uint64_t low;
1866*ec02198aSmrg 	    uint64_t length;
1867*ec02198aSmrg 
1868*ec02198aSmrg 	    low = read_address (&rnglists_buf, u->addrsize);
1869*ec02198aSmrg 	    length = read_uleb128 (&rnglists_buf);
1870*ec02198aSmrg 	    low += base_address;
1871*ec02198aSmrg 	    if (!add_range (state, rdata, low, low + length,
1872*ec02198aSmrg 			    error_callback, data, vec))
1873*ec02198aSmrg 	      return 0;
1874*ec02198aSmrg 	  }
1875*ec02198aSmrg 	  break;
1876*ec02198aSmrg 
1877*ec02198aSmrg 	default:
1878*ec02198aSmrg 	  dwarf_buf_error (&rnglists_buf, "unrecognized DW_RLE value");
1879*ec02198aSmrg 	  return 0;
1880*ec02198aSmrg 	}
1881*ec02198aSmrg     }
1882*ec02198aSmrg 
1883*ec02198aSmrg   if (rnglists_buf.reported_underflow)
1884*ec02198aSmrg     return 0;
1885*ec02198aSmrg 
1886*ec02198aSmrg   return 1;
1887*ec02198aSmrg }
1888*ec02198aSmrg 
1889*ec02198aSmrg /* Call ADD_RANGE for each lowpc/highpc pair in PCRANGE.  RDATA is
1890*ec02198aSmrg    passed to ADD_RANGE, and is either a struct unit * or a struct
1891*ec02198aSmrg    function *.  VEC is the vector we are adding ranges to, and is
1892*ec02198aSmrg    either a struct unit_addrs_vector * or a struct function_vector *.
1893*ec02198aSmrg    Returns 1 on success, 0 on error.  */
1894*ec02198aSmrg 
1895*ec02198aSmrg static int
add_ranges(struct backtrace_state * state,const struct dwarf_sections * dwarf_sections,uintptr_t base_address,int is_bigendian,struct unit * u,uint64_t base,const struct pcrange * pcrange,int (* add_range)(struct backtrace_state * state,void * rdata,uint64_t lowpc,uint64_t highpc,backtrace_error_callback error_callback,void * data,void * vec),void * rdata,backtrace_error_callback error_callback,void * data,void * vec)1896*ec02198aSmrg add_ranges (struct backtrace_state *state,
1897*ec02198aSmrg 	    const struct dwarf_sections *dwarf_sections,
1898*ec02198aSmrg 	    uintptr_t base_address, int is_bigendian,
1899*ec02198aSmrg 	    struct unit *u, uint64_t base, const struct pcrange *pcrange,
1900*ec02198aSmrg 	    int (*add_range) (struct backtrace_state *state, void *rdata,
1901*ec02198aSmrg 			      uint64_t lowpc, uint64_t highpc,
1902*ec02198aSmrg 			      backtrace_error_callback error_callback,
1903*ec02198aSmrg 			      void *data, void *vec),
1904*ec02198aSmrg 	    void *rdata,
1905*ec02198aSmrg 	    backtrace_error_callback error_callback, void *data,
1906*ec02198aSmrg 	    void *vec)
1907*ec02198aSmrg {
1908*ec02198aSmrg   if (pcrange->have_lowpc && pcrange->have_highpc)
1909*ec02198aSmrg     return add_low_high_range (state, dwarf_sections, base_address,
1910*ec02198aSmrg 			       is_bigendian, u, pcrange, add_range, rdata,
1911*ec02198aSmrg 			       error_callback, data, vec);
1912*ec02198aSmrg 
1913*ec02198aSmrg   if (!pcrange->have_ranges)
1914*ec02198aSmrg     {
1915*ec02198aSmrg       /* Did not find any address ranges to add.  */
1916*ec02198aSmrg       return 1;
1917*ec02198aSmrg     }
1918*ec02198aSmrg 
1919*ec02198aSmrg   if (u->version < 5)
1920*ec02198aSmrg     return add_ranges_from_ranges (state, dwarf_sections, base_address,
1921*ec02198aSmrg 				   is_bigendian, u, base, pcrange, add_range,
1922*ec02198aSmrg 				   rdata, error_callback, data, vec);
1923*ec02198aSmrg   else
1924*ec02198aSmrg     return add_ranges_from_rnglists (state, dwarf_sections, base_address,
1925*ec02198aSmrg 				     is_bigendian, u, base, pcrange, add_range,
1926*ec02198aSmrg 				     rdata, error_callback, data, vec);
1927*ec02198aSmrg }
1928*ec02198aSmrg 
192963d1a8abSmrg /* Find the address range covered by a compilation unit, reading from
193063d1a8abSmrg    UNIT_BUF and adding values to U.  Returns 1 if all data could be
193163d1a8abSmrg    read, 0 if there is some error.  */
193263d1a8abSmrg 
193363d1a8abSmrg static int
find_address_ranges(struct backtrace_state * state,uintptr_t base_address,struct dwarf_buf * unit_buf,const struct dwarf_sections * dwarf_sections,int is_bigendian,struct dwarf_data * altlink,backtrace_error_callback error_callback,void * data,struct unit * u,struct unit_addrs_vector * addrs,enum dwarf_tag * unit_tag)193463d1a8abSmrg find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
193563d1a8abSmrg 		     struct dwarf_buf *unit_buf,
1936*ec02198aSmrg 		     const struct dwarf_sections *dwarf_sections,
19370fc04c29Smrg 		     int is_bigendian, struct dwarf_data *altlink,
19380fc04c29Smrg 		     backtrace_error_callback error_callback, void *data,
19390fc04c29Smrg 		     struct unit *u, struct unit_addrs_vector *addrs,
19400fc04c29Smrg 		     enum dwarf_tag *unit_tag)
194163d1a8abSmrg {
194263d1a8abSmrg   while (unit_buf->left > 0)
194363d1a8abSmrg     {
194463d1a8abSmrg       uint64_t code;
194563d1a8abSmrg       const struct abbrev *abbrev;
1946*ec02198aSmrg       struct pcrange pcrange;
1947*ec02198aSmrg       struct attr_val name_val;
1948*ec02198aSmrg       int have_name_val;
1949*ec02198aSmrg       struct attr_val comp_dir_val;
1950*ec02198aSmrg       int have_comp_dir_val;
195163d1a8abSmrg       size_t i;
195263d1a8abSmrg 
195363d1a8abSmrg       code = read_uleb128 (unit_buf);
195463d1a8abSmrg       if (code == 0)
195563d1a8abSmrg 	return 1;
195663d1a8abSmrg 
195763d1a8abSmrg       abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
195863d1a8abSmrg       if (abbrev == NULL)
195963d1a8abSmrg 	return 0;
196063d1a8abSmrg 
19610fc04c29Smrg       if (unit_tag != NULL)
19620fc04c29Smrg 	*unit_tag = abbrev->tag;
19630fc04c29Smrg 
1964*ec02198aSmrg       memset (&pcrange, 0, sizeof pcrange);
1965*ec02198aSmrg       memset (&name_val, 0, sizeof name_val);
1966*ec02198aSmrg       have_name_val = 0;
1967*ec02198aSmrg       memset (&comp_dir_val, 0, sizeof comp_dir_val);
1968*ec02198aSmrg       have_comp_dir_val = 0;
196963d1a8abSmrg       for (i = 0; i < abbrev->num_attrs; ++i)
197063d1a8abSmrg 	{
197163d1a8abSmrg 	  struct attr_val val;
197263d1a8abSmrg 
1973*ec02198aSmrg 	  if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,
1974*ec02198aSmrg 			       unit_buf, u->is_dwarf64, u->version,
1975*ec02198aSmrg 			       u->addrsize, dwarf_sections, altlink, &val))
197663d1a8abSmrg 	    return 0;
197763d1a8abSmrg 
197863d1a8abSmrg 	  switch (abbrev->attrs[i].name)
197963d1a8abSmrg 	    {
1980*ec02198aSmrg 	    case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges:
1981*ec02198aSmrg 	      update_pcrange (&abbrev->attrs[i], &val, &pcrange);
198263d1a8abSmrg 	      break;
198363d1a8abSmrg 
198463d1a8abSmrg 	    case DW_AT_stmt_list:
198563d1a8abSmrg 	      if (abbrev->tag == DW_TAG_compile_unit
198663d1a8abSmrg 		  && (val.encoding == ATTR_VAL_UINT
198763d1a8abSmrg 		      || val.encoding == ATTR_VAL_REF_SECTION))
198863d1a8abSmrg 		u->lineoff = val.u.uint;
198963d1a8abSmrg 	      break;
199063d1a8abSmrg 
199163d1a8abSmrg 	    case DW_AT_name:
1992*ec02198aSmrg 	      if (abbrev->tag == DW_TAG_compile_unit)
1993*ec02198aSmrg 		{
1994*ec02198aSmrg 		  name_val = val;
1995*ec02198aSmrg 		  have_name_val = 1;
1996*ec02198aSmrg 		}
199763d1a8abSmrg 	      break;
199863d1a8abSmrg 
199963d1a8abSmrg 	    case DW_AT_comp_dir:
2000*ec02198aSmrg 	      if (abbrev->tag == DW_TAG_compile_unit)
2001*ec02198aSmrg 		{
2002*ec02198aSmrg 		  comp_dir_val = val;
2003*ec02198aSmrg 		  have_comp_dir_val = 1;
2004*ec02198aSmrg 		}
2005*ec02198aSmrg 	      break;
2006*ec02198aSmrg 
2007*ec02198aSmrg 	    case DW_AT_str_offsets_base:
200863d1a8abSmrg 	      if (abbrev->tag == DW_TAG_compile_unit
2009*ec02198aSmrg 		  && val.encoding == ATTR_VAL_REF_SECTION)
2010*ec02198aSmrg 		u->str_offsets_base = val.u.uint;
2011*ec02198aSmrg 	      break;
2012*ec02198aSmrg 
2013*ec02198aSmrg 	    case DW_AT_addr_base:
2014*ec02198aSmrg 	      if (abbrev->tag == DW_TAG_compile_unit
2015*ec02198aSmrg 		  && val.encoding == ATTR_VAL_REF_SECTION)
2016*ec02198aSmrg 		u->addr_base = val.u.uint;
2017*ec02198aSmrg 	      break;
2018*ec02198aSmrg 
2019*ec02198aSmrg 	    case DW_AT_rnglists_base:
2020*ec02198aSmrg 	      if (abbrev->tag == DW_TAG_compile_unit
2021*ec02198aSmrg 		  && val.encoding == ATTR_VAL_REF_SECTION)
2022*ec02198aSmrg 		u->rnglists_base = val.u.uint;
202363d1a8abSmrg 	      break;
202463d1a8abSmrg 
202563d1a8abSmrg 	    default:
202663d1a8abSmrg 	      break;
202763d1a8abSmrg 	    }
202863d1a8abSmrg 	}
202963d1a8abSmrg 
2030*ec02198aSmrg       // Resolve strings after we're sure that we have seen
2031*ec02198aSmrg       // DW_AT_str_offsets_base.
2032*ec02198aSmrg       if (have_name_val)
2033*ec02198aSmrg 	{
2034*ec02198aSmrg 	  if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian,
2035*ec02198aSmrg 			       u->str_offsets_base, &name_val,
2036*ec02198aSmrg 			       error_callback, data, &u->filename))
2037*ec02198aSmrg 	    return 0;
2038*ec02198aSmrg 	}
2039*ec02198aSmrg       if (have_comp_dir_val)
2040*ec02198aSmrg 	{
2041*ec02198aSmrg 	  if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian,
2042*ec02198aSmrg 			       u->str_offsets_base, &comp_dir_val,
2043*ec02198aSmrg 			       error_callback, data, &u->comp_dir))
2044*ec02198aSmrg 	    return 0;
2045*ec02198aSmrg 	}
2046*ec02198aSmrg 
204763d1a8abSmrg       if (abbrev->tag == DW_TAG_compile_unit
204863d1a8abSmrg 	  || abbrev->tag == DW_TAG_subprogram)
204963d1a8abSmrg 	{
2050*ec02198aSmrg 	  if (!add_ranges (state, dwarf_sections, base_address,
2051*ec02198aSmrg 			   is_bigendian, u, pcrange.lowpc, &pcrange,
2052*ec02198aSmrg 			   add_unit_addr, (void *) u, error_callback, data,
2053*ec02198aSmrg 			   (void *) addrs))
205463d1a8abSmrg 	    return 0;
205563d1a8abSmrg 
205663d1a8abSmrg 	  /* If we found the PC range in the DW_TAG_compile_unit, we
205763d1a8abSmrg 	     can stop now.  */
205863d1a8abSmrg 	  if (abbrev->tag == DW_TAG_compile_unit
2059*ec02198aSmrg 	      && (pcrange.have_ranges
2060*ec02198aSmrg 		  || (pcrange.have_lowpc && pcrange.have_highpc)))
206163d1a8abSmrg 	    return 1;
206263d1a8abSmrg 	}
206363d1a8abSmrg 
206463d1a8abSmrg       if (abbrev->has_children)
206563d1a8abSmrg 	{
206663d1a8abSmrg 	  if (!find_address_ranges (state, base_address, unit_buf,
2067*ec02198aSmrg 				    dwarf_sections, is_bigendian, altlink,
2068*ec02198aSmrg 				    error_callback, data, u, addrs, NULL))
206963d1a8abSmrg 	    return 0;
207063d1a8abSmrg 	}
207163d1a8abSmrg     }
207263d1a8abSmrg 
207363d1a8abSmrg   return 1;
207463d1a8abSmrg }
207563d1a8abSmrg 
207663d1a8abSmrg /* Build a mapping from address ranges to the compilation units where
207763d1a8abSmrg    the line number information for that range can be found.  Returns 1
207863d1a8abSmrg    on success, 0 on failure.  */
207963d1a8abSmrg 
208063d1a8abSmrg static int
build_address_map(struct backtrace_state * state,uintptr_t base_address,const struct dwarf_sections * dwarf_sections,int is_bigendian,struct dwarf_data * altlink,backtrace_error_callback error_callback,void * data,struct unit_addrs_vector * addrs,struct unit_vector * unit_vec)208163d1a8abSmrg build_address_map (struct backtrace_state *state, uintptr_t base_address,
2082*ec02198aSmrg 		   const struct dwarf_sections *dwarf_sections,
20830fc04c29Smrg 		   int is_bigendian, struct dwarf_data *altlink,
20840fc04c29Smrg 		   backtrace_error_callback error_callback, void *data,
20850fc04c29Smrg 		   struct unit_addrs_vector *addrs,
20860fc04c29Smrg 		   struct unit_vector *unit_vec)
208763d1a8abSmrg {
208863d1a8abSmrg   struct dwarf_buf info;
20890fc04c29Smrg   struct backtrace_vector units;
20900fc04c29Smrg   size_t units_count;
20910fc04c29Smrg   size_t i;
20920fc04c29Smrg   struct unit **pu;
20930fc04c29Smrg   size_t unit_offset = 0;
209463d1a8abSmrg 
209563d1a8abSmrg   memset (&addrs->vec, 0, sizeof addrs->vec);
20960fc04c29Smrg   memset (&unit_vec->vec, 0, sizeof unit_vec->vec);
209763d1a8abSmrg   addrs->count = 0;
20980fc04c29Smrg   unit_vec->count = 0;
209963d1a8abSmrg 
210063d1a8abSmrg   /* Read through the .debug_info section.  FIXME: Should we use the
210163d1a8abSmrg      .debug_aranges section?  gdb and addr2line don't use it, but I'm
210263d1a8abSmrg      not sure why.  */
210363d1a8abSmrg 
210463d1a8abSmrg   info.name = ".debug_info";
2105*ec02198aSmrg   info.start = dwarf_sections->data[DEBUG_INFO];
2106*ec02198aSmrg   info.buf = info.start;
2107*ec02198aSmrg   info.left = dwarf_sections->size[DEBUG_INFO];
210863d1a8abSmrg   info.is_bigendian = is_bigendian;
210963d1a8abSmrg   info.error_callback = error_callback;
211063d1a8abSmrg   info.data = data;
211163d1a8abSmrg   info.reported_underflow = 0;
211263d1a8abSmrg 
21130fc04c29Smrg   memset (&units, 0, sizeof units);
21140fc04c29Smrg   units_count = 0;
21150fc04c29Smrg 
211663d1a8abSmrg   while (info.left > 0)
211763d1a8abSmrg     {
211863d1a8abSmrg       const unsigned char *unit_data_start;
211963d1a8abSmrg       uint64_t len;
212063d1a8abSmrg       int is_dwarf64;
212163d1a8abSmrg       struct dwarf_buf unit_buf;
212263d1a8abSmrg       int version;
2123*ec02198aSmrg       int unit_type;
212463d1a8abSmrg       uint64_t abbrev_offset;
212563d1a8abSmrg       int addrsize;
212663d1a8abSmrg       struct unit *u;
21270fc04c29Smrg       enum dwarf_tag unit_tag;
212863d1a8abSmrg 
212963d1a8abSmrg       if (info.reported_underflow)
213063d1a8abSmrg 	goto fail;
213163d1a8abSmrg 
213263d1a8abSmrg       unit_data_start = info.buf;
213363d1a8abSmrg 
21340fc04c29Smrg       len = read_initial_length (&info, &is_dwarf64);
213563d1a8abSmrg       unit_buf = info;
213663d1a8abSmrg       unit_buf.left = len;
213763d1a8abSmrg 
213863d1a8abSmrg       if (!advance (&info, len))
213963d1a8abSmrg 	goto fail;
214063d1a8abSmrg 
214163d1a8abSmrg       version = read_uint16 (&unit_buf);
2142*ec02198aSmrg       if (version < 2 || version > 5)
214363d1a8abSmrg 	{
214463d1a8abSmrg 	  dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
214563d1a8abSmrg 	  goto fail;
214663d1a8abSmrg 	}
214763d1a8abSmrg 
2148*ec02198aSmrg       if (version < 5)
2149*ec02198aSmrg 	unit_type = 0;
2150*ec02198aSmrg       else
2151*ec02198aSmrg 	{
2152*ec02198aSmrg 	  unit_type = read_byte (&unit_buf);
2153*ec02198aSmrg 	  if (unit_type == DW_UT_type || unit_type == DW_UT_split_type)
2154*ec02198aSmrg 	    {
2155*ec02198aSmrg 	      /* This unit doesn't have anything we need.  */
2156*ec02198aSmrg 	      continue;
2157*ec02198aSmrg 	    }
2158*ec02198aSmrg 	}
2159*ec02198aSmrg 
21600fc04c29Smrg       pu = ((struct unit **)
21610fc04c29Smrg 	    backtrace_vector_grow (state, sizeof (struct unit *),
21620fc04c29Smrg 				   error_callback, data, &units));
21630fc04c29Smrg       if (pu == NULL)
216463d1a8abSmrg 	  goto fail;
216563d1a8abSmrg 
216663d1a8abSmrg       u = ((struct unit *)
216763d1a8abSmrg 	   backtrace_alloc (state, sizeof *u, error_callback, data));
216863d1a8abSmrg       if (u == NULL)
216963d1a8abSmrg 	goto fail;
21700fc04c29Smrg 
21710fc04c29Smrg       *pu = u;
21720fc04c29Smrg       ++units_count;
21730fc04c29Smrg 
2174*ec02198aSmrg       if (version < 5)
2175*ec02198aSmrg 	addrsize = 0; /* Set below.  */
2176*ec02198aSmrg       else
2177*ec02198aSmrg 	addrsize = read_byte (&unit_buf);
2178*ec02198aSmrg 
21790fc04c29Smrg       memset (&u->abbrevs, 0, sizeof u->abbrevs);
21800fc04c29Smrg       abbrev_offset = read_offset (&unit_buf, is_dwarf64);
2181*ec02198aSmrg       if (!read_abbrevs (state, abbrev_offset,
2182*ec02198aSmrg 			 dwarf_sections->data[DEBUG_ABBREV],
2183*ec02198aSmrg 			 dwarf_sections->size[DEBUG_ABBREV],
21840fc04c29Smrg 			 is_bigendian, error_callback, data, &u->abbrevs))
21850fc04c29Smrg 	goto fail;
21860fc04c29Smrg 
2187*ec02198aSmrg       if (version < 5)
21880fc04c29Smrg 	addrsize = read_byte (&unit_buf);
21890fc04c29Smrg 
2190*ec02198aSmrg       switch (unit_type)
2191*ec02198aSmrg 	{
2192*ec02198aSmrg 	case 0:
2193*ec02198aSmrg 	  break;
2194*ec02198aSmrg 	case DW_UT_compile: case DW_UT_partial:
2195*ec02198aSmrg 	  break;
2196*ec02198aSmrg 	case DW_UT_skeleton: case DW_UT_split_compile:
2197*ec02198aSmrg 	  read_uint64 (&unit_buf); /* dwo_id */
2198*ec02198aSmrg 	  break;
2199*ec02198aSmrg 	default:
2200*ec02198aSmrg 	  break;
2201*ec02198aSmrg 	}
2202*ec02198aSmrg 
22030fc04c29Smrg       u->low_offset = unit_offset;
22040fc04c29Smrg       unit_offset += len + (is_dwarf64 ? 12 : 4);
22050fc04c29Smrg       u->high_offset = unit_offset;
220663d1a8abSmrg       u->unit_data = unit_buf.buf;
220763d1a8abSmrg       u->unit_data_len = unit_buf.left;
220863d1a8abSmrg       u->unit_data_offset = unit_buf.buf - unit_data_start;
220963d1a8abSmrg       u->version = version;
221063d1a8abSmrg       u->is_dwarf64 = is_dwarf64;
221163d1a8abSmrg       u->addrsize = addrsize;
221263d1a8abSmrg       u->filename = NULL;
221363d1a8abSmrg       u->comp_dir = NULL;
221463d1a8abSmrg       u->abs_filename = NULL;
221563d1a8abSmrg       u->lineoff = 0;
221663d1a8abSmrg 
221763d1a8abSmrg       /* The actual line number mappings will be read as needed.  */
221863d1a8abSmrg       u->lines = NULL;
221963d1a8abSmrg       u->lines_count = 0;
222063d1a8abSmrg       u->function_addrs = NULL;
222163d1a8abSmrg       u->function_addrs_count = 0;
222263d1a8abSmrg 
2223*ec02198aSmrg       if (!find_address_ranges (state, base_address, &unit_buf, dwarf_sections,
22240fc04c29Smrg 				is_bigendian, altlink, error_callback, data,
22250fc04c29Smrg 				u, addrs, &unit_tag))
222663d1a8abSmrg 	goto fail;
222763d1a8abSmrg 
222863d1a8abSmrg       if (unit_buf.reported_underflow)
222963d1a8abSmrg 	goto fail;
223063d1a8abSmrg     }
223163d1a8abSmrg   if (info.reported_underflow)
223263d1a8abSmrg     goto fail;
223363d1a8abSmrg 
22340fc04c29Smrg   unit_vec->vec = units;
22350fc04c29Smrg   unit_vec->count = units_count;
223663d1a8abSmrg   return 1;
223763d1a8abSmrg 
223863d1a8abSmrg  fail:
22390fc04c29Smrg   if (units_count > 0)
22400fc04c29Smrg     {
22410fc04c29Smrg       pu = (struct unit **) units.base;
22420fc04c29Smrg       for (i = 0; i < units_count; i++)
22430fc04c29Smrg 	{
22440fc04c29Smrg 	  free_abbrevs (state, &pu[i]->abbrevs, error_callback, data);
22450fc04c29Smrg 	  backtrace_free (state, pu[i], sizeof **pu, error_callback, data);
22460fc04c29Smrg 	}
22470fc04c29Smrg       backtrace_vector_free (state, &units, error_callback, data);
22480fc04c29Smrg     }
22490fc04c29Smrg   if (addrs->count > 0)
22500fc04c29Smrg     {
22510fc04c29Smrg       backtrace_vector_free (state, &addrs->vec, error_callback, data);
22520fc04c29Smrg       addrs->count = 0;
22530fc04c29Smrg     }
225463d1a8abSmrg   return 0;
225563d1a8abSmrg }
225663d1a8abSmrg 
225763d1a8abSmrg /* Add a new mapping to the vector of line mappings that we are
225863d1a8abSmrg    building.  Returns 1 on success, 0 on failure.  */
225963d1a8abSmrg 
226063d1a8abSmrg static int
add_line(struct backtrace_state * state,struct dwarf_data * ddata,uintptr_t pc,const char * filename,int lineno,backtrace_error_callback error_callback,void * data,struct line_vector * vec)226163d1a8abSmrg add_line (struct backtrace_state *state, struct dwarf_data *ddata,
226263d1a8abSmrg 	  uintptr_t pc, const char *filename, int lineno,
226363d1a8abSmrg 	  backtrace_error_callback error_callback, void *data,
226463d1a8abSmrg 	  struct line_vector *vec)
226563d1a8abSmrg {
226663d1a8abSmrg   struct line *ln;
226763d1a8abSmrg 
226863d1a8abSmrg   /* If we are adding the same mapping, ignore it.  This can happen
226963d1a8abSmrg      when using discriminators.  */
227063d1a8abSmrg   if (vec->count > 0)
227163d1a8abSmrg     {
227263d1a8abSmrg       ln = (struct line *) vec->vec.base + (vec->count - 1);
227363d1a8abSmrg       if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)
227463d1a8abSmrg 	return 1;
227563d1a8abSmrg     }
227663d1a8abSmrg 
227763d1a8abSmrg   ln = ((struct line *)
227863d1a8abSmrg 	backtrace_vector_grow (state, sizeof (struct line), error_callback,
227963d1a8abSmrg 			       data, &vec->vec));
228063d1a8abSmrg   if (ln == NULL)
228163d1a8abSmrg     return 0;
228263d1a8abSmrg 
228363d1a8abSmrg   /* Add in the base address here, so that we can look up the PC
228463d1a8abSmrg      directly.  */
228563d1a8abSmrg   ln->pc = pc + ddata->base_address;
228663d1a8abSmrg 
228763d1a8abSmrg   ln->filename = filename;
228863d1a8abSmrg   ln->lineno = lineno;
228963d1a8abSmrg   ln->idx = vec->count;
229063d1a8abSmrg 
229163d1a8abSmrg   ++vec->count;
229263d1a8abSmrg 
229363d1a8abSmrg   return 1;
229463d1a8abSmrg }
229563d1a8abSmrg 
2296c7a68eb7Smrg /* Free the line header information.  */
229763d1a8abSmrg 
229863d1a8abSmrg static void
free_line_header(struct backtrace_state * state,struct line_header * hdr,backtrace_error_callback error_callback,void * data)229963d1a8abSmrg free_line_header (struct backtrace_state *state, struct line_header *hdr,
230063d1a8abSmrg 		  backtrace_error_callback error_callback, void *data)
230163d1a8abSmrg {
2302c7a68eb7Smrg   if (hdr->dirs_count != 0)
230363d1a8abSmrg     backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),
230463d1a8abSmrg 		    error_callback, data);
230563d1a8abSmrg   backtrace_free (state, hdr->filenames,
230663d1a8abSmrg 		  hdr->filenames_count * sizeof (char *),
230763d1a8abSmrg 		  error_callback, data);
230863d1a8abSmrg }
230963d1a8abSmrg 
2310*ec02198aSmrg /* Read the directories and file names for a line header for version
2311*ec02198aSmrg    2, setting fields in HDR.  Return 1 on success, 0 on failure.  */
231263d1a8abSmrg 
231363d1a8abSmrg static int
read_v2_paths(struct backtrace_state * state,struct unit * u,struct dwarf_buf * hdr_buf,struct line_header * hdr)2314*ec02198aSmrg read_v2_paths (struct backtrace_state *state, struct unit *u,
2315*ec02198aSmrg 	       struct dwarf_buf *hdr_buf, struct line_header *hdr)
231663d1a8abSmrg {
231763d1a8abSmrg   const unsigned char *p;
231863d1a8abSmrg   const unsigned char *pend;
231963d1a8abSmrg   size_t i;
232063d1a8abSmrg 
2321*ec02198aSmrg   /* Count the number of directory entries.  */
2322*ec02198aSmrg   hdr->dirs_count = 0;
2323*ec02198aSmrg   p = hdr_buf->buf;
2324*ec02198aSmrg   pend = p + hdr_buf->left;
2325*ec02198aSmrg   while (p < pend && *p != '\0')
2326*ec02198aSmrg     {
2327*ec02198aSmrg       p += strnlen((const char *) p, pend - p) + 1;
2328*ec02198aSmrg       ++hdr->dirs_count;
2329*ec02198aSmrg     }
2330*ec02198aSmrg 
2331*ec02198aSmrg   hdr->dirs = NULL;
2332*ec02198aSmrg   if (hdr->dirs_count != 0)
2333*ec02198aSmrg     {
2334*ec02198aSmrg       hdr->dirs = ((const char **)
2335*ec02198aSmrg 		   backtrace_alloc (state,
2336*ec02198aSmrg 				    hdr->dirs_count * sizeof (const char *),
2337*ec02198aSmrg 				    hdr_buf->error_callback,
2338*ec02198aSmrg 				    hdr_buf->data));
2339*ec02198aSmrg       if (hdr->dirs == NULL)
2340*ec02198aSmrg 	return 0;
2341*ec02198aSmrg     }
2342*ec02198aSmrg 
2343*ec02198aSmrg   i = 0;
2344*ec02198aSmrg   while (*hdr_buf->buf != '\0')
2345*ec02198aSmrg     {
2346*ec02198aSmrg       if (hdr_buf->reported_underflow)
2347*ec02198aSmrg 	return 0;
2348*ec02198aSmrg 
2349*ec02198aSmrg       hdr->dirs[i] = read_string (hdr_buf);
2350*ec02198aSmrg       if (hdr->dirs[i] == NULL)
2351*ec02198aSmrg 	return 0;
2352*ec02198aSmrg       ++i;
2353*ec02198aSmrg     }
2354*ec02198aSmrg   if (!advance (hdr_buf, 1))
2355*ec02198aSmrg     return 0;
2356*ec02198aSmrg 
2357*ec02198aSmrg   /* Count the number of file entries.  */
2358*ec02198aSmrg   hdr->filenames_count = 0;
2359*ec02198aSmrg   p = hdr_buf->buf;
2360*ec02198aSmrg   pend = p + hdr_buf->left;
2361*ec02198aSmrg   while (p < pend && *p != '\0')
2362*ec02198aSmrg     {
2363*ec02198aSmrg       p += strnlen ((const char *) p, pend - p) + 1;
2364*ec02198aSmrg       p += leb128_len (p);
2365*ec02198aSmrg       p += leb128_len (p);
2366*ec02198aSmrg       p += leb128_len (p);
2367*ec02198aSmrg       ++hdr->filenames_count;
2368*ec02198aSmrg     }
2369*ec02198aSmrg 
2370*ec02198aSmrg   hdr->filenames = ((const char **)
2371*ec02198aSmrg 		    backtrace_alloc (state,
2372*ec02198aSmrg 				     hdr->filenames_count * sizeof (char *),
2373*ec02198aSmrg 				     hdr_buf->error_callback,
2374*ec02198aSmrg 				     hdr_buf->data));
2375*ec02198aSmrg   if (hdr->filenames == NULL)
2376*ec02198aSmrg     return 0;
2377*ec02198aSmrg   i = 0;
2378*ec02198aSmrg   while (*hdr_buf->buf != '\0')
2379*ec02198aSmrg     {
2380*ec02198aSmrg       const char *filename;
2381*ec02198aSmrg       uint64_t dir_index;
2382*ec02198aSmrg 
2383*ec02198aSmrg       if (hdr_buf->reported_underflow)
2384*ec02198aSmrg 	return 0;
2385*ec02198aSmrg 
2386*ec02198aSmrg       filename = read_string (hdr_buf);
2387*ec02198aSmrg       if (filename == NULL)
2388*ec02198aSmrg 	return 0;
2389*ec02198aSmrg       dir_index = read_uleb128 (hdr_buf);
2390*ec02198aSmrg       if (IS_ABSOLUTE_PATH (filename)
2391*ec02198aSmrg 	  || (dir_index == 0 && u->comp_dir == NULL))
2392*ec02198aSmrg 	hdr->filenames[i] = filename;
2393*ec02198aSmrg       else
2394*ec02198aSmrg 	{
2395*ec02198aSmrg 	  const char *dir;
2396*ec02198aSmrg 	  size_t dir_len;
2397*ec02198aSmrg 	  size_t filename_len;
2398*ec02198aSmrg 	  char *s;
2399*ec02198aSmrg 
2400*ec02198aSmrg 	  if (dir_index == 0)
2401*ec02198aSmrg 	    dir = u->comp_dir;
2402*ec02198aSmrg 	  else if (dir_index - 1 < hdr->dirs_count)
2403*ec02198aSmrg 	    dir = hdr->dirs[dir_index - 1];
2404*ec02198aSmrg 	  else
2405*ec02198aSmrg 	    {
2406*ec02198aSmrg 	      dwarf_buf_error (hdr_buf,
2407*ec02198aSmrg 			       ("invalid directory index in "
2408*ec02198aSmrg 				"line number program header"));
2409*ec02198aSmrg 	      return 0;
2410*ec02198aSmrg 	    }
2411*ec02198aSmrg 	  dir_len = strlen (dir);
2412*ec02198aSmrg 	  filename_len = strlen (filename);
2413*ec02198aSmrg 	  s = ((char *) backtrace_alloc (state, dir_len + filename_len + 2,
2414*ec02198aSmrg 					 hdr_buf->error_callback,
2415*ec02198aSmrg 					 hdr_buf->data));
2416*ec02198aSmrg 	  if (s == NULL)
2417*ec02198aSmrg 	    return 0;
2418*ec02198aSmrg 	  memcpy (s, dir, dir_len);
2419*ec02198aSmrg 	  /* FIXME: If we are on a DOS-based file system, and the
2420*ec02198aSmrg 	     directory or the file name use backslashes, then we
2421*ec02198aSmrg 	     should use a backslash here.  */
2422*ec02198aSmrg 	  s[dir_len] = '/';
2423*ec02198aSmrg 	  memcpy (s + dir_len + 1, filename, filename_len + 1);
2424*ec02198aSmrg 	  hdr->filenames[i] = s;
2425*ec02198aSmrg 	}
2426*ec02198aSmrg 
2427*ec02198aSmrg       /* Ignore the modification time and size.  */
2428*ec02198aSmrg       read_uleb128 (hdr_buf);
2429*ec02198aSmrg       read_uleb128 (hdr_buf);
2430*ec02198aSmrg 
2431*ec02198aSmrg       ++i;
2432*ec02198aSmrg     }
2433*ec02198aSmrg 
2434*ec02198aSmrg   return 1;
2435*ec02198aSmrg }
2436*ec02198aSmrg 
2437*ec02198aSmrg /* Read a single version 5 LNCT entry for a directory or file name in a
2438*ec02198aSmrg    line header.  Sets *STRING to the resulting name, ignoring other
2439*ec02198aSmrg    data.  Return 1 on success, 0 on failure.  */
2440*ec02198aSmrg 
2441*ec02198aSmrg static int
read_lnct(struct backtrace_state * state,struct dwarf_data * ddata,struct unit * u,struct dwarf_buf * hdr_buf,const struct line_header * hdr,size_t formats_count,const struct line_header_format * formats,const char ** string)2442*ec02198aSmrg read_lnct (struct backtrace_state *state, struct dwarf_data *ddata,
2443*ec02198aSmrg 	   struct unit *u, struct dwarf_buf *hdr_buf,
2444*ec02198aSmrg 	   const struct line_header *hdr, size_t formats_count,
2445*ec02198aSmrg 	   const struct line_header_format *formats, const char **string)
2446*ec02198aSmrg {
2447*ec02198aSmrg   size_t i;
2448*ec02198aSmrg   const char *dir;
2449*ec02198aSmrg   const char *path;
2450*ec02198aSmrg 
2451*ec02198aSmrg   dir = NULL;
2452*ec02198aSmrg   path = NULL;
2453*ec02198aSmrg   for (i = 0; i < formats_count; i++)
2454*ec02198aSmrg     {
2455*ec02198aSmrg       struct attr_val val;
2456*ec02198aSmrg 
2457*ec02198aSmrg       if (!read_attribute (formats[i].form, 0, hdr_buf, u->is_dwarf64,
2458*ec02198aSmrg 			   u->version, hdr->addrsize, &ddata->dwarf_sections,
2459*ec02198aSmrg 			   ddata->altlink, &val))
2460*ec02198aSmrg 	return 0;
2461*ec02198aSmrg       switch (formats[i].lnct)
2462*ec02198aSmrg 	{
2463*ec02198aSmrg 	case DW_LNCT_path:
2464*ec02198aSmrg 	  if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,
2465*ec02198aSmrg 			       ddata->is_bigendian, u->str_offsets_base,
2466*ec02198aSmrg 			       &val, hdr_buf->error_callback, hdr_buf->data,
2467*ec02198aSmrg 			       &path))
2468*ec02198aSmrg 	    return 0;
2469*ec02198aSmrg 	  break;
2470*ec02198aSmrg 	case DW_LNCT_directory_index:
2471*ec02198aSmrg 	  if (val.encoding == ATTR_VAL_UINT)
2472*ec02198aSmrg 	    {
2473*ec02198aSmrg 	      if (val.u.uint >= hdr->dirs_count)
2474*ec02198aSmrg 		{
2475*ec02198aSmrg 		  dwarf_buf_error (hdr_buf,
2476*ec02198aSmrg 				   ("invalid directory index in "
2477*ec02198aSmrg 				    "line number program header"));
2478*ec02198aSmrg 		  return 0;
2479*ec02198aSmrg 		}
2480*ec02198aSmrg 	      dir = hdr->dirs[val.u.uint];
2481*ec02198aSmrg 	    }
2482*ec02198aSmrg 	  break;
2483*ec02198aSmrg 	default:
2484*ec02198aSmrg 	  /* We don't care about timestamps or sizes or hashes.  */
2485*ec02198aSmrg 	  break;
2486*ec02198aSmrg 	}
2487*ec02198aSmrg     }
2488*ec02198aSmrg 
2489*ec02198aSmrg   if (path == NULL)
2490*ec02198aSmrg     {
2491*ec02198aSmrg       dwarf_buf_error (hdr_buf,
2492*ec02198aSmrg 		       "missing file name in line number program header");
2493*ec02198aSmrg       return 0;
2494*ec02198aSmrg     }
2495*ec02198aSmrg 
2496*ec02198aSmrg   if (dir == NULL)
2497*ec02198aSmrg     *string = path;
2498*ec02198aSmrg   else
2499*ec02198aSmrg     {
2500*ec02198aSmrg       size_t dir_len;
2501*ec02198aSmrg       size_t path_len;
2502*ec02198aSmrg       char *s;
2503*ec02198aSmrg 
2504*ec02198aSmrg       dir_len = strlen (dir);
2505*ec02198aSmrg       path_len = strlen (path);
2506*ec02198aSmrg       s = (char *) backtrace_alloc (state, dir_len + path_len + 2,
2507*ec02198aSmrg 				    hdr_buf->error_callback, hdr_buf->data);
2508*ec02198aSmrg       if (s == NULL)
2509*ec02198aSmrg 	return 0;
2510*ec02198aSmrg       memcpy (s, dir, dir_len);
2511*ec02198aSmrg       /* FIXME: If we are on a DOS-based file system, and the
2512*ec02198aSmrg 	 directory or the path name use backslashes, then we should
2513*ec02198aSmrg 	 use a backslash here.  */
2514*ec02198aSmrg       s[dir_len] = '/';
2515*ec02198aSmrg       memcpy (s + dir_len + 1, path, path_len + 1);
2516*ec02198aSmrg       *string = s;
2517*ec02198aSmrg     }
2518*ec02198aSmrg 
2519*ec02198aSmrg   return 1;
2520*ec02198aSmrg }
2521*ec02198aSmrg 
2522*ec02198aSmrg /* Read a set of DWARF 5 line header format entries, setting *PCOUNT
2523*ec02198aSmrg    and *PPATHS.  Return 1 on success, 0 on failure.  */
2524*ec02198aSmrg 
2525*ec02198aSmrg static int
read_line_header_format_entries(struct backtrace_state * state,struct dwarf_data * ddata,struct unit * u,struct dwarf_buf * hdr_buf,struct line_header * hdr,size_t * pcount,const char *** ppaths)2526*ec02198aSmrg read_line_header_format_entries (struct backtrace_state *state,
2527*ec02198aSmrg 				 struct dwarf_data *ddata,
2528*ec02198aSmrg 				 struct unit *u,
2529*ec02198aSmrg 				 struct dwarf_buf *hdr_buf,
2530*ec02198aSmrg 				 struct line_header *hdr,
2531*ec02198aSmrg 				 size_t *pcount,
2532*ec02198aSmrg 				 const char ***ppaths)
2533*ec02198aSmrg {
2534*ec02198aSmrg   size_t formats_count;
2535*ec02198aSmrg   struct line_header_format *formats;
2536*ec02198aSmrg   size_t paths_count;
2537*ec02198aSmrg   const char **paths;
2538*ec02198aSmrg   size_t i;
2539*ec02198aSmrg   int ret;
2540*ec02198aSmrg 
2541*ec02198aSmrg   formats_count = read_byte (hdr_buf);
2542*ec02198aSmrg   if (formats_count == 0)
2543*ec02198aSmrg     formats = NULL;
2544*ec02198aSmrg   else
2545*ec02198aSmrg     {
2546*ec02198aSmrg       formats = ((struct line_header_format *)
2547*ec02198aSmrg 		 backtrace_alloc (state,
2548*ec02198aSmrg 				  (formats_count
2549*ec02198aSmrg 				   * sizeof (struct line_header_format)),
2550*ec02198aSmrg 				  hdr_buf->error_callback,
2551*ec02198aSmrg 				  hdr_buf->data));
2552*ec02198aSmrg       if (formats == NULL)
2553*ec02198aSmrg 	return 0;
2554*ec02198aSmrg 
2555*ec02198aSmrg       for (i = 0; i < formats_count; i++)
2556*ec02198aSmrg 	{
2557*ec02198aSmrg 	  formats[i].lnct = (int) read_uleb128(hdr_buf);
2558*ec02198aSmrg 	  formats[i].form = (enum dwarf_form) read_uleb128 (hdr_buf);
2559*ec02198aSmrg 	}
2560*ec02198aSmrg     }
2561*ec02198aSmrg 
2562*ec02198aSmrg   paths_count = read_uleb128 (hdr_buf);
2563*ec02198aSmrg   if (paths_count == 0)
2564*ec02198aSmrg     {
2565*ec02198aSmrg       *pcount = 0;
2566*ec02198aSmrg       *ppaths = NULL;
2567*ec02198aSmrg       ret = 1;
2568*ec02198aSmrg       goto exit;
2569*ec02198aSmrg     }
2570*ec02198aSmrg 
2571*ec02198aSmrg   paths = ((const char **)
2572*ec02198aSmrg 	   backtrace_alloc (state, paths_count * sizeof (const char *),
2573*ec02198aSmrg 			    hdr_buf->error_callback, hdr_buf->data));
2574*ec02198aSmrg   if (paths == NULL)
2575*ec02198aSmrg     {
2576*ec02198aSmrg       ret = 0;
2577*ec02198aSmrg       goto exit;
2578*ec02198aSmrg     }
2579*ec02198aSmrg   for (i = 0; i < paths_count; i++)
2580*ec02198aSmrg     {
2581*ec02198aSmrg       if (!read_lnct (state, ddata, u, hdr_buf, hdr, formats_count,
2582*ec02198aSmrg 		      formats, &paths[i]))
2583*ec02198aSmrg 	{
2584*ec02198aSmrg 	  backtrace_free (state, paths,
2585*ec02198aSmrg 			  paths_count * sizeof (const char *),
2586*ec02198aSmrg 			  hdr_buf->error_callback, hdr_buf->data);
2587*ec02198aSmrg 	  ret = 0;
2588*ec02198aSmrg 	  goto exit;
2589*ec02198aSmrg 	}
2590*ec02198aSmrg     }
2591*ec02198aSmrg 
2592*ec02198aSmrg   *pcount = paths_count;
2593*ec02198aSmrg   *ppaths = paths;
2594*ec02198aSmrg 
2595*ec02198aSmrg   ret = 1;
2596*ec02198aSmrg 
2597*ec02198aSmrg  exit:
2598*ec02198aSmrg   if (formats != NULL)
2599*ec02198aSmrg     backtrace_free (state, formats,
2600*ec02198aSmrg 		    formats_count * sizeof (struct line_header_format),
2601*ec02198aSmrg 		    hdr_buf->error_callback, hdr_buf->data);
2602*ec02198aSmrg 
2603*ec02198aSmrg   return  ret;
2604*ec02198aSmrg }
2605*ec02198aSmrg 
2606*ec02198aSmrg /* Read the line header.  Return 1 on success, 0 on failure.  */
2607*ec02198aSmrg 
2608*ec02198aSmrg static int
read_line_header(struct backtrace_state * state,struct dwarf_data * ddata,struct unit * u,int is_dwarf64,struct dwarf_buf * line_buf,struct line_header * hdr)2609*ec02198aSmrg read_line_header (struct backtrace_state *state, struct dwarf_data *ddata,
2610*ec02198aSmrg 		  struct unit *u, int is_dwarf64, struct dwarf_buf *line_buf,
2611*ec02198aSmrg 		  struct line_header *hdr)
2612*ec02198aSmrg {
2613*ec02198aSmrg   uint64_t hdrlen;
2614*ec02198aSmrg   struct dwarf_buf hdr_buf;
2615*ec02198aSmrg 
261663d1a8abSmrg   hdr->version = read_uint16 (line_buf);
2617*ec02198aSmrg   if (hdr->version < 2 || hdr->version > 5)
261863d1a8abSmrg     {
261963d1a8abSmrg       dwarf_buf_error (line_buf, "unsupported line number version");
262063d1a8abSmrg       return 0;
262163d1a8abSmrg     }
262263d1a8abSmrg 
2623*ec02198aSmrg   if (hdr->version < 5)
2624*ec02198aSmrg     hdr->addrsize = u->addrsize;
2625*ec02198aSmrg   else
2626*ec02198aSmrg     {
2627*ec02198aSmrg       hdr->addrsize = read_byte (line_buf);
2628*ec02198aSmrg       /* We could support a non-zero segment_selector_size but I doubt
2629*ec02198aSmrg 	 we'll ever see it.  */
2630*ec02198aSmrg       if (read_byte (line_buf) != 0)
2631*ec02198aSmrg 	{
2632*ec02198aSmrg 	  dwarf_buf_error (line_buf,
2633*ec02198aSmrg 			   "non-zero segment_selector_size not supported");
2634*ec02198aSmrg 	  return 0;
2635*ec02198aSmrg 	}
2636*ec02198aSmrg     }
2637*ec02198aSmrg 
263863d1a8abSmrg   hdrlen = read_offset (line_buf, is_dwarf64);
263963d1a8abSmrg 
264063d1a8abSmrg   hdr_buf = *line_buf;
264163d1a8abSmrg   hdr_buf.left = hdrlen;
264263d1a8abSmrg 
264363d1a8abSmrg   if (!advance (line_buf, hdrlen))
264463d1a8abSmrg     return 0;
264563d1a8abSmrg 
264663d1a8abSmrg   hdr->min_insn_len = read_byte (&hdr_buf);
264763d1a8abSmrg   if (hdr->version < 4)
264863d1a8abSmrg     hdr->max_ops_per_insn = 1;
264963d1a8abSmrg   else
265063d1a8abSmrg     hdr->max_ops_per_insn = read_byte (&hdr_buf);
265163d1a8abSmrg 
265263d1a8abSmrg   /* We don't care about default_is_stmt.  */
265363d1a8abSmrg   read_byte (&hdr_buf);
265463d1a8abSmrg 
265563d1a8abSmrg   hdr->line_base = read_sbyte (&hdr_buf);
265663d1a8abSmrg   hdr->line_range = read_byte (&hdr_buf);
265763d1a8abSmrg 
265863d1a8abSmrg   hdr->opcode_base = read_byte (&hdr_buf);
265963d1a8abSmrg   hdr->opcode_lengths = hdr_buf.buf;
266063d1a8abSmrg   if (!advance (&hdr_buf, hdr->opcode_base - 1))
266163d1a8abSmrg     return 0;
266263d1a8abSmrg 
2663*ec02198aSmrg   if (hdr->version < 5)
266463d1a8abSmrg     {
2665*ec02198aSmrg       if (!read_v2_paths (state, u, &hdr_buf, hdr))
266663d1a8abSmrg 	return 0;
2667c7a68eb7Smrg     }
266863d1a8abSmrg   else
266963d1a8abSmrg     {
2670*ec02198aSmrg       if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr,
2671*ec02198aSmrg 					    &hdr->dirs_count,
2672*ec02198aSmrg 					    &hdr->dirs))
267363d1a8abSmrg 	return 0;
2674*ec02198aSmrg       if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr,
2675*ec02198aSmrg 					    &hdr->filenames_count,
2676*ec02198aSmrg 					    &hdr->filenames))
267763d1a8abSmrg 	return 0;
267863d1a8abSmrg     }
267963d1a8abSmrg 
268063d1a8abSmrg   if (hdr_buf.reported_underflow)
268163d1a8abSmrg     return 0;
268263d1a8abSmrg 
268363d1a8abSmrg   return 1;
268463d1a8abSmrg }
268563d1a8abSmrg 
268663d1a8abSmrg /* Read the line program, adding line mappings to VEC.  Return 1 on
268763d1a8abSmrg    success, 0 on failure.  */
268863d1a8abSmrg 
268963d1a8abSmrg static int
read_line_program(struct backtrace_state * state,struct dwarf_data * ddata,struct unit * u,const struct line_header * hdr,struct dwarf_buf * line_buf,struct line_vector * vec)269063d1a8abSmrg read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
269163d1a8abSmrg 		   struct unit *u, const struct line_header *hdr,
269263d1a8abSmrg 		   struct dwarf_buf *line_buf, struct line_vector *vec)
269363d1a8abSmrg {
269463d1a8abSmrg   uint64_t address;
269563d1a8abSmrg   unsigned int op_index;
269663d1a8abSmrg   const char *reset_filename;
269763d1a8abSmrg   const char *filename;
269863d1a8abSmrg   int lineno;
269963d1a8abSmrg 
270063d1a8abSmrg   address = 0;
270163d1a8abSmrg   op_index = 0;
270263d1a8abSmrg   if (hdr->filenames_count > 0)
270363d1a8abSmrg     reset_filename = hdr->filenames[0];
270463d1a8abSmrg   else
270563d1a8abSmrg     reset_filename = "";
270663d1a8abSmrg   filename = reset_filename;
270763d1a8abSmrg   lineno = 1;
270863d1a8abSmrg   while (line_buf->left > 0)
270963d1a8abSmrg     {
271063d1a8abSmrg       unsigned int op;
271163d1a8abSmrg 
271263d1a8abSmrg       op = read_byte (line_buf);
271363d1a8abSmrg       if (op >= hdr->opcode_base)
271463d1a8abSmrg 	{
271563d1a8abSmrg 	  unsigned int advance;
271663d1a8abSmrg 
271763d1a8abSmrg 	  /* Special opcode.  */
271863d1a8abSmrg 	  op -= hdr->opcode_base;
271963d1a8abSmrg 	  advance = op / hdr->line_range;
272063d1a8abSmrg 	  address += (hdr->min_insn_len * (op_index + advance)
272163d1a8abSmrg 		      / hdr->max_ops_per_insn);
272263d1a8abSmrg 	  op_index = (op_index + advance) % hdr->max_ops_per_insn;
272363d1a8abSmrg 	  lineno += hdr->line_base + (int) (op % hdr->line_range);
272463d1a8abSmrg 	  add_line (state, ddata, address, filename, lineno,
272563d1a8abSmrg 		    line_buf->error_callback, line_buf->data, vec);
272663d1a8abSmrg 	}
272763d1a8abSmrg       else if (op == DW_LNS_extended_op)
272863d1a8abSmrg 	{
272963d1a8abSmrg 	  uint64_t len;
273063d1a8abSmrg 
273163d1a8abSmrg 	  len = read_uleb128 (line_buf);
273263d1a8abSmrg 	  op = read_byte (line_buf);
273363d1a8abSmrg 	  switch (op)
273463d1a8abSmrg 	    {
273563d1a8abSmrg 	    case DW_LNE_end_sequence:
273663d1a8abSmrg 	      /* FIXME: Should we mark the high PC here?  It seems
273763d1a8abSmrg 		 that we already have that information from the
273863d1a8abSmrg 		 compilation unit.  */
273963d1a8abSmrg 	      address = 0;
274063d1a8abSmrg 	      op_index = 0;
274163d1a8abSmrg 	      filename = reset_filename;
274263d1a8abSmrg 	      lineno = 1;
274363d1a8abSmrg 	      break;
274463d1a8abSmrg 	    case DW_LNE_set_address:
2745*ec02198aSmrg 	      address = read_address (line_buf, hdr->addrsize);
274663d1a8abSmrg 	      break;
274763d1a8abSmrg 	    case DW_LNE_define_file:
274863d1a8abSmrg 	      {
274963d1a8abSmrg 		const char *f;
275063d1a8abSmrg 		unsigned int dir_index;
275163d1a8abSmrg 
27520fc04c29Smrg 		f = read_string (line_buf);
27530fc04c29Smrg 		if (f == NULL)
275463d1a8abSmrg 		  return 0;
275563d1a8abSmrg 		dir_index = read_uleb128 (line_buf);
275663d1a8abSmrg 		/* Ignore that time and length.  */
275763d1a8abSmrg 		read_uleb128 (line_buf);
275863d1a8abSmrg 		read_uleb128 (line_buf);
275963d1a8abSmrg 		if (IS_ABSOLUTE_PATH (f))
276063d1a8abSmrg 		  filename = f;
276163d1a8abSmrg 		else
276263d1a8abSmrg 		  {
276363d1a8abSmrg 		    const char *dir;
276463d1a8abSmrg 		    size_t dir_len;
276563d1a8abSmrg 		    size_t f_len;
276663d1a8abSmrg 		    char *p;
276763d1a8abSmrg 
2768*ec02198aSmrg 		    if (dir_index == 0 && hdr->version < 5)
276963d1a8abSmrg 		      dir = u->comp_dir;
277063d1a8abSmrg 		    else if (dir_index - 1 < hdr->dirs_count)
277163d1a8abSmrg 		      dir = hdr->dirs[dir_index - 1];
277263d1a8abSmrg 		    else
277363d1a8abSmrg 		      {
277463d1a8abSmrg 			dwarf_buf_error (line_buf,
277563d1a8abSmrg 					 ("invalid directory index "
277663d1a8abSmrg 					  "in line number program"));
277763d1a8abSmrg 			return 0;
277863d1a8abSmrg 		      }
277963d1a8abSmrg 		    dir_len = strlen (dir);
278063d1a8abSmrg 		    f_len = strlen (f);
278163d1a8abSmrg 		    p = ((char *)
278263d1a8abSmrg 			 backtrace_alloc (state, dir_len + f_len + 2,
278363d1a8abSmrg 					  line_buf->error_callback,
278463d1a8abSmrg 					  line_buf->data));
278563d1a8abSmrg 		    if (p == NULL)
278663d1a8abSmrg 		      return 0;
278763d1a8abSmrg 		    memcpy (p, dir, dir_len);
278863d1a8abSmrg 		    /* FIXME: If we are on a DOS-based file system,
278963d1a8abSmrg 		       and the directory or the file name use
279063d1a8abSmrg 		       backslashes, then we should use a backslash
279163d1a8abSmrg 		       here.  */
279263d1a8abSmrg 		    p[dir_len] = '/';
279363d1a8abSmrg 		    memcpy (p + dir_len + 1, f, f_len + 1);
279463d1a8abSmrg 		    filename = p;
279563d1a8abSmrg 		  }
279663d1a8abSmrg 	      }
279763d1a8abSmrg 	      break;
279863d1a8abSmrg 	    case DW_LNE_set_discriminator:
279963d1a8abSmrg 	      /* We don't care about discriminators.  */
280063d1a8abSmrg 	      read_uleb128 (line_buf);
280163d1a8abSmrg 	      break;
280263d1a8abSmrg 	    default:
280363d1a8abSmrg 	      if (!advance (line_buf, len - 1))
280463d1a8abSmrg 		return 0;
280563d1a8abSmrg 	      break;
280663d1a8abSmrg 	    }
280763d1a8abSmrg 	}
280863d1a8abSmrg       else
280963d1a8abSmrg 	{
281063d1a8abSmrg 	  switch (op)
281163d1a8abSmrg 	    {
281263d1a8abSmrg 	    case DW_LNS_copy:
281363d1a8abSmrg 	      add_line (state, ddata, address, filename, lineno,
281463d1a8abSmrg 			line_buf->error_callback, line_buf->data, vec);
281563d1a8abSmrg 	      break;
281663d1a8abSmrg 	    case DW_LNS_advance_pc:
281763d1a8abSmrg 	      {
281863d1a8abSmrg 		uint64_t advance;
281963d1a8abSmrg 
282063d1a8abSmrg 		advance = read_uleb128 (line_buf);
282163d1a8abSmrg 		address += (hdr->min_insn_len * (op_index + advance)
282263d1a8abSmrg 			    / hdr->max_ops_per_insn);
282363d1a8abSmrg 		op_index = (op_index + advance) % hdr->max_ops_per_insn;
282463d1a8abSmrg 	      }
282563d1a8abSmrg 	      break;
282663d1a8abSmrg 	    case DW_LNS_advance_line:
282763d1a8abSmrg 	      lineno += (int) read_sleb128 (line_buf);
282863d1a8abSmrg 	      break;
282963d1a8abSmrg 	    case DW_LNS_set_file:
283063d1a8abSmrg 	      {
283163d1a8abSmrg 		uint64_t fileno;
283263d1a8abSmrg 
283363d1a8abSmrg 		fileno = read_uleb128 (line_buf);
283463d1a8abSmrg 		if (fileno == 0)
283563d1a8abSmrg 		  filename = "";
283663d1a8abSmrg 		else
283763d1a8abSmrg 		  {
283863d1a8abSmrg 		    if (fileno - 1 >= hdr->filenames_count)
283963d1a8abSmrg 		      {
284063d1a8abSmrg 			dwarf_buf_error (line_buf,
284163d1a8abSmrg 					 ("invalid file number in "
284263d1a8abSmrg 					  "line number program"));
284363d1a8abSmrg 			return 0;
284463d1a8abSmrg 		      }
284563d1a8abSmrg 		    filename = hdr->filenames[fileno - 1];
284663d1a8abSmrg 		  }
284763d1a8abSmrg 	      }
284863d1a8abSmrg 	      break;
284963d1a8abSmrg 	    case DW_LNS_set_column:
285063d1a8abSmrg 	      read_uleb128 (line_buf);
285163d1a8abSmrg 	      break;
285263d1a8abSmrg 	    case DW_LNS_negate_stmt:
285363d1a8abSmrg 	      break;
285463d1a8abSmrg 	    case DW_LNS_set_basic_block:
285563d1a8abSmrg 	      break;
285663d1a8abSmrg 	    case DW_LNS_const_add_pc:
285763d1a8abSmrg 	      {
285863d1a8abSmrg 		unsigned int advance;
285963d1a8abSmrg 
286063d1a8abSmrg 		op = 255 - hdr->opcode_base;
286163d1a8abSmrg 		advance = op / hdr->line_range;
286263d1a8abSmrg 		address += (hdr->min_insn_len * (op_index + advance)
286363d1a8abSmrg 			    / hdr->max_ops_per_insn);
286463d1a8abSmrg 		op_index = (op_index + advance) % hdr->max_ops_per_insn;
286563d1a8abSmrg 	      }
286663d1a8abSmrg 	      break;
286763d1a8abSmrg 	    case DW_LNS_fixed_advance_pc:
286863d1a8abSmrg 	      address += read_uint16 (line_buf);
286963d1a8abSmrg 	      op_index = 0;
287063d1a8abSmrg 	      break;
287163d1a8abSmrg 	    case DW_LNS_set_prologue_end:
287263d1a8abSmrg 	      break;
287363d1a8abSmrg 	    case DW_LNS_set_epilogue_begin:
287463d1a8abSmrg 	      break;
287563d1a8abSmrg 	    case DW_LNS_set_isa:
287663d1a8abSmrg 	      read_uleb128 (line_buf);
287763d1a8abSmrg 	      break;
287863d1a8abSmrg 	    default:
287963d1a8abSmrg 	      {
288063d1a8abSmrg 		unsigned int i;
288163d1a8abSmrg 
288263d1a8abSmrg 		for (i = hdr->opcode_lengths[op - 1]; i > 0; --i)
288363d1a8abSmrg 		  read_uleb128 (line_buf);
288463d1a8abSmrg 	      }
288563d1a8abSmrg 	      break;
288663d1a8abSmrg 	    }
288763d1a8abSmrg 	}
288863d1a8abSmrg     }
288963d1a8abSmrg 
289063d1a8abSmrg   return 1;
289163d1a8abSmrg }
289263d1a8abSmrg 
289363d1a8abSmrg /* Read the line number information for a compilation unit.  Returns 1
289463d1a8abSmrg    on success, 0 on failure.  */
289563d1a8abSmrg 
289663d1a8abSmrg static int
read_line_info(struct backtrace_state * state,struct dwarf_data * ddata,backtrace_error_callback error_callback,void * data,struct unit * u,struct line_header * hdr,struct line ** lines,size_t * lines_count)289763d1a8abSmrg read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
289863d1a8abSmrg 		backtrace_error_callback error_callback, void *data,
289963d1a8abSmrg 		struct unit *u, struct line_header *hdr, struct line **lines,
290063d1a8abSmrg 		size_t *lines_count)
290163d1a8abSmrg {
290263d1a8abSmrg   struct line_vector vec;
290363d1a8abSmrg   struct dwarf_buf line_buf;
290463d1a8abSmrg   uint64_t len;
290563d1a8abSmrg   int is_dwarf64;
290663d1a8abSmrg   struct line *ln;
290763d1a8abSmrg 
290863d1a8abSmrg   memset (&vec.vec, 0, sizeof vec.vec);
290963d1a8abSmrg   vec.count = 0;
291063d1a8abSmrg 
291163d1a8abSmrg   memset (hdr, 0, sizeof *hdr);
291263d1a8abSmrg 
291363d1a8abSmrg   if (u->lineoff != (off_t) (size_t) u->lineoff
2914*ec02198aSmrg       || (size_t) u->lineoff >= ddata->dwarf_sections.size[DEBUG_LINE])
291563d1a8abSmrg     {
291663d1a8abSmrg       error_callback (data, "unit line offset out of range", 0);
291763d1a8abSmrg       goto fail;
291863d1a8abSmrg     }
291963d1a8abSmrg 
292063d1a8abSmrg   line_buf.name = ".debug_line";
2921*ec02198aSmrg   line_buf.start = ddata->dwarf_sections.data[DEBUG_LINE];
2922*ec02198aSmrg   line_buf.buf = ddata->dwarf_sections.data[DEBUG_LINE] + u->lineoff;
2923*ec02198aSmrg   line_buf.left = ddata->dwarf_sections.size[DEBUG_LINE] - u->lineoff;
292463d1a8abSmrg   line_buf.is_bigendian = ddata->is_bigendian;
292563d1a8abSmrg   line_buf.error_callback = error_callback;
292663d1a8abSmrg   line_buf.data = data;
292763d1a8abSmrg   line_buf.reported_underflow = 0;
292863d1a8abSmrg 
29290fc04c29Smrg   len = read_initial_length (&line_buf, &is_dwarf64);
293063d1a8abSmrg   line_buf.left = len;
293163d1a8abSmrg 
2932*ec02198aSmrg   if (!read_line_header (state, ddata, u, is_dwarf64, &line_buf, hdr))
293363d1a8abSmrg     goto fail;
293463d1a8abSmrg 
293563d1a8abSmrg   if (!read_line_program (state, ddata, u, hdr, &line_buf, &vec))
293663d1a8abSmrg     goto fail;
293763d1a8abSmrg 
293863d1a8abSmrg   if (line_buf.reported_underflow)
293963d1a8abSmrg     goto fail;
294063d1a8abSmrg 
294163d1a8abSmrg   if (vec.count == 0)
294263d1a8abSmrg     {
294363d1a8abSmrg       /* This is not a failure in the sense of a generating an error,
294463d1a8abSmrg 	 but it is a failure in that sense that we have no useful
294563d1a8abSmrg 	 information.  */
294663d1a8abSmrg       goto fail;
294763d1a8abSmrg     }
294863d1a8abSmrg 
294963d1a8abSmrg   /* Allocate one extra entry at the end.  */
295063d1a8abSmrg   ln = ((struct line *)
295163d1a8abSmrg 	backtrace_vector_grow (state, sizeof (struct line), error_callback,
295263d1a8abSmrg 			       data, &vec.vec));
295363d1a8abSmrg   if (ln == NULL)
295463d1a8abSmrg     goto fail;
295563d1a8abSmrg   ln->pc = (uintptr_t) -1;
295663d1a8abSmrg   ln->filename = NULL;
295763d1a8abSmrg   ln->lineno = 0;
295863d1a8abSmrg   ln->idx = 0;
295963d1a8abSmrg 
296063d1a8abSmrg   if (!backtrace_vector_release (state, &vec.vec, error_callback, data))
296163d1a8abSmrg     goto fail;
296263d1a8abSmrg 
296363d1a8abSmrg   ln = (struct line *) vec.vec.base;
296463d1a8abSmrg   backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);
296563d1a8abSmrg 
296663d1a8abSmrg   *lines = ln;
296763d1a8abSmrg   *lines_count = vec.count;
296863d1a8abSmrg 
296963d1a8abSmrg   return 1;
297063d1a8abSmrg 
297163d1a8abSmrg  fail:
29720fc04c29Smrg   backtrace_vector_free (state, &vec.vec, error_callback, data);
297363d1a8abSmrg   free_line_header (state, hdr, error_callback, data);
297463d1a8abSmrg   *lines = (struct line *) (uintptr_t) -1;
297563d1a8abSmrg   *lines_count = 0;
297663d1a8abSmrg   return 0;
297763d1a8abSmrg }
297863d1a8abSmrg 
29790fc04c29Smrg static const char *read_referenced_name (struct dwarf_data *, struct unit *,
29800fc04c29Smrg 					 uint64_t, backtrace_error_callback,
29810fc04c29Smrg 					 void *);
29820fc04c29Smrg 
29830fc04c29Smrg /* Read the name of a function from a DIE referenced by ATTR with VAL.  */
29840fc04c29Smrg 
29850fc04c29Smrg static const char *
read_referenced_name_from_attr(struct dwarf_data * ddata,struct unit * u,struct attr * attr,struct attr_val * val,backtrace_error_callback error_callback,void * data)29860fc04c29Smrg read_referenced_name_from_attr (struct dwarf_data *ddata, struct unit *u,
29870fc04c29Smrg 				struct attr *attr, struct attr_val *val,
29880fc04c29Smrg 				backtrace_error_callback error_callback,
29890fc04c29Smrg 				void *data)
29900fc04c29Smrg {
29910fc04c29Smrg   switch (attr->name)
29920fc04c29Smrg     {
29930fc04c29Smrg     case DW_AT_abstract_origin:
29940fc04c29Smrg     case DW_AT_specification:
29950fc04c29Smrg       break;
29960fc04c29Smrg     default:
29970fc04c29Smrg       return NULL;
29980fc04c29Smrg     }
29990fc04c29Smrg 
30000fc04c29Smrg   if (attr->form == DW_FORM_ref_sig8)
30010fc04c29Smrg     return NULL;
30020fc04c29Smrg 
30030fc04c29Smrg   if (val->encoding == ATTR_VAL_REF_INFO)
30040fc04c29Smrg     {
30050fc04c29Smrg       struct unit *unit
30060fc04c29Smrg 	= find_unit (ddata->units, ddata->units_count,
30070fc04c29Smrg 		     val->u.uint);
30080fc04c29Smrg       if (unit == NULL)
30090fc04c29Smrg 	return NULL;
30100fc04c29Smrg 
30110fc04c29Smrg       uint64_t offset = val->u.uint - unit->low_offset;
30120fc04c29Smrg       return read_referenced_name (ddata, unit, offset, error_callback, data);
30130fc04c29Smrg     }
30140fc04c29Smrg 
30150fc04c29Smrg   if (val->encoding == ATTR_VAL_UINT
30160fc04c29Smrg       || val->encoding == ATTR_VAL_REF_UNIT)
30170fc04c29Smrg     return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
30180fc04c29Smrg 
30190fc04c29Smrg   if (val->encoding == ATTR_VAL_REF_ALT_INFO)
30200fc04c29Smrg     {
30210fc04c29Smrg       struct unit *alt_unit
30220fc04c29Smrg 	= find_unit (ddata->altlink->units, ddata->altlink->units_count,
30230fc04c29Smrg 		     val->u.uint);
30240fc04c29Smrg       if (alt_unit == NULL)
30250fc04c29Smrg 	return NULL;
30260fc04c29Smrg 
30270fc04c29Smrg       uint64_t offset = val->u.uint - alt_unit->low_offset;
30280fc04c29Smrg       return read_referenced_name (ddata->altlink, alt_unit, offset,
30290fc04c29Smrg 				   error_callback, data);
30300fc04c29Smrg     }
30310fc04c29Smrg 
30320fc04c29Smrg   return NULL;
30330fc04c29Smrg }
30340fc04c29Smrg 
303563d1a8abSmrg /* Read the name of a function from a DIE referenced by a
303663d1a8abSmrg    DW_AT_abstract_origin or DW_AT_specification tag.  OFFSET is within
303763d1a8abSmrg    the same compilation unit.  */
303863d1a8abSmrg 
303963d1a8abSmrg static const char *
read_referenced_name(struct dwarf_data * ddata,struct unit * u,uint64_t offset,backtrace_error_callback error_callback,void * data)304063d1a8abSmrg read_referenced_name (struct dwarf_data *ddata, struct unit *u,
304163d1a8abSmrg 		      uint64_t offset, backtrace_error_callback error_callback,
304263d1a8abSmrg 		      void *data)
304363d1a8abSmrg {
304463d1a8abSmrg   struct dwarf_buf unit_buf;
304563d1a8abSmrg   uint64_t code;
304663d1a8abSmrg   const struct abbrev *abbrev;
304763d1a8abSmrg   const char *ret;
304863d1a8abSmrg   size_t i;
304963d1a8abSmrg 
305063d1a8abSmrg   /* OFFSET is from the start of the data for this compilation unit.
305163d1a8abSmrg      U->unit_data is the data, but it starts U->unit_data_offset bytes
305263d1a8abSmrg      from the beginning.  */
305363d1a8abSmrg 
305463d1a8abSmrg   if (offset < u->unit_data_offset
305563d1a8abSmrg       || offset - u->unit_data_offset >= u->unit_data_len)
305663d1a8abSmrg     {
305763d1a8abSmrg       error_callback (data,
305863d1a8abSmrg 		      "abstract origin or specification out of range",
305963d1a8abSmrg 		      0);
306063d1a8abSmrg       return NULL;
306163d1a8abSmrg     }
306263d1a8abSmrg 
306363d1a8abSmrg   offset -= u->unit_data_offset;
306463d1a8abSmrg 
306563d1a8abSmrg   unit_buf.name = ".debug_info";
3066*ec02198aSmrg   unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];
306763d1a8abSmrg   unit_buf.buf = u->unit_data + offset;
306863d1a8abSmrg   unit_buf.left = u->unit_data_len - offset;
306963d1a8abSmrg   unit_buf.is_bigendian = ddata->is_bigendian;
307063d1a8abSmrg   unit_buf.error_callback = error_callback;
307163d1a8abSmrg   unit_buf.data = data;
307263d1a8abSmrg   unit_buf.reported_underflow = 0;
307363d1a8abSmrg 
307463d1a8abSmrg   code = read_uleb128 (&unit_buf);
307563d1a8abSmrg   if (code == 0)
307663d1a8abSmrg     {
307763d1a8abSmrg       dwarf_buf_error (&unit_buf, "invalid abstract origin or specification");
307863d1a8abSmrg       return NULL;
307963d1a8abSmrg     }
308063d1a8abSmrg 
308163d1a8abSmrg   abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
308263d1a8abSmrg   if (abbrev == NULL)
308363d1a8abSmrg     return NULL;
308463d1a8abSmrg 
308563d1a8abSmrg   ret = NULL;
308663d1a8abSmrg   for (i = 0; i < abbrev->num_attrs; ++i)
308763d1a8abSmrg     {
308863d1a8abSmrg       struct attr_val val;
308963d1a8abSmrg 
3090*ec02198aSmrg       if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,
3091*ec02198aSmrg 			   &unit_buf, u->is_dwarf64, u->version, u->addrsize,
3092*ec02198aSmrg 			   &ddata->dwarf_sections, ddata->altlink, &val))
309363d1a8abSmrg 	return NULL;
309463d1a8abSmrg 
309563d1a8abSmrg       switch (abbrev->attrs[i].name)
309663d1a8abSmrg 	{
309763d1a8abSmrg 	case DW_AT_name:
30980fc04c29Smrg 	  /* Third name preference: don't override.  A name we found in some
30990fc04c29Smrg 	     other way, will normally be more useful -- e.g., this name is
31000fc04c29Smrg 	     normally not mangled.  */
31010fc04c29Smrg 	  if (ret != NULL)
31020fc04c29Smrg 	    break;
3103*ec02198aSmrg 	  if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,
3104*ec02198aSmrg 			       ddata->is_bigendian, u->str_offsets_base,
3105*ec02198aSmrg 			       &val, error_callback, data, &ret))
3106*ec02198aSmrg 	    return NULL;
310763d1a8abSmrg 	  break;
310863d1a8abSmrg 
310963d1a8abSmrg 	case DW_AT_linkage_name:
311063d1a8abSmrg 	case DW_AT_MIPS_linkage_name:
31110fc04c29Smrg 	  /* First name preference: override all.  */
3112*ec02198aSmrg 	  {
3113*ec02198aSmrg 	    const char *s;
3114*ec02198aSmrg 
3115*ec02198aSmrg 	    s = NULL;
3116*ec02198aSmrg 	    if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,
3117*ec02198aSmrg 				 ddata->is_bigendian, u->str_offsets_base,
3118*ec02198aSmrg 				 &val, error_callback, data, &s))
3119*ec02198aSmrg 	      return NULL;
3120*ec02198aSmrg 	    if (s != NULL)
3121*ec02198aSmrg 	      return s;
3122*ec02198aSmrg 	  }
312363d1a8abSmrg 	  break;
312463d1a8abSmrg 
312563d1a8abSmrg 	case DW_AT_specification:
31260fc04c29Smrg 	  /* Second name preference: override DW_AT_name, don't override
31270fc04c29Smrg 	     DW_AT_linkage_name.  */
312863d1a8abSmrg 	  {
312963d1a8abSmrg 	    const char *name;
313063d1a8abSmrg 
31310fc04c29Smrg 	    name = read_referenced_name_from_attr (ddata, u, &abbrev->attrs[i],
31320fc04c29Smrg 						   &val, error_callback, data);
313363d1a8abSmrg 	    if (name != NULL)
313463d1a8abSmrg 	      ret = name;
313563d1a8abSmrg 	  }
313663d1a8abSmrg 	  break;
313763d1a8abSmrg 
313863d1a8abSmrg 	default:
313963d1a8abSmrg 	  break;
314063d1a8abSmrg 	}
314163d1a8abSmrg     }
314263d1a8abSmrg 
314363d1a8abSmrg   return ret;
314463d1a8abSmrg }
314563d1a8abSmrg 
3146*ec02198aSmrg /* Add a range to a unit that maps to a function.  This is called via
3147*ec02198aSmrg    add_ranges.  Returns 1 on success, 0 on error.  */
314863d1a8abSmrg 
314963d1a8abSmrg static int
add_function_range(struct backtrace_state * state,void * rdata,uint64_t lowpc,uint64_t highpc,backtrace_error_callback error_callback,void * data,void * pvec)3150*ec02198aSmrg add_function_range (struct backtrace_state *state, void *rdata,
3151*ec02198aSmrg 		    uint64_t lowpc, uint64_t highpc,
3152*ec02198aSmrg 		    backtrace_error_callback error_callback, void *data,
3153*ec02198aSmrg 		    void *pvec)
315463d1a8abSmrg {
3155*ec02198aSmrg   struct function *function = (struct function *) rdata;
3156*ec02198aSmrg   struct function_vector *vec = (struct function_vector *) pvec;
315763d1a8abSmrg   struct function_addrs *p;
315863d1a8abSmrg 
315963d1a8abSmrg   if (vec->count > 0)
316063d1a8abSmrg     {
3161*ec02198aSmrg       p = (struct function_addrs *) vec->vec.base + (vec->count - 1);
316263d1a8abSmrg       if ((lowpc == p->high || lowpc == p->high + 1)
316363d1a8abSmrg 	  && function == p->function)
316463d1a8abSmrg 	{
316563d1a8abSmrg 	  if (highpc > p->high)
316663d1a8abSmrg 	    p->high = highpc;
316763d1a8abSmrg 	  return 1;
316863d1a8abSmrg 	}
316963d1a8abSmrg     }
317063d1a8abSmrg 
317163d1a8abSmrg   p = ((struct function_addrs *)
317263d1a8abSmrg        backtrace_vector_grow (state, sizeof (struct function_addrs),
317363d1a8abSmrg 			      error_callback, data, &vec->vec));
317463d1a8abSmrg   if (p == NULL)
317563d1a8abSmrg     return 0;
317663d1a8abSmrg 
317763d1a8abSmrg   p->low = lowpc;
317863d1a8abSmrg   p->high = highpc;
317963d1a8abSmrg   p->function = function;
3180*ec02198aSmrg 
318163d1a8abSmrg   ++vec->count;
318263d1a8abSmrg 
318363d1a8abSmrg   return 1;
318463d1a8abSmrg }
318563d1a8abSmrg 
318663d1a8abSmrg /* Read one entry plus all its children.  Add function addresses to
318763d1a8abSmrg    VEC.  Returns 1 on success, 0 on error.  */
318863d1a8abSmrg 
318963d1a8abSmrg static int
read_function_entry(struct backtrace_state * state,struct dwarf_data * ddata,struct unit * u,uint64_t base,struct dwarf_buf * unit_buf,const struct line_header * lhdr,backtrace_error_callback error_callback,void * data,struct function_vector * vec_function,struct function_vector * vec_inlined)319063d1a8abSmrg read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
319163d1a8abSmrg 		     struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
319263d1a8abSmrg 		     const struct line_header *lhdr,
319363d1a8abSmrg 		     backtrace_error_callback error_callback, void *data,
319463d1a8abSmrg 		     struct function_vector *vec_function,
319563d1a8abSmrg 		     struct function_vector *vec_inlined)
319663d1a8abSmrg {
319763d1a8abSmrg   while (unit_buf->left > 0)
319863d1a8abSmrg     {
319963d1a8abSmrg       uint64_t code;
320063d1a8abSmrg       const struct abbrev *abbrev;
320163d1a8abSmrg       int is_function;
320263d1a8abSmrg       struct function *function;
320363d1a8abSmrg       struct function_vector *vec;
320463d1a8abSmrg       size_t i;
3205*ec02198aSmrg       struct pcrange pcrange;
32060fc04c29Smrg       int have_linkage_name;
320763d1a8abSmrg 
320863d1a8abSmrg       code = read_uleb128 (unit_buf);
320963d1a8abSmrg       if (code == 0)
321063d1a8abSmrg 	return 1;
321163d1a8abSmrg 
321263d1a8abSmrg       abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
321363d1a8abSmrg       if (abbrev == NULL)
321463d1a8abSmrg 	return 0;
321563d1a8abSmrg 
321663d1a8abSmrg       is_function = (abbrev->tag == DW_TAG_subprogram
321763d1a8abSmrg 		     || abbrev->tag == DW_TAG_entry_point
321863d1a8abSmrg 		     || abbrev->tag == DW_TAG_inlined_subroutine);
321963d1a8abSmrg 
322063d1a8abSmrg       if (abbrev->tag == DW_TAG_inlined_subroutine)
322163d1a8abSmrg 	vec = vec_inlined;
322263d1a8abSmrg       else
322363d1a8abSmrg 	vec = vec_function;
322463d1a8abSmrg 
322563d1a8abSmrg       function = NULL;
322663d1a8abSmrg       if (is_function)
322763d1a8abSmrg 	{
322863d1a8abSmrg 	  function = ((struct function *)
322963d1a8abSmrg 		      backtrace_alloc (state, sizeof *function,
323063d1a8abSmrg 				       error_callback, data));
323163d1a8abSmrg 	  if (function == NULL)
323263d1a8abSmrg 	    return 0;
323363d1a8abSmrg 	  memset (function, 0, sizeof *function);
323463d1a8abSmrg 	}
323563d1a8abSmrg 
3236*ec02198aSmrg       memset (&pcrange, 0, sizeof pcrange);
32370fc04c29Smrg       have_linkage_name = 0;
323863d1a8abSmrg       for (i = 0; i < abbrev->num_attrs; ++i)
323963d1a8abSmrg 	{
324063d1a8abSmrg 	  struct attr_val val;
324163d1a8abSmrg 
3242*ec02198aSmrg 	  if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val,
3243*ec02198aSmrg 			       unit_buf, u->is_dwarf64, u->version,
3244*ec02198aSmrg 			       u->addrsize, &ddata->dwarf_sections,
32450fc04c29Smrg 			       ddata->altlink, &val))
324663d1a8abSmrg 	    return 0;
324763d1a8abSmrg 
324863d1a8abSmrg 	  /* The compile unit sets the base address for any address
324963d1a8abSmrg 	     ranges in the function entries.  */
325063d1a8abSmrg 	  if (abbrev->tag == DW_TAG_compile_unit
3251*ec02198aSmrg 	      && abbrev->attrs[i].name == DW_AT_low_pc)
3252*ec02198aSmrg 	    {
3253*ec02198aSmrg 	      if (val.encoding == ATTR_VAL_ADDRESS)
325463d1a8abSmrg 		base = val.u.uint;
3255*ec02198aSmrg 	      else if (val.encoding == ATTR_VAL_ADDRESS_INDEX)
3256*ec02198aSmrg 		{
3257*ec02198aSmrg 		  if (!resolve_addr_index (&ddata->dwarf_sections,
3258*ec02198aSmrg 					   u->addr_base, u->addrsize,
3259*ec02198aSmrg 					   ddata->is_bigendian, val.u.uint,
3260*ec02198aSmrg 					   error_callback, data, &base))
3261*ec02198aSmrg 		    return 0;
3262*ec02198aSmrg 		}
3263*ec02198aSmrg 	    }
326463d1a8abSmrg 
326563d1a8abSmrg 	  if (is_function)
326663d1a8abSmrg 	    {
326763d1a8abSmrg 	      switch (abbrev->attrs[i].name)
326863d1a8abSmrg 		{
326963d1a8abSmrg 		case DW_AT_call_file:
327063d1a8abSmrg 		  if (val.encoding == ATTR_VAL_UINT)
327163d1a8abSmrg 		    {
327263d1a8abSmrg 		      if (val.u.uint == 0)
327363d1a8abSmrg 			function->caller_filename = "";
327463d1a8abSmrg 		      else
327563d1a8abSmrg 			{
327663d1a8abSmrg 			  if (val.u.uint - 1 >= lhdr->filenames_count)
327763d1a8abSmrg 			    {
327863d1a8abSmrg 			      dwarf_buf_error (unit_buf,
327963d1a8abSmrg 					       ("invalid file number in "
328063d1a8abSmrg 						"DW_AT_call_file attribute"));
328163d1a8abSmrg 			      return 0;
328263d1a8abSmrg 			    }
328363d1a8abSmrg 			  function->caller_filename =
328463d1a8abSmrg 			    lhdr->filenames[val.u.uint - 1];
328563d1a8abSmrg 			}
328663d1a8abSmrg 		    }
328763d1a8abSmrg 		  break;
328863d1a8abSmrg 
328963d1a8abSmrg 		case DW_AT_call_line:
329063d1a8abSmrg 		  if (val.encoding == ATTR_VAL_UINT)
329163d1a8abSmrg 		    function->caller_lineno = val.u.uint;
329263d1a8abSmrg 		  break;
329363d1a8abSmrg 
329463d1a8abSmrg 		case DW_AT_abstract_origin:
329563d1a8abSmrg 		case DW_AT_specification:
32960fc04c29Smrg 		  /* Second name preference: override DW_AT_name, don't override
32970fc04c29Smrg 		     DW_AT_linkage_name.  */
32980fc04c29Smrg 		  if (have_linkage_name)
329963d1a8abSmrg 		    break;
330063d1a8abSmrg 		  {
330163d1a8abSmrg 		    const char *name;
330263d1a8abSmrg 
33030fc04c29Smrg 		    name
33040fc04c29Smrg 		      = read_referenced_name_from_attr (ddata, u,
33050fc04c29Smrg 							&abbrev->attrs[i], &val,
330663d1a8abSmrg 							error_callback, data);
330763d1a8abSmrg 		    if (name != NULL)
330863d1a8abSmrg 		      function->name = name;
330963d1a8abSmrg 		  }
331063d1a8abSmrg 		  break;
331163d1a8abSmrg 
331263d1a8abSmrg 		case DW_AT_name:
33130fc04c29Smrg 		  /* Third name preference: don't override.  */
33140fc04c29Smrg 		  if (function->name != NULL)
33150fc04c29Smrg 		    break;
3316*ec02198aSmrg 		  if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,
3317*ec02198aSmrg 				       ddata->is_bigendian,
3318*ec02198aSmrg 				       u->str_offsets_base, &val,
3319*ec02198aSmrg 				       error_callback, data, &function->name))
3320*ec02198aSmrg 		    return 0;
332163d1a8abSmrg 		  break;
332263d1a8abSmrg 
332363d1a8abSmrg 		case DW_AT_linkage_name:
332463d1a8abSmrg 		case DW_AT_MIPS_linkage_name:
33250fc04c29Smrg 		  /* First name preference: override all.  */
33260fc04c29Smrg 		  {
3327*ec02198aSmrg 		    const char *s;
3328*ec02198aSmrg 
3329*ec02198aSmrg 		    s = NULL;
3330*ec02198aSmrg 		    if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64,
3331*ec02198aSmrg 					 ddata->is_bigendian,
3332*ec02198aSmrg 					 u->str_offsets_base, &val,
3333*ec02198aSmrg 					 error_callback, data, &s))
3334*ec02198aSmrg 		      return 0;
3335*ec02198aSmrg 		    if (s != NULL)
3336*ec02198aSmrg 		      {
3337*ec02198aSmrg 			function->name = s;
33380fc04c29Smrg 			have_linkage_name = 1;
33390fc04c29Smrg 		      }
334063d1a8abSmrg 		  }
334163d1a8abSmrg 		  break;
334263d1a8abSmrg 
3343*ec02198aSmrg 		case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges:
3344*ec02198aSmrg 		  update_pcrange (&abbrev->attrs[i], &val, &pcrange);
334563d1a8abSmrg 		  break;
334663d1a8abSmrg 
334763d1a8abSmrg 		default:
334863d1a8abSmrg 		  break;
334963d1a8abSmrg 		}
335063d1a8abSmrg 	    }
335163d1a8abSmrg 	}
335263d1a8abSmrg 
335363d1a8abSmrg       /* If we couldn't find a name for the function, we have no use
335463d1a8abSmrg 	 for it.  */
335563d1a8abSmrg       if (is_function && function->name == NULL)
335663d1a8abSmrg 	{
335763d1a8abSmrg 	  backtrace_free (state, function, sizeof *function,
335863d1a8abSmrg 			  error_callback, data);
335963d1a8abSmrg 	  is_function = 0;
336063d1a8abSmrg 	}
336163d1a8abSmrg 
336263d1a8abSmrg       if (is_function)
336363d1a8abSmrg 	{
3364*ec02198aSmrg 	  if (pcrange.have_ranges
3365*ec02198aSmrg 	      || (pcrange.have_lowpc && pcrange.have_highpc))
336663d1a8abSmrg 	    {
3367*ec02198aSmrg 	      if (!add_ranges (state, &ddata->dwarf_sections,
3368*ec02198aSmrg 			       ddata->base_address, ddata->is_bigendian,
3369*ec02198aSmrg 			       u, base, &pcrange, add_function_range,
3370*ec02198aSmrg 			       (void *) function, error_callback, data,
3371*ec02198aSmrg 			       (void *) vec))
337263d1a8abSmrg 		return 0;
337363d1a8abSmrg 	    }
337463d1a8abSmrg 	  else
337563d1a8abSmrg 	    {
337663d1a8abSmrg 	      backtrace_free (state, function, sizeof *function,
337763d1a8abSmrg 			      error_callback, data);
337863d1a8abSmrg 	      is_function = 0;
337963d1a8abSmrg 	    }
338063d1a8abSmrg 	}
338163d1a8abSmrg 
338263d1a8abSmrg       if (abbrev->has_children)
338363d1a8abSmrg 	{
338463d1a8abSmrg 	  if (!is_function)
338563d1a8abSmrg 	    {
338663d1a8abSmrg 	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
338763d1a8abSmrg 					error_callback, data, vec_function,
338863d1a8abSmrg 					vec_inlined))
338963d1a8abSmrg 		return 0;
339063d1a8abSmrg 	    }
339163d1a8abSmrg 	  else
339263d1a8abSmrg 	    {
339363d1a8abSmrg 	      struct function_vector fvec;
339463d1a8abSmrg 
339563d1a8abSmrg 	      /* Gather any information for inlined functions in
339663d1a8abSmrg 		 FVEC.  */
339763d1a8abSmrg 
339863d1a8abSmrg 	      memset (&fvec, 0, sizeof fvec);
339963d1a8abSmrg 
340063d1a8abSmrg 	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
340163d1a8abSmrg 					error_callback, data, vec_function,
340263d1a8abSmrg 					&fvec))
340363d1a8abSmrg 		return 0;
340463d1a8abSmrg 
340563d1a8abSmrg 	      if (fvec.count > 0)
340663d1a8abSmrg 		{
340763d1a8abSmrg 		  struct function_addrs *faddrs;
340863d1a8abSmrg 
340963d1a8abSmrg 		  if (!backtrace_vector_release (state, &fvec.vec,
341063d1a8abSmrg 						 error_callback, data))
341163d1a8abSmrg 		    return 0;
341263d1a8abSmrg 
341363d1a8abSmrg 		  faddrs = (struct function_addrs *) fvec.vec.base;
341463d1a8abSmrg 		  backtrace_qsort (faddrs, fvec.count,
341563d1a8abSmrg 				   sizeof (struct function_addrs),
341663d1a8abSmrg 				   function_addrs_compare);
341763d1a8abSmrg 
341863d1a8abSmrg 		  function->function_addrs = faddrs;
341963d1a8abSmrg 		  function->function_addrs_count = fvec.count;
342063d1a8abSmrg 		}
342163d1a8abSmrg 	    }
342263d1a8abSmrg 	}
342363d1a8abSmrg     }
342463d1a8abSmrg 
342563d1a8abSmrg   return 1;
342663d1a8abSmrg }
342763d1a8abSmrg 
342863d1a8abSmrg /* Read function name information for a compilation unit.  We look
342963d1a8abSmrg    through the whole unit looking for function tags.  */
343063d1a8abSmrg 
343163d1a8abSmrg static void
read_function_info(struct backtrace_state * state,struct dwarf_data * ddata,const struct line_header * lhdr,backtrace_error_callback error_callback,void * data,struct unit * u,struct function_vector * fvec,struct function_addrs ** ret_addrs,size_t * ret_addrs_count)343263d1a8abSmrg read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
343363d1a8abSmrg 		    const struct line_header *lhdr,
343463d1a8abSmrg 		    backtrace_error_callback error_callback, void *data,
343563d1a8abSmrg 		    struct unit *u, struct function_vector *fvec,
343663d1a8abSmrg 		    struct function_addrs **ret_addrs,
343763d1a8abSmrg 		    size_t *ret_addrs_count)
343863d1a8abSmrg {
343963d1a8abSmrg   struct function_vector lvec;
344063d1a8abSmrg   struct function_vector *pfvec;
344163d1a8abSmrg   struct dwarf_buf unit_buf;
344263d1a8abSmrg   struct function_addrs *addrs;
344363d1a8abSmrg   size_t addrs_count;
344463d1a8abSmrg 
344563d1a8abSmrg   /* Use FVEC if it is not NULL.  Otherwise use our own vector.  */
344663d1a8abSmrg   if (fvec != NULL)
344763d1a8abSmrg     pfvec = fvec;
344863d1a8abSmrg   else
344963d1a8abSmrg     {
345063d1a8abSmrg       memset (&lvec, 0, sizeof lvec);
345163d1a8abSmrg       pfvec = &lvec;
345263d1a8abSmrg     }
345363d1a8abSmrg 
345463d1a8abSmrg   unit_buf.name = ".debug_info";
3455*ec02198aSmrg   unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO];
345663d1a8abSmrg   unit_buf.buf = u->unit_data;
345763d1a8abSmrg   unit_buf.left = u->unit_data_len;
345863d1a8abSmrg   unit_buf.is_bigendian = ddata->is_bigendian;
345963d1a8abSmrg   unit_buf.error_callback = error_callback;
346063d1a8abSmrg   unit_buf.data = data;
346163d1a8abSmrg   unit_buf.reported_underflow = 0;
346263d1a8abSmrg 
346363d1a8abSmrg   while (unit_buf.left > 0)
346463d1a8abSmrg     {
346563d1a8abSmrg       if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,
346663d1a8abSmrg 				error_callback, data, pfvec, pfvec))
346763d1a8abSmrg 	return;
346863d1a8abSmrg     }
346963d1a8abSmrg 
347063d1a8abSmrg   if (pfvec->count == 0)
347163d1a8abSmrg     return;
347263d1a8abSmrg 
347363d1a8abSmrg   addrs_count = pfvec->count;
347463d1a8abSmrg 
347563d1a8abSmrg   if (fvec == NULL)
347663d1a8abSmrg     {
347763d1a8abSmrg       if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))
347863d1a8abSmrg 	return;
347963d1a8abSmrg       addrs = (struct function_addrs *) pfvec->vec.base;
348063d1a8abSmrg     }
348163d1a8abSmrg   else
348263d1a8abSmrg     {
348363d1a8abSmrg       /* Finish this list of addresses, but leave the remaining space in
348463d1a8abSmrg 	 the vector available for the next function unit.  */
348563d1a8abSmrg       addrs = ((struct function_addrs *)
348663d1a8abSmrg 	       backtrace_vector_finish (state, &fvec->vec,
348763d1a8abSmrg 					error_callback, data));
348863d1a8abSmrg       if (addrs == NULL)
348963d1a8abSmrg 	return;
349063d1a8abSmrg       fvec->count = 0;
349163d1a8abSmrg     }
349263d1a8abSmrg 
349363d1a8abSmrg   backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),
349463d1a8abSmrg 		   function_addrs_compare);
349563d1a8abSmrg 
349663d1a8abSmrg   *ret_addrs = addrs;
349763d1a8abSmrg   *ret_addrs_count = addrs_count;
349863d1a8abSmrg }
349963d1a8abSmrg 
350063d1a8abSmrg /* See if PC is inlined in FUNCTION.  If it is, print out the inlined
350163d1a8abSmrg    information, and update FILENAME and LINENO for the caller.
350263d1a8abSmrg    Returns whatever CALLBACK returns, or 0 to keep going.  */
350363d1a8abSmrg 
350463d1a8abSmrg static int
report_inlined_functions(uintptr_t pc,struct function * function,backtrace_full_callback callback,void * data,const char ** filename,int * lineno)350563d1a8abSmrg report_inlined_functions (uintptr_t pc, struct function *function,
350663d1a8abSmrg 			  backtrace_full_callback callback, void *data,
350763d1a8abSmrg 			  const char **filename, int *lineno)
350863d1a8abSmrg {
350963d1a8abSmrg   struct function_addrs *function_addrs;
351063d1a8abSmrg   struct function *inlined;
351163d1a8abSmrg   int ret;
351263d1a8abSmrg 
351363d1a8abSmrg   if (function->function_addrs_count == 0)
351463d1a8abSmrg     return 0;
351563d1a8abSmrg 
351663d1a8abSmrg   function_addrs = ((struct function_addrs *)
351763d1a8abSmrg 		    bsearch (&pc, function->function_addrs,
351863d1a8abSmrg 			     function->function_addrs_count,
351963d1a8abSmrg 			     sizeof (struct function_addrs),
352063d1a8abSmrg 			     function_addrs_search));
352163d1a8abSmrg   if (function_addrs == NULL)
352263d1a8abSmrg     return 0;
352363d1a8abSmrg 
352463d1a8abSmrg   while (((size_t) (function_addrs - function->function_addrs) + 1
352563d1a8abSmrg 	  < function->function_addrs_count)
352663d1a8abSmrg 	 && pc >= (function_addrs + 1)->low
352763d1a8abSmrg 	 && pc < (function_addrs + 1)->high)
352863d1a8abSmrg     ++function_addrs;
352963d1a8abSmrg 
353063d1a8abSmrg   /* We found an inlined call.  */
353163d1a8abSmrg 
353263d1a8abSmrg   inlined = function_addrs->function;
353363d1a8abSmrg 
353463d1a8abSmrg   /* Report any calls inlined into this one.  */
353563d1a8abSmrg   ret = report_inlined_functions (pc, inlined, callback, data,
353663d1a8abSmrg 				  filename, lineno);
353763d1a8abSmrg   if (ret != 0)
353863d1a8abSmrg     return ret;
353963d1a8abSmrg 
354063d1a8abSmrg   /* Report this inlined call.  */
354163d1a8abSmrg   ret = callback (data, pc, *filename, *lineno, inlined->name);
354263d1a8abSmrg   if (ret != 0)
354363d1a8abSmrg     return ret;
354463d1a8abSmrg 
354563d1a8abSmrg   /* Our caller will report the caller of the inlined function; tell
354663d1a8abSmrg      it the appropriate filename and line number.  */
354763d1a8abSmrg   *filename = inlined->caller_filename;
354863d1a8abSmrg   *lineno = inlined->caller_lineno;
354963d1a8abSmrg 
355063d1a8abSmrg   return 0;
355163d1a8abSmrg }
355263d1a8abSmrg 
355363d1a8abSmrg /* Look for a PC in the DWARF mapping for one module.  On success,
355463d1a8abSmrg    call CALLBACK and return whatever it returns.  On error, call
355563d1a8abSmrg    ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,
355663d1a8abSmrg    0 if not.  */
355763d1a8abSmrg 
355863d1a8abSmrg static int
dwarf_lookup_pc(struct backtrace_state * state,struct dwarf_data * ddata,uintptr_t pc,backtrace_full_callback callback,backtrace_error_callback error_callback,void * data,int * found)355963d1a8abSmrg dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
356063d1a8abSmrg 		 uintptr_t pc, backtrace_full_callback callback,
356163d1a8abSmrg 		 backtrace_error_callback error_callback, void *data,
356263d1a8abSmrg 		 int *found)
356363d1a8abSmrg {
356463d1a8abSmrg   struct unit_addrs *entry;
356563d1a8abSmrg   struct unit *u;
356663d1a8abSmrg   int new_data;
356763d1a8abSmrg   struct line *lines;
356863d1a8abSmrg   struct line *ln;
356963d1a8abSmrg   struct function_addrs *function_addrs;
357063d1a8abSmrg   struct function *function;
357163d1a8abSmrg   const char *filename;
357263d1a8abSmrg   int lineno;
357363d1a8abSmrg   int ret;
357463d1a8abSmrg 
357563d1a8abSmrg   *found = 1;
357663d1a8abSmrg 
357763d1a8abSmrg   /* Find an address range that includes PC.  */
35780fc04c29Smrg   entry = (ddata->addrs_count == 0
35790fc04c29Smrg 	   ? NULL
35800fc04c29Smrg 	   : bsearch (&pc, ddata->addrs, ddata->addrs_count,
35810fc04c29Smrg 		      sizeof (struct unit_addrs), unit_addrs_search));
358263d1a8abSmrg 
358363d1a8abSmrg   if (entry == NULL)
358463d1a8abSmrg     {
358563d1a8abSmrg       *found = 0;
358663d1a8abSmrg       return 0;
358763d1a8abSmrg     }
358863d1a8abSmrg 
358963d1a8abSmrg   /* If there are multiple ranges that contain PC, use the last one,
359063d1a8abSmrg      in order to produce predictable results.  If we assume that all
359163d1a8abSmrg      ranges are properly nested, then the last range will be the
359263d1a8abSmrg      smallest one.  */
359363d1a8abSmrg   while ((size_t) (entry - ddata->addrs) + 1 < ddata->addrs_count
359463d1a8abSmrg 	 && pc >= (entry + 1)->low
359563d1a8abSmrg 	 && pc < (entry + 1)->high)
359663d1a8abSmrg     ++entry;
359763d1a8abSmrg 
359863d1a8abSmrg   /* We need the lines, lines_count, function_addrs,
359963d1a8abSmrg      function_addrs_count fields of u.  If they are not set, we need
360063d1a8abSmrg      to set them.  When running in threaded mode, we need to allow for
360163d1a8abSmrg      the possibility that some other thread is setting them
360263d1a8abSmrg      simultaneously.  */
360363d1a8abSmrg 
360463d1a8abSmrg   u = entry->u;
360563d1a8abSmrg   lines = u->lines;
360663d1a8abSmrg 
360763d1a8abSmrg   /* Skip units with no useful line number information by walking
360863d1a8abSmrg      backward.  Useless line number information is marked by setting
360963d1a8abSmrg      lines == -1.  */
361063d1a8abSmrg   while (entry > ddata->addrs
361163d1a8abSmrg 	 && pc >= (entry - 1)->low
361263d1a8abSmrg 	 && pc < (entry - 1)->high)
361363d1a8abSmrg     {
361463d1a8abSmrg       if (state->threaded)
361563d1a8abSmrg 	lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);
361663d1a8abSmrg 
361763d1a8abSmrg       if (lines != (struct line *) (uintptr_t) -1)
361863d1a8abSmrg 	break;
361963d1a8abSmrg 
362063d1a8abSmrg       --entry;
362163d1a8abSmrg 
362263d1a8abSmrg       u = entry->u;
362363d1a8abSmrg       lines = u->lines;
362463d1a8abSmrg     }
362563d1a8abSmrg 
362663d1a8abSmrg   if (state->threaded)
362763d1a8abSmrg     lines = backtrace_atomic_load_pointer (&u->lines);
362863d1a8abSmrg 
362963d1a8abSmrg   new_data = 0;
363063d1a8abSmrg   if (lines == NULL)
363163d1a8abSmrg     {
363263d1a8abSmrg       size_t function_addrs_count;
363363d1a8abSmrg       struct line_header lhdr;
363463d1a8abSmrg       size_t count;
363563d1a8abSmrg 
363663d1a8abSmrg       /* We have never read the line information for this unit.  Read
363763d1a8abSmrg 	 it now.  */
363863d1a8abSmrg 
363963d1a8abSmrg       function_addrs = NULL;
364063d1a8abSmrg       function_addrs_count = 0;
364163d1a8abSmrg       if (read_line_info (state, ddata, error_callback, data, entry->u, &lhdr,
364263d1a8abSmrg 			  &lines, &count))
364363d1a8abSmrg 	{
364463d1a8abSmrg 	  struct function_vector *pfvec;
364563d1a8abSmrg 
364663d1a8abSmrg 	  /* If not threaded, reuse DDATA->FVEC for better memory
364763d1a8abSmrg 	     consumption.  */
364863d1a8abSmrg 	  if (state->threaded)
364963d1a8abSmrg 	    pfvec = NULL;
365063d1a8abSmrg 	  else
365163d1a8abSmrg 	    pfvec = &ddata->fvec;
365263d1a8abSmrg 	  read_function_info (state, ddata, &lhdr, error_callback, data,
365363d1a8abSmrg 			      entry->u, pfvec, &function_addrs,
365463d1a8abSmrg 			      &function_addrs_count);
365563d1a8abSmrg 	  free_line_header (state, &lhdr, error_callback, data);
365663d1a8abSmrg 	  new_data = 1;
365763d1a8abSmrg 	}
365863d1a8abSmrg 
365963d1a8abSmrg       /* Atomically store the information we just read into the unit.
366063d1a8abSmrg 	 If another thread is simultaneously writing, it presumably
366163d1a8abSmrg 	 read the same information, and we don't care which one we
366263d1a8abSmrg 	 wind up with; we just leak the other one.  We do have to
366363d1a8abSmrg 	 write the lines field last, so that the acquire-loads above
366463d1a8abSmrg 	 ensure that the other fields are set.  */
366563d1a8abSmrg 
366663d1a8abSmrg       if (!state->threaded)
366763d1a8abSmrg 	{
366863d1a8abSmrg 	  u->lines_count = count;
366963d1a8abSmrg 	  u->function_addrs = function_addrs;
367063d1a8abSmrg 	  u->function_addrs_count = function_addrs_count;
367163d1a8abSmrg 	  u->lines = lines;
367263d1a8abSmrg 	}
367363d1a8abSmrg       else
367463d1a8abSmrg 	{
367563d1a8abSmrg 	  backtrace_atomic_store_size_t (&u->lines_count, count);
367663d1a8abSmrg 	  backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);
367763d1a8abSmrg 	  backtrace_atomic_store_size_t (&u->function_addrs_count,
367863d1a8abSmrg 					 function_addrs_count);
367963d1a8abSmrg 	  backtrace_atomic_store_pointer (&u->lines, lines);
368063d1a8abSmrg 	}
368163d1a8abSmrg     }
368263d1a8abSmrg 
368363d1a8abSmrg   /* Now all fields of U have been initialized.  */
368463d1a8abSmrg 
368563d1a8abSmrg   if (lines == (struct line *) (uintptr_t) -1)
368663d1a8abSmrg     {
368763d1a8abSmrg       /* If reading the line number information failed in some way,
368863d1a8abSmrg 	 try again to see if there is a better compilation unit for
368963d1a8abSmrg 	 this PC.  */
369063d1a8abSmrg       if (new_data)
369163d1a8abSmrg 	return dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
369263d1a8abSmrg 				data, found);
369363d1a8abSmrg       return callback (data, pc, NULL, 0, NULL);
369463d1a8abSmrg     }
369563d1a8abSmrg 
369663d1a8abSmrg   /* Search for PC within this unit.  */
369763d1a8abSmrg 
369863d1a8abSmrg   ln = (struct line *) bsearch (&pc, lines, entry->u->lines_count,
369963d1a8abSmrg 				sizeof (struct line), line_search);
370063d1a8abSmrg   if (ln == NULL)
370163d1a8abSmrg     {
370263d1a8abSmrg       /* The PC is between the low_pc and high_pc attributes of the
370363d1a8abSmrg 	 compilation unit, but no entry in the line table covers it.
370463d1a8abSmrg 	 This implies that the start of the compilation unit has no
370563d1a8abSmrg 	 line number information.  */
370663d1a8abSmrg 
370763d1a8abSmrg       if (entry->u->abs_filename == NULL)
370863d1a8abSmrg 	{
370963d1a8abSmrg 	  const char *filename;
371063d1a8abSmrg 
371163d1a8abSmrg 	  filename = entry->u->filename;
371263d1a8abSmrg 	  if (filename != NULL
371363d1a8abSmrg 	      && !IS_ABSOLUTE_PATH (filename)
371463d1a8abSmrg 	      && entry->u->comp_dir != NULL)
371563d1a8abSmrg 	    {
371663d1a8abSmrg 	      size_t filename_len;
371763d1a8abSmrg 	      const char *dir;
371863d1a8abSmrg 	      size_t dir_len;
371963d1a8abSmrg 	      char *s;
372063d1a8abSmrg 
372163d1a8abSmrg 	      filename_len = strlen (filename);
372263d1a8abSmrg 	      dir = entry->u->comp_dir;
372363d1a8abSmrg 	      dir_len = strlen (dir);
372463d1a8abSmrg 	      s = (char *) backtrace_alloc (state, dir_len + filename_len + 2,
372563d1a8abSmrg 					    error_callback, data);
372663d1a8abSmrg 	      if (s == NULL)
372763d1a8abSmrg 		{
372863d1a8abSmrg 		  *found = 0;
372963d1a8abSmrg 		  return 0;
373063d1a8abSmrg 		}
373163d1a8abSmrg 	      memcpy (s, dir, dir_len);
373263d1a8abSmrg 	      /* FIXME: Should use backslash if DOS file system.  */
373363d1a8abSmrg 	      s[dir_len] = '/';
373463d1a8abSmrg 	      memcpy (s + dir_len + 1, filename, filename_len + 1);
373563d1a8abSmrg 	      filename = s;
373663d1a8abSmrg 	    }
373763d1a8abSmrg 	  entry->u->abs_filename = filename;
373863d1a8abSmrg 	}
373963d1a8abSmrg 
374063d1a8abSmrg       return callback (data, pc, entry->u->abs_filename, 0, NULL);
374163d1a8abSmrg     }
374263d1a8abSmrg 
374363d1a8abSmrg   /* Search for function name within this unit.  */
374463d1a8abSmrg 
374563d1a8abSmrg   if (entry->u->function_addrs_count == 0)
374663d1a8abSmrg     return callback (data, pc, ln->filename, ln->lineno, NULL);
374763d1a8abSmrg 
374863d1a8abSmrg   function_addrs = ((struct function_addrs *)
374963d1a8abSmrg 		    bsearch (&pc, entry->u->function_addrs,
375063d1a8abSmrg 			     entry->u->function_addrs_count,
375163d1a8abSmrg 			     sizeof (struct function_addrs),
375263d1a8abSmrg 			     function_addrs_search));
375363d1a8abSmrg   if (function_addrs == NULL)
375463d1a8abSmrg     return callback (data, pc, ln->filename, ln->lineno, NULL);
375563d1a8abSmrg 
375663d1a8abSmrg   /* If there are multiple function ranges that contain PC, use the
375763d1a8abSmrg      last one, in order to produce predictable results.  */
375863d1a8abSmrg 
375963d1a8abSmrg   while (((size_t) (function_addrs - entry->u->function_addrs + 1)
376063d1a8abSmrg 	  < entry->u->function_addrs_count)
376163d1a8abSmrg 	 && pc >= (function_addrs + 1)->low
376263d1a8abSmrg 	 && pc < (function_addrs + 1)->high)
376363d1a8abSmrg     ++function_addrs;
376463d1a8abSmrg 
376563d1a8abSmrg   function = function_addrs->function;
376663d1a8abSmrg 
376763d1a8abSmrg   filename = ln->filename;
376863d1a8abSmrg   lineno = ln->lineno;
376963d1a8abSmrg 
377063d1a8abSmrg   ret = report_inlined_functions (pc, function, callback, data,
377163d1a8abSmrg 				  &filename, &lineno);
377263d1a8abSmrg   if (ret != 0)
377363d1a8abSmrg     return ret;
377463d1a8abSmrg 
377563d1a8abSmrg   return callback (data, pc, filename, lineno, function->name);
377663d1a8abSmrg }
377763d1a8abSmrg 
377863d1a8abSmrg 
377963d1a8abSmrg /* Return the file/line information for a PC using the DWARF mapping
378063d1a8abSmrg    we built earlier.  */
378163d1a8abSmrg 
378263d1a8abSmrg static int
dwarf_fileline(struct backtrace_state * state,uintptr_t pc,backtrace_full_callback callback,backtrace_error_callback error_callback,void * data)378363d1a8abSmrg dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
378463d1a8abSmrg 		backtrace_full_callback callback,
378563d1a8abSmrg 		backtrace_error_callback error_callback, void *data)
378663d1a8abSmrg {
378763d1a8abSmrg   struct dwarf_data *ddata;
378863d1a8abSmrg   int found;
378963d1a8abSmrg   int ret;
379063d1a8abSmrg 
379163d1a8abSmrg   if (!state->threaded)
379263d1a8abSmrg     {
379363d1a8abSmrg       for (ddata = (struct dwarf_data *) state->fileline_data;
379463d1a8abSmrg 	   ddata != NULL;
379563d1a8abSmrg 	   ddata = ddata->next)
379663d1a8abSmrg 	{
379763d1a8abSmrg 	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
379863d1a8abSmrg 				 data, &found);
379963d1a8abSmrg 	  if (ret != 0 || found)
380063d1a8abSmrg 	    return ret;
380163d1a8abSmrg 	}
380263d1a8abSmrg     }
380363d1a8abSmrg   else
380463d1a8abSmrg     {
380563d1a8abSmrg       struct dwarf_data **pp;
380663d1a8abSmrg 
380763d1a8abSmrg       pp = (struct dwarf_data **) (void *) &state->fileline_data;
380863d1a8abSmrg       while (1)
380963d1a8abSmrg 	{
381063d1a8abSmrg 	  ddata = backtrace_atomic_load_pointer (pp);
381163d1a8abSmrg 	  if (ddata == NULL)
381263d1a8abSmrg 	    break;
381363d1a8abSmrg 
381463d1a8abSmrg 	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
381563d1a8abSmrg 				 data, &found);
381663d1a8abSmrg 	  if (ret != 0 || found)
381763d1a8abSmrg 	    return ret;
381863d1a8abSmrg 
381963d1a8abSmrg 	  pp = &ddata->next;
382063d1a8abSmrg 	}
382163d1a8abSmrg     }
382263d1a8abSmrg 
382363d1a8abSmrg   /* FIXME: See if any libraries have been dlopen'ed.  */
382463d1a8abSmrg 
382563d1a8abSmrg   return callback (data, pc, NULL, 0, NULL);
382663d1a8abSmrg }
382763d1a8abSmrg 
382863d1a8abSmrg /* Initialize our data structures from the DWARF debug info for a
382963d1a8abSmrg    file.  Return NULL on failure.  */
383063d1a8abSmrg 
383163d1a8abSmrg static struct dwarf_data *
build_dwarf_data(struct backtrace_state * state,uintptr_t base_address,const struct dwarf_sections * dwarf_sections,int is_bigendian,struct dwarf_data * altlink,backtrace_error_callback error_callback,void * data)383263d1a8abSmrg build_dwarf_data (struct backtrace_state *state,
383363d1a8abSmrg 		  uintptr_t base_address,
3834*ec02198aSmrg 		  const struct dwarf_sections *dwarf_sections,
383563d1a8abSmrg 		  int is_bigendian,
38360fc04c29Smrg 		  struct dwarf_data *altlink,
383763d1a8abSmrg 		  backtrace_error_callback error_callback,
383863d1a8abSmrg 		  void *data)
383963d1a8abSmrg {
384063d1a8abSmrg   struct unit_addrs_vector addrs_vec;
384163d1a8abSmrg   struct unit_addrs *addrs;
384263d1a8abSmrg   size_t addrs_count;
38430fc04c29Smrg   struct unit_vector units_vec;
38440fc04c29Smrg   struct unit **units;
38450fc04c29Smrg   size_t units_count;
384663d1a8abSmrg   struct dwarf_data *fdata;
384763d1a8abSmrg 
3848*ec02198aSmrg   if (!build_address_map (state, base_address, dwarf_sections, is_bigendian,
3849*ec02198aSmrg 			  altlink, error_callback, data, &addrs_vec,
3850*ec02198aSmrg 			  &units_vec))
385163d1a8abSmrg     return NULL;
385263d1a8abSmrg 
385363d1a8abSmrg   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
385463d1a8abSmrg     return NULL;
38550fc04c29Smrg   if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data))
38560fc04c29Smrg     return NULL;
385763d1a8abSmrg   addrs = (struct unit_addrs *) addrs_vec.vec.base;
38580fc04c29Smrg   units = (struct unit **) units_vec.vec.base;
385963d1a8abSmrg   addrs_count = addrs_vec.count;
38600fc04c29Smrg   units_count = units_vec.count;
386163d1a8abSmrg   backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
386263d1a8abSmrg 		   unit_addrs_compare);
38630fc04c29Smrg   /* No qsort for units required, already sorted.  */
386463d1a8abSmrg 
386563d1a8abSmrg   fdata = ((struct dwarf_data *)
386663d1a8abSmrg 	   backtrace_alloc (state, sizeof (struct dwarf_data),
386763d1a8abSmrg 			    error_callback, data));
386863d1a8abSmrg   if (fdata == NULL)
386963d1a8abSmrg     return NULL;
387063d1a8abSmrg 
387163d1a8abSmrg   fdata->next = NULL;
38720fc04c29Smrg   fdata->altlink = altlink;
387363d1a8abSmrg   fdata->base_address = base_address;
387463d1a8abSmrg   fdata->addrs = addrs;
387563d1a8abSmrg   fdata->addrs_count = addrs_count;
38760fc04c29Smrg   fdata->units = units;
38770fc04c29Smrg   fdata->units_count = units_count;
3878*ec02198aSmrg   fdata->dwarf_sections = *dwarf_sections;
387963d1a8abSmrg   fdata->is_bigendian = is_bigendian;
388063d1a8abSmrg   memset (&fdata->fvec, 0, sizeof fdata->fvec);
388163d1a8abSmrg 
388263d1a8abSmrg   return fdata;
388363d1a8abSmrg }
388463d1a8abSmrg 
388563d1a8abSmrg /* Build our data structures from the DWARF sections for a module.
388663d1a8abSmrg    Set FILELINE_FN and STATE->FILELINE_DATA.  Return 1 on success, 0
388763d1a8abSmrg    on failure.  */
388863d1a8abSmrg 
388963d1a8abSmrg int
backtrace_dwarf_add(struct backtrace_state * state,uintptr_t base_address,const struct dwarf_sections * dwarf_sections,int is_bigendian,struct dwarf_data * fileline_altlink,backtrace_error_callback error_callback,void * data,fileline * fileline_fn,struct dwarf_data ** fileline_entry)389063d1a8abSmrg backtrace_dwarf_add (struct backtrace_state *state,
389163d1a8abSmrg 		     uintptr_t base_address,
3892*ec02198aSmrg 		     const struct dwarf_sections *dwarf_sections,
389363d1a8abSmrg 		     int is_bigendian,
38940fc04c29Smrg 		     struct dwarf_data *fileline_altlink,
389563d1a8abSmrg 		     backtrace_error_callback error_callback,
38960fc04c29Smrg 		     void *data, fileline *fileline_fn,
38970fc04c29Smrg 		     struct dwarf_data **fileline_entry)
389863d1a8abSmrg {
389963d1a8abSmrg   struct dwarf_data *fdata;
390063d1a8abSmrg 
3901*ec02198aSmrg   fdata = build_dwarf_data (state, base_address, dwarf_sections, is_bigendian,
39020fc04c29Smrg 			    fileline_altlink, error_callback, data);
390363d1a8abSmrg   if (fdata == NULL)
390463d1a8abSmrg     return 0;
390563d1a8abSmrg 
39060fc04c29Smrg   if (fileline_entry != NULL)
39070fc04c29Smrg     *fileline_entry = fdata;
39080fc04c29Smrg 
390963d1a8abSmrg   if (!state->threaded)
391063d1a8abSmrg     {
391163d1a8abSmrg       struct dwarf_data **pp;
391263d1a8abSmrg 
391363d1a8abSmrg       for (pp = (struct dwarf_data **) (void *) &state->fileline_data;
391463d1a8abSmrg 	   *pp != NULL;
391563d1a8abSmrg 	   pp = &(*pp)->next)
391663d1a8abSmrg 	;
391763d1a8abSmrg       *pp = fdata;
391863d1a8abSmrg     }
391963d1a8abSmrg   else
392063d1a8abSmrg     {
392163d1a8abSmrg       while (1)
392263d1a8abSmrg 	{
392363d1a8abSmrg 	  struct dwarf_data **pp;
392463d1a8abSmrg 
392563d1a8abSmrg 	  pp = (struct dwarf_data **) (void *) &state->fileline_data;
392663d1a8abSmrg 
392763d1a8abSmrg 	  while (1)
392863d1a8abSmrg 	    {
392963d1a8abSmrg 	      struct dwarf_data *p;
393063d1a8abSmrg 
393163d1a8abSmrg 	      p = backtrace_atomic_load_pointer (pp);
393263d1a8abSmrg 
393363d1a8abSmrg 	      if (p == NULL)
393463d1a8abSmrg 		break;
393563d1a8abSmrg 
393663d1a8abSmrg 	      pp = &p->next;
393763d1a8abSmrg 	    }
393863d1a8abSmrg 
393963d1a8abSmrg 	  if (__sync_bool_compare_and_swap (pp, NULL, fdata))
394063d1a8abSmrg 	    break;
394163d1a8abSmrg 	}
394263d1a8abSmrg     }
394363d1a8abSmrg 
394463d1a8abSmrg   *fileline_fn = dwarf_fileline;
394563d1a8abSmrg 
394663d1a8abSmrg   return 1;
394763d1a8abSmrg }
3948