xref: /dflybsd-src/contrib/gcc-8.0/libbacktrace/dwarf.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* dwarf.c -- Get file/line information from DWARF for backtraces.
2*38fd1498Szrj    Copyright (C) 2012-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Written by Ian Lance Taylor, Google.
4*38fd1498Szrj 
5*38fd1498Szrj Redistribution and use in source and binary forms, with or without
6*38fd1498Szrj modification, are permitted provided that the following conditions are
7*38fd1498Szrj met:
8*38fd1498Szrj 
9*38fd1498Szrj     (1) Redistributions of source code must retain the above copyright
10*38fd1498Szrj     notice, this list of conditions and the following disclaimer.
11*38fd1498Szrj 
12*38fd1498Szrj     (2) Redistributions in binary form must reproduce the above copyright
13*38fd1498Szrj     notice, this list of conditions and the following disclaimer in
14*38fd1498Szrj     the documentation and/or other materials provided with the
15*38fd1498Szrj     distribution.
16*38fd1498Szrj 
17*38fd1498Szrj     (3) The name of the author may not be used to
18*38fd1498Szrj     endorse or promote products derived from this software without
19*38fd1498Szrj     specific prior written permission.
20*38fd1498Szrj 
21*38fd1498Szrj THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22*38fd1498Szrj IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23*38fd1498Szrj WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24*38fd1498Szrj DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25*38fd1498Szrj INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26*38fd1498Szrj (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27*38fd1498Szrj SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*38fd1498Szrj HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29*38fd1498Szrj STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30*38fd1498Szrj IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31*38fd1498Szrj POSSIBILITY OF SUCH DAMAGE.  */
32*38fd1498Szrj 
33*38fd1498Szrj #include "config.h"
34*38fd1498Szrj 
35*38fd1498Szrj #include <errno.h>
36*38fd1498Szrj #include <stdlib.h>
37*38fd1498Szrj #include <string.h>
38*38fd1498Szrj #include <sys/types.h>
39*38fd1498Szrj 
40*38fd1498Szrj #include "dwarf2.h"
41*38fd1498Szrj #include "filenames.h"
42*38fd1498Szrj 
43*38fd1498Szrj #include "backtrace.h"
44*38fd1498Szrj #include "internal.h"
45*38fd1498Szrj 
46*38fd1498Szrj #if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
47*38fd1498Szrj 
48*38fd1498Szrj /* If strnlen is not declared, provide our own version.  */
49*38fd1498Szrj 
50*38fd1498Szrj static size_t
xstrnlen(const char * s,size_t maxlen)51*38fd1498Szrj xstrnlen (const char *s, size_t maxlen)
52*38fd1498Szrj {
53*38fd1498Szrj   size_t i;
54*38fd1498Szrj 
55*38fd1498Szrj   for (i = 0; i < maxlen; ++i)
56*38fd1498Szrj     if (s[i] == '\0')
57*38fd1498Szrj       break;
58*38fd1498Szrj   return i;
59*38fd1498Szrj }
60*38fd1498Szrj 
61*38fd1498Szrj #define strnlen xstrnlen
62*38fd1498Szrj 
63*38fd1498Szrj #endif
64*38fd1498Szrj 
65*38fd1498Szrj /* A buffer to read DWARF info.  */
66*38fd1498Szrj 
67*38fd1498Szrj struct dwarf_buf
68*38fd1498Szrj {
69*38fd1498Szrj   /* Buffer name for error messages.  */
70*38fd1498Szrj   const char *name;
71*38fd1498Szrj   /* Start of the buffer.  */
72*38fd1498Szrj   const unsigned char *start;
73*38fd1498Szrj   /* Next byte to read.  */
74*38fd1498Szrj   const unsigned char *buf;
75*38fd1498Szrj   /* The number of bytes remaining.  */
76*38fd1498Szrj   size_t left;
77*38fd1498Szrj   /* Whether the data is big-endian.  */
78*38fd1498Szrj   int is_bigendian;
79*38fd1498Szrj   /* Error callback routine.  */
80*38fd1498Szrj   backtrace_error_callback error_callback;
81*38fd1498Szrj   /* Data for error_callback.  */
82*38fd1498Szrj   void *data;
83*38fd1498Szrj   /* Non-zero if we've reported an underflow error.  */
84*38fd1498Szrj   int reported_underflow;
85*38fd1498Szrj };
86*38fd1498Szrj 
87*38fd1498Szrj /* A single attribute in a DWARF abbreviation.  */
88*38fd1498Szrj 
89*38fd1498Szrj struct attr
90*38fd1498Szrj {
91*38fd1498Szrj   /* The attribute name.  */
92*38fd1498Szrj   enum dwarf_attribute name;
93*38fd1498Szrj   /* The attribute form.  */
94*38fd1498Szrj   enum dwarf_form form;
95*38fd1498Szrj };
96*38fd1498Szrj 
97*38fd1498Szrj /* A single DWARF abbreviation.  */
98*38fd1498Szrj 
99*38fd1498Szrj struct abbrev
100*38fd1498Szrj {
101*38fd1498Szrj   /* The abbrev code--the number used to refer to the abbrev.  */
102*38fd1498Szrj   uint64_t code;
103*38fd1498Szrj   /* The entry tag.  */
104*38fd1498Szrj   enum dwarf_tag tag;
105*38fd1498Szrj   /* Non-zero if this abbrev has child entries.  */
106*38fd1498Szrj   int has_children;
107*38fd1498Szrj   /* The number of attributes.  */
108*38fd1498Szrj   size_t num_attrs;
109*38fd1498Szrj   /* The attributes.  */
110*38fd1498Szrj   struct attr *attrs;
111*38fd1498Szrj };
112*38fd1498Szrj 
113*38fd1498Szrj /* The DWARF abbreviations for a compilation unit.  This structure
114*38fd1498Szrj    only exists while reading the compilation unit.  Most DWARF readers
115*38fd1498Szrj    seem to a hash table to map abbrev ID's to abbrev entries.
116*38fd1498Szrj    However, we primarily care about GCC, and GCC simply issues ID's in
117*38fd1498Szrj    numerical order starting at 1.  So we simply keep a sorted vector,
118*38fd1498Szrj    and try to just look up the code.  */
119*38fd1498Szrj 
120*38fd1498Szrj struct abbrevs
121*38fd1498Szrj {
122*38fd1498Szrj   /* The number of abbrevs in the vector.  */
123*38fd1498Szrj   size_t num_abbrevs;
124*38fd1498Szrj   /* The abbrevs, sorted by the code field.  */
125*38fd1498Szrj   struct abbrev *abbrevs;
126*38fd1498Szrj };
127*38fd1498Szrj 
128*38fd1498Szrj /* The different kinds of attribute values.  */
129*38fd1498Szrj 
130*38fd1498Szrj enum attr_val_encoding
131*38fd1498Szrj {
132*38fd1498Szrj   /* An address.  */
133*38fd1498Szrj   ATTR_VAL_ADDRESS,
134*38fd1498Szrj   /* A unsigned integer.  */
135*38fd1498Szrj   ATTR_VAL_UINT,
136*38fd1498Szrj   /* A sigd integer.  */
137*38fd1498Szrj   ATTR_VAL_SINT,
138*38fd1498Szrj   /* A string.  */
139*38fd1498Szrj   ATTR_VAL_STRING,
140*38fd1498Szrj   /* An offset to other data in the containing unit.  */
141*38fd1498Szrj   ATTR_VAL_REF_UNIT,
142*38fd1498Szrj   /* An offset to other data within the .dwarf_info section.  */
143*38fd1498Szrj   ATTR_VAL_REF_INFO,
144*38fd1498Szrj   /* An offset to data in some other section.  */
145*38fd1498Szrj   ATTR_VAL_REF_SECTION,
146*38fd1498Szrj   /* A type signature.  */
147*38fd1498Szrj   ATTR_VAL_REF_TYPE,
148*38fd1498Szrj   /* A block of data (not represented).  */
149*38fd1498Szrj   ATTR_VAL_BLOCK,
150*38fd1498Szrj   /* An expression (not represented).  */
151*38fd1498Szrj   ATTR_VAL_EXPR,
152*38fd1498Szrj };
153*38fd1498Szrj 
154*38fd1498Szrj /* An attribute value.  */
155*38fd1498Szrj 
156*38fd1498Szrj struct attr_val
157*38fd1498Szrj {
158*38fd1498Szrj   /* How the value is stored in the field u.  */
159*38fd1498Szrj   enum attr_val_encoding encoding;
160*38fd1498Szrj   union
161*38fd1498Szrj   {
162*38fd1498Szrj     /* ATTR_VAL_ADDRESS, ATTR_VAL_UINT, ATTR_VAL_REF*.  */
163*38fd1498Szrj     uint64_t uint;
164*38fd1498Szrj     /* ATTR_VAL_SINT.  */
165*38fd1498Szrj     int64_t sint;
166*38fd1498Szrj     /* ATTR_VAL_STRING.  */
167*38fd1498Szrj     const char *string;
168*38fd1498Szrj     /* ATTR_VAL_BLOCK not stored.  */
169*38fd1498Szrj   } u;
170*38fd1498Szrj };
171*38fd1498Szrj 
172*38fd1498Szrj /* The line number program header.  */
173*38fd1498Szrj 
174*38fd1498Szrj struct line_header
175*38fd1498Szrj {
176*38fd1498Szrj   /* The version of the line number information.  */
177*38fd1498Szrj   int version;
178*38fd1498Szrj   /* The minimum instruction length.  */
179*38fd1498Szrj   unsigned int min_insn_len;
180*38fd1498Szrj   /* The maximum number of ops per instruction.  */
181*38fd1498Szrj   unsigned int max_ops_per_insn;
182*38fd1498Szrj   /* The line base for special opcodes.  */
183*38fd1498Szrj   int line_base;
184*38fd1498Szrj   /* The line range for special opcodes.  */
185*38fd1498Szrj   unsigned int line_range;
186*38fd1498Szrj   /* The opcode base--the first special opcode.  */
187*38fd1498Szrj   unsigned int opcode_base;
188*38fd1498Szrj   /* Opcode lengths, indexed by opcode - 1.  */
189*38fd1498Szrj   const unsigned char *opcode_lengths;
190*38fd1498Szrj   /* The number of directory entries.  */
191*38fd1498Szrj   size_t dirs_count;
192*38fd1498Szrj   /* The directory entries.  */
193*38fd1498Szrj   const char **dirs;
194*38fd1498Szrj   /* The number of filenames.  */
195*38fd1498Szrj   size_t filenames_count;
196*38fd1498Szrj   /* The filenames.  */
197*38fd1498Szrj   const char **filenames;
198*38fd1498Szrj };
199*38fd1498Szrj 
200*38fd1498Szrj /* Map a single PC value to a file/line.  We will keep a vector of
201*38fd1498Szrj    these sorted by PC value.  Each file/line will be correct from the
202*38fd1498Szrj    PC up to the PC of the next entry if there is one.  We allocate one
203*38fd1498Szrj    extra entry at the end so that we can use bsearch.  */
204*38fd1498Szrj 
205*38fd1498Szrj struct line
206*38fd1498Szrj {
207*38fd1498Szrj   /* PC.  */
208*38fd1498Szrj   uintptr_t pc;
209*38fd1498Szrj   /* File name.  Many entries in the array are expected to point to
210*38fd1498Szrj      the same file name.  */
211*38fd1498Szrj   const char *filename;
212*38fd1498Szrj   /* Line number.  */
213*38fd1498Szrj   int lineno;
214*38fd1498Szrj   /* Index of the object in the original array read from the DWARF
215*38fd1498Szrj      section, before it has been sorted.  The index makes it possible
216*38fd1498Szrj      to use Quicksort and maintain stability.  */
217*38fd1498Szrj   int idx;
218*38fd1498Szrj };
219*38fd1498Szrj 
220*38fd1498Szrj /* A growable vector of line number information.  This is used while
221*38fd1498Szrj    reading the line numbers.  */
222*38fd1498Szrj 
223*38fd1498Szrj struct line_vector
224*38fd1498Szrj {
225*38fd1498Szrj   /* Memory.  This is an array of struct line.  */
226*38fd1498Szrj   struct backtrace_vector vec;
227*38fd1498Szrj   /* Number of valid mappings.  */
228*38fd1498Szrj   size_t count;
229*38fd1498Szrj };
230*38fd1498Szrj 
231*38fd1498Szrj /* A function described in the debug info.  */
232*38fd1498Szrj 
233*38fd1498Szrj struct function
234*38fd1498Szrj {
235*38fd1498Szrj   /* The name of the function.  */
236*38fd1498Szrj   const char *name;
237*38fd1498Szrj   /* If this is an inlined function, the filename of the call
238*38fd1498Szrj      site.  */
239*38fd1498Szrj   const char *caller_filename;
240*38fd1498Szrj   /* If this is an inlined function, the line number of the call
241*38fd1498Szrj      site.  */
242*38fd1498Szrj   int caller_lineno;
243*38fd1498Szrj   /* Map PC ranges to inlined functions.  */
244*38fd1498Szrj   struct function_addrs *function_addrs;
245*38fd1498Szrj   size_t function_addrs_count;
246*38fd1498Szrj };
247*38fd1498Szrj 
248*38fd1498Szrj /* An address range for a function.  This maps a PC value to a
249*38fd1498Szrj    specific function.  */
250*38fd1498Szrj 
251*38fd1498Szrj struct function_addrs
252*38fd1498Szrj {
253*38fd1498Szrj   /* Range is LOW <= PC < HIGH.  */
254*38fd1498Szrj   uint64_t low;
255*38fd1498Szrj   uint64_t high;
256*38fd1498Szrj   /* Function for this address range.  */
257*38fd1498Szrj   struct function *function;
258*38fd1498Szrj };
259*38fd1498Szrj 
260*38fd1498Szrj /* A growable vector of function address ranges.  */
261*38fd1498Szrj 
262*38fd1498Szrj struct function_vector
263*38fd1498Szrj {
264*38fd1498Szrj   /* Memory.  This is an array of struct function_addrs.  */
265*38fd1498Szrj   struct backtrace_vector vec;
266*38fd1498Szrj   /* Number of address ranges present.  */
267*38fd1498Szrj   size_t count;
268*38fd1498Szrj };
269*38fd1498Szrj 
270*38fd1498Szrj /* A DWARF compilation unit.  This only holds the information we need
271*38fd1498Szrj    to map a PC to a file and line.  */
272*38fd1498Szrj 
273*38fd1498Szrj struct unit
274*38fd1498Szrj {
275*38fd1498Szrj   /* The first entry for this compilation unit.  */
276*38fd1498Szrj   const unsigned char *unit_data;
277*38fd1498Szrj   /* The length of the data for this compilation unit.  */
278*38fd1498Szrj   size_t unit_data_len;
279*38fd1498Szrj   /* The offset of UNIT_DATA from the start of the information for
280*38fd1498Szrj      this compilation unit.  */
281*38fd1498Szrj   size_t unit_data_offset;
282*38fd1498Szrj   /* DWARF version.  */
283*38fd1498Szrj   int version;
284*38fd1498Szrj   /* Whether unit is DWARF64.  */
285*38fd1498Szrj   int is_dwarf64;
286*38fd1498Szrj   /* Address size.  */
287*38fd1498Szrj   int addrsize;
288*38fd1498Szrj   /* Offset into line number information.  */
289*38fd1498Szrj   off_t lineoff;
290*38fd1498Szrj   /* Primary source file.  */
291*38fd1498Szrj   const char *filename;
292*38fd1498Szrj   /* Compilation command working directory.  */
293*38fd1498Szrj   const char *comp_dir;
294*38fd1498Szrj   /* Absolute file name, only set if needed.  */
295*38fd1498Szrj   const char *abs_filename;
296*38fd1498Szrj   /* The abbreviations for this unit.  */
297*38fd1498Szrj   struct abbrevs abbrevs;
298*38fd1498Szrj 
299*38fd1498Szrj   /* The fields above this point are read in during initialization and
300*38fd1498Szrj      may be accessed freely.  The fields below this point are read in
301*38fd1498Szrj      as needed, and therefore require care, as different threads may
302*38fd1498Szrj      try to initialize them simultaneously.  */
303*38fd1498Szrj 
304*38fd1498Szrj   /* PC to line number mapping.  This is NULL if the values have not
305*38fd1498Szrj      been read.  This is (struct line *) -1 if there was an error
306*38fd1498Szrj      reading the values.  */
307*38fd1498Szrj   struct line *lines;
308*38fd1498Szrj   /* Number of entries in lines.  */
309*38fd1498Szrj   size_t lines_count;
310*38fd1498Szrj   /* PC ranges to function.  */
311*38fd1498Szrj   struct function_addrs *function_addrs;
312*38fd1498Szrj   size_t function_addrs_count;
313*38fd1498Szrj };
314*38fd1498Szrj 
315*38fd1498Szrj /* An address range for a compilation unit.  This maps a PC value to a
316*38fd1498Szrj    specific compilation unit.  Note that we invert the representation
317*38fd1498Szrj    in DWARF: instead of listing the units and attaching a list of
318*38fd1498Szrj    ranges, we list the ranges and have each one point to the unit.
319*38fd1498Szrj    This lets us do a binary search to find the unit.  */
320*38fd1498Szrj 
321*38fd1498Szrj struct unit_addrs
322*38fd1498Szrj {
323*38fd1498Szrj   /* Range is LOW <= PC < HIGH.  */
324*38fd1498Szrj   uint64_t low;
325*38fd1498Szrj   uint64_t high;
326*38fd1498Szrj   /* Compilation unit for this address range.  */
327*38fd1498Szrj   struct unit *u;
328*38fd1498Szrj };
329*38fd1498Szrj 
330*38fd1498Szrj /* A growable vector of compilation unit address ranges.  */
331*38fd1498Szrj 
332*38fd1498Szrj struct unit_addrs_vector
333*38fd1498Szrj {
334*38fd1498Szrj   /* Memory.  This is an array of struct unit_addrs.  */
335*38fd1498Szrj   struct backtrace_vector vec;
336*38fd1498Szrj   /* Number of address ranges present.  */
337*38fd1498Szrj   size_t count;
338*38fd1498Szrj };
339*38fd1498Szrj 
340*38fd1498Szrj /* The information we need to map a PC to a file and line.  */
341*38fd1498Szrj 
342*38fd1498Szrj struct dwarf_data
343*38fd1498Szrj {
344*38fd1498Szrj   /* The data for the next file we know about.  */
345*38fd1498Szrj   struct dwarf_data *next;
346*38fd1498Szrj   /* The base address for this file.  */
347*38fd1498Szrj   uintptr_t base_address;
348*38fd1498Szrj   /* A sorted list of address ranges.  */
349*38fd1498Szrj   struct unit_addrs *addrs;
350*38fd1498Szrj   /* Number of address ranges in list.  */
351*38fd1498Szrj   size_t addrs_count;
352*38fd1498Szrj   /* The unparsed .debug_info section.  */
353*38fd1498Szrj   const unsigned char *dwarf_info;
354*38fd1498Szrj   size_t dwarf_info_size;
355*38fd1498Szrj   /* The unparsed .debug_line section.  */
356*38fd1498Szrj   const unsigned char *dwarf_line;
357*38fd1498Szrj   size_t dwarf_line_size;
358*38fd1498Szrj   /* The unparsed .debug_ranges section.  */
359*38fd1498Szrj   const unsigned char *dwarf_ranges;
360*38fd1498Szrj   size_t dwarf_ranges_size;
361*38fd1498Szrj   /* The unparsed .debug_str section.  */
362*38fd1498Szrj   const unsigned char *dwarf_str;
363*38fd1498Szrj   size_t dwarf_str_size;
364*38fd1498Szrj   /* Whether the data is big-endian or not.  */
365*38fd1498Szrj   int is_bigendian;
366*38fd1498Szrj   /* A vector used for function addresses.  We keep this here so that
367*38fd1498Szrj      we can grow the vector as we read more functions.  */
368*38fd1498Szrj   struct function_vector fvec;
369*38fd1498Szrj };
370*38fd1498Szrj 
371*38fd1498Szrj /* Report an error for a DWARF buffer.  */
372*38fd1498Szrj 
373*38fd1498Szrj static void
dwarf_buf_error(struct dwarf_buf * buf,const char * msg)374*38fd1498Szrj dwarf_buf_error (struct dwarf_buf *buf, const char *msg)
375*38fd1498Szrj {
376*38fd1498Szrj   char b[200];
377*38fd1498Szrj 
378*38fd1498Szrj   snprintf (b, sizeof b, "%s in %s at %d",
379*38fd1498Szrj 	    msg, buf->name, (int) (buf->buf - buf->start));
380*38fd1498Szrj   buf->error_callback (buf->data, b, 0);
381*38fd1498Szrj }
382*38fd1498Szrj 
383*38fd1498Szrj /* Require at least COUNT bytes in BUF.  Return 1 if all is well, 0 on
384*38fd1498Szrj    error.  */
385*38fd1498Szrj 
386*38fd1498Szrj static int
require(struct dwarf_buf * buf,size_t count)387*38fd1498Szrj require (struct dwarf_buf *buf, size_t count)
388*38fd1498Szrj {
389*38fd1498Szrj   if (buf->left >= count)
390*38fd1498Szrj     return 1;
391*38fd1498Szrj 
392*38fd1498Szrj   if (!buf->reported_underflow)
393*38fd1498Szrj     {
394*38fd1498Szrj       dwarf_buf_error (buf, "DWARF underflow");
395*38fd1498Szrj       buf->reported_underflow = 1;
396*38fd1498Szrj     }
397*38fd1498Szrj 
398*38fd1498Szrj   return 0;
399*38fd1498Szrj }
400*38fd1498Szrj 
401*38fd1498Szrj /* Advance COUNT bytes in BUF.  Return 1 if all is well, 0 on
402*38fd1498Szrj    error.  */
403*38fd1498Szrj 
404*38fd1498Szrj static int
advance(struct dwarf_buf * buf,size_t count)405*38fd1498Szrj advance (struct dwarf_buf *buf, size_t count)
406*38fd1498Szrj {
407*38fd1498Szrj   if (!require (buf, count))
408*38fd1498Szrj     return 0;
409*38fd1498Szrj   buf->buf += count;
410*38fd1498Szrj   buf->left -= count;
411*38fd1498Szrj   return 1;
412*38fd1498Szrj }
413*38fd1498Szrj 
414*38fd1498Szrj /* Read one byte from BUF and advance 1 byte.  */
415*38fd1498Szrj 
416*38fd1498Szrj static unsigned char
read_byte(struct dwarf_buf * buf)417*38fd1498Szrj read_byte (struct dwarf_buf *buf)
418*38fd1498Szrj {
419*38fd1498Szrj   const unsigned char *p = buf->buf;
420*38fd1498Szrj 
421*38fd1498Szrj   if (!advance (buf, 1))
422*38fd1498Szrj     return 0;
423*38fd1498Szrj   return p[0];
424*38fd1498Szrj }
425*38fd1498Szrj 
426*38fd1498Szrj /* Read a signed char from BUF and advance 1 byte.  */
427*38fd1498Szrj 
428*38fd1498Szrj static signed char
read_sbyte(struct dwarf_buf * buf)429*38fd1498Szrj read_sbyte (struct dwarf_buf *buf)
430*38fd1498Szrj {
431*38fd1498Szrj   const unsigned char *p = buf->buf;
432*38fd1498Szrj 
433*38fd1498Szrj   if (!advance (buf, 1))
434*38fd1498Szrj     return 0;
435*38fd1498Szrj   return (*p ^ 0x80) - 0x80;
436*38fd1498Szrj }
437*38fd1498Szrj 
438*38fd1498Szrj /* Read a uint16 from BUF and advance 2 bytes.  */
439*38fd1498Szrj 
440*38fd1498Szrj static uint16_t
read_uint16(struct dwarf_buf * buf)441*38fd1498Szrj read_uint16 (struct dwarf_buf *buf)
442*38fd1498Szrj {
443*38fd1498Szrj   const unsigned char *p = buf->buf;
444*38fd1498Szrj 
445*38fd1498Szrj   if (!advance (buf, 2))
446*38fd1498Szrj     return 0;
447*38fd1498Szrj   if (buf->is_bigendian)
448*38fd1498Szrj     return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
449*38fd1498Szrj   else
450*38fd1498Szrj     return ((uint16_t) p[1] << 8) | (uint16_t) p[0];
451*38fd1498Szrj }
452*38fd1498Szrj 
453*38fd1498Szrj /* Read a uint32 from BUF and advance 4 bytes.  */
454*38fd1498Szrj 
455*38fd1498Szrj static uint32_t
read_uint32(struct dwarf_buf * buf)456*38fd1498Szrj read_uint32 (struct dwarf_buf *buf)
457*38fd1498Szrj {
458*38fd1498Szrj   const unsigned char *p = buf->buf;
459*38fd1498Szrj 
460*38fd1498Szrj   if (!advance (buf, 4))
461*38fd1498Szrj     return 0;
462*38fd1498Szrj   if (buf->is_bigendian)
463*38fd1498Szrj     return (((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16)
464*38fd1498Szrj 	    | ((uint32_t) p[2] << 8) | (uint32_t) p[3]);
465*38fd1498Szrj   else
466*38fd1498Szrj     return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16)
467*38fd1498Szrj 	    | ((uint32_t) p[1] << 8) | (uint32_t) p[0]);
468*38fd1498Szrj }
469*38fd1498Szrj 
470*38fd1498Szrj /* Read a uint64 from BUF and advance 8 bytes.  */
471*38fd1498Szrj 
472*38fd1498Szrj static uint64_t
read_uint64(struct dwarf_buf * buf)473*38fd1498Szrj read_uint64 (struct dwarf_buf *buf)
474*38fd1498Szrj {
475*38fd1498Szrj   const unsigned char *p = buf->buf;
476*38fd1498Szrj 
477*38fd1498Szrj   if (!advance (buf, 8))
478*38fd1498Szrj     return 0;
479*38fd1498Szrj   if (buf->is_bigendian)
480*38fd1498Szrj     return (((uint64_t) p[0] << 56) | ((uint64_t) p[1] << 48)
481*38fd1498Szrj 	    | ((uint64_t) p[2] << 40) | ((uint64_t) p[3] << 32)
482*38fd1498Szrj 	    | ((uint64_t) p[4] << 24) | ((uint64_t) p[5] << 16)
483*38fd1498Szrj 	    | ((uint64_t) p[6] << 8) | (uint64_t) p[7]);
484*38fd1498Szrj   else
485*38fd1498Szrj     return (((uint64_t) p[7] << 56) | ((uint64_t) p[6] << 48)
486*38fd1498Szrj 	    | ((uint64_t) p[5] << 40) | ((uint64_t) p[4] << 32)
487*38fd1498Szrj 	    | ((uint64_t) p[3] << 24) | ((uint64_t) p[2] << 16)
488*38fd1498Szrj 	    | ((uint64_t) p[1] << 8) | (uint64_t) p[0]);
489*38fd1498Szrj }
490*38fd1498Szrj 
491*38fd1498Szrj /* Read an offset from BUF and advance the appropriate number of
492*38fd1498Szrj    bytes.  */
493*38fd1498Szrj 
494*38fd1498Szrj static uint64_t
read_offset(struct dwarf_buf * buf,int is_dwarf64)495*38fd1498Szrj read_offset (struct dwarf_buf *buf, int is_dwarf64)
496*38fd1498Szrj {
497*38fd1498Szrj   if (is_dwarf64)
498*38fd1498Szrj     return read_uint64 (buf);
499*38fd1498Szrj   else
500*38fd1498Szrj     return read_uint32 (buf);
501*38fd1498Szrj }
502*38fd1498Szrj 
503*38fd1498Szrj /* Read an address from BUF and advance the appropriate number of
504*38fd1498Szrj    bytes.  */
505*38fd1498Szrj 
506*38fd1498Szrj static uint64_t
read_address(struct dwarf_buf * buf,int addrsize)507*38fd1498Szrj read_address (struct dwarf_buf *buf, int addrsize)
508*38fd1498Szrj {
509*38fd1498Szrj   switch (addrsize)
510*38fd1498Szrj     {
511*38fd1498Szrj     case 1:
512*38fd1498Szrj       return read_byte (buf);
513*38fd1498Szrj     case 2:
514*38fd1498Szrj       return read_uint16 (buf);
515*38fd1498Szrj     case 4:
516*38fd1498Szrj       return read_uint32 (buf);
517*38fd1498Szrj     case 8:
518*38fd1498Szrj       return read_uint64 (buf);
519*38fd1498Szrj     default:
520*38fd1498Szrj       dwarf_buf_error (buf, "unrecognized address size");
521*38fd1498Szrj       return 0;
522*38fd1498Szrj     }
523*38fd1498Szrj }
524*38fd1498Szrj 
525*38fd1498Szrj /* Return whether a value is the highest possible address, given the
526*38fd1498Szrj    address size.  */
527*38fd1498Szrj 
528*38fd1498Szrj static int
is_highest_address(uint64_t address,int addrsize)529*38fd1498Szrj is_highest_address (uint64_t address, int addrsize)
530*38fd1498Szrj {
531*38fd1498Szrj   switch (addrsize)
532*38fd1498Szrj     {
533*38fd1498Szrj     case 1:
534*38fd1498Szrj       return address == (unsigned char) -1;
535*38fd1498Szrj     case 2:
536*38fd1498Szrj       return address == (uint16_t) -1;
537*38fd1498Szrj     case 4:
538*38fd1498Szrj       return address == (uint32_t) -1;
539*38fd1498Szrj     case 8:
540*38fd1498Szrj       return address == (uint64_t) -1;
541*38fd1498Szrj     default:
542*38fd1498Szrj       return 0;
543*38fd1498Szrj     }
544*38fd1498Szrj }
545*38fd1498Szrj 
546*38fd1498Szrj /* Read an unsigned LEB128 number.  */
547*38fd1498Szrj 
548*38fd1498Szrj static uint64_t
read_uleb128(struct dwarf_buf * buf)549*38fd1498Szrj read_uleb128 (struct dwarf_buf *buf)
550*38fd1498Szrj {
551*38fd1498Szrj   uint64_t ret;
552*38fd1498Szrj   unsigned int shift;
553*38fd1498Szrj   int overflow;
554*38fd1498Szrj   unsigned char b;
555*38fd1498Szrj 
556*38fd1498Szrj   ret = 0;
557*38fd1498Szrj   shift = 0;
558*38fd1498Szrj   overflow = 0;
559*38fd1498Szrj   do
560*38fd1498Szrj     {
561*38fd1498Szrj       const unsigned char *p;
562*38fd1498Szrj 
563*38fd1498Szrj       p = buf->buf;
564*38fd1498Szrj       if (!advance (buf, 1))
565*38fd1498Szrj 	return 0;
566*38fd1498Szrj       b = *p;
567*38fd1498Szrj       if (shift < 64)
568*38fd1498Szrj 	ret |= ((uint64_t) (b & 0x7f)) << shift;
569*38fd1498Szrj       else if (!overflow)
570*38fd1498Szrj 	{
571*38fd1498Szrj 	  dwarf_buf_error (buf, "LEB128 overflows uint64_t");
572*38fd1498Szrj 	  overflow = 1;
573*38fd1498Szrj 	}
574*38fd1498Szrj       shift += 7;
575*38fd1498Szrj     }
576*38fd1498Szrj   while ((b & 0x80) != 0);
577*38fd1498Szrj 
578*38fd1498Szrj   return ret;
579*38fd1498Szrj }
580*38fd1498Szrj 
581*38fd1498Szrj /* Read a signed LEB128 number.  */
582*38fd1498Szrj 
583*38fd1498Szrj static int64_t
read_sleb128(struct dwarf_buf * buf)584*38fd1498Szrj read_sleb128 (struct dwarf_buf *buf)
585*38fd1498Szrj {
586*38fd1498Szrj   uint64_t val;
587*38fd1498Szrj   unsigned int shift;
588*38fd1498Szrj   int overflow;
589*38fd1498Szrj   unsigned char b;
590*38fd1498Szrj 
591*38fd1498Szrj   val = 0;
592*38fd1498Szrj   shift = 0;
593*38fd1498Szrj   overflow = 0;
594*38fd1498Szrj   do
595*38fd1498Szrj     {
596*38fd1498Szrj       const unsigned char *p;
597*38fd1498Szrj 
598*38fd1498Szrj       p = buf->buf;
599*38fd1498Szrj       if (!advance (buf, 1))
600*38fd1498Szrj 	return 0;
601*38fd1498Szrj       b = *p;
602*38fd1498Szrj       if (shift < 64)
603*38fd1498Szrj 	val |= ((uint64_t) (b & 0x7f)) << shift;
604*38fd1498Szrj       else if (!overflow)
605*38fd1498Szrj 	{
606*38fd1498Szrj 	  dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
607*38fd1498Szrj 	  overflow = 1;
608*38fd1498Szrj 	}
609*38fd1498Szrj       shift += 7;
610*38fd1498Szrj     }
611*38fd1498Szrj   while ((b & 0x80) != 0);
612*38fd1498Szrj 
613*38fd1498Szrj   if ((b & 0x40) != 0 && shift < 64)
614*38fd1498Szrj     val |= ((uint64_t) -1) << shift;
615*38fd1498Szrj 
616*38fd1498Szrj   return (int64_t) val;
617*38fd1498Szrj }
618*38fd1498Szrj 
619*38fd1498Szrj /* Return the length of an LEB128 number.  */
620*38fd1498Szrj 
621*38fd1498Szrj static size_t
leb128_len(const unsigned char * p)622*38fd1498Szrj leb128_len (const unsigned char *p)
623*38fd1498Szrj {
624*38fd1498Szrj   size_t ret;
625*38fd1498Szrj 
626*38fd1498Szrj   ret = 1;
627*38fd1498Szrj   while ((*p & 0x80) != 0)
628*38fd1498Szrj     {
629*38fd1498Szrj       ++p;
630*38fd1498Szrj       ++ret;
631*38fd1498Szrj     }
632*38fd1498Szrj   return ret;
633*38fd1498Szrj }
634*38fd1498Szrj 
635*38fd1498Szrj /* Free an abbreviations structure.  */
636*38fd1498Szrj 
637*38fd1498Szrj static void
free_abbrevs(struct backtrace_state * state,struct abbrevs * abbrevs,backtrace_error_callback error_callback,void * data)638*38fd1498Szrj free_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs,
639*38fd1498Szrj 	      backtrace_error_callback error_callback, void *data)
640*38fd1498Szrj {
641*38fd1498Szrj   size_t i;
642*38fd1498Szrj 
643*38fd1498Szrj   for (i = 0; i < abbrevs->num_abbrevs; ++i)
644*38fd1498Szrj     backtrace_free (state, abbrevs->abbrevs[i].attrs,
645*38fd1498Szrj 		    abbrevs->abbrevs[i].num_attrs * sizeof (struct attr),
646*38fd1498Szrj 		    error_callback, data);
647*38fd1498Szrj   backtrace_free (state, abbrevs->abbrevs,
648*38fd1498Szrj 		  abbrevs->num_abbrevs * sizeof (struct abbrev),
649*38fd1498Szrj 		  error_callback, data);
650*38fd1498Szrj   abbrevs->num_abbrevs = 0;
651*38fd1498Szrj   abbrevs->abbrevs = NULL;
652*38fd1498Szrj }
653*38fd1498Szrj 
654*38fd1498Szrj /* Read an attribute value.  Returns 1 on success, 0 on failure.  If
655*38fd1498Szrj    the value can be represented as a uint64_t, sets *VAL and sets
656*38fd1498Szrj    *IS_VALID to 1.  We don't try to store the value of other attribute
657*38fd1498Szrj    forms, because we don't care about them.  */
658*38fd1498Szrj 
659*38fd1498Szrj static int
read_attribute(enum dwarf_form form,struct dwarf_buf * buf,int is_dwarf64,int version,int addrsize,const unsigned char * dwarf_str,size_t dwarf_str_size,struct attr_val * val)660*38fd1498Szrj read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
661*38fd1498Szrj 		int is_dwarf64, int version, int addrsize,
662*38fd1498Szrj 		const unsigned char *dwarf_str, size_t dwarf_str_size,
663*38fd1498Szrj 		struct attr_val *val)
664*38fd1498Szrj {
665*38fd1498Szrj   /* Avoid warnings about val.u.FIELD may be used uninitialized if
666*38fd1498Szrj      this function is inlined.  The warnings aren't valid but can
667*38fd1498Szrj      occur because the different fields are set and used
668*38fd1498Szrj      conditionally.  */
669*38fd1498Szrj   memset (val, 0, sizeof *val);
670*38fd1498Szrj 
671*38fd1498Szrj   switch (form)
672*38fd1498Szrj     {
673*38fd1498Szrj     case DW_FORM_addr:
674*38fd1498Szrj       val->encoding = ATTR_VAL_ADDRESS;
675*38fd1498Szrj       val->u.uint = read_address (buf, addrsize);
676*38fd1498Szrj       return 1;
677*38fd1498Szrj     case DW_FORM_block2:
678*38fd1498Szrj       val->encoding = ATTR_VAL_BLOCK;
679*38fd1498Szrj       return advance (buf, read_uint16 (buf));
680*38fd1498Szrj     case DW_FORM_block4:
681*38fd1498Szrj       val->encoding = ATTR_VAL_BLOCK;
682*38fd1498Szrj       return advance (buf, read_uint32 (buf));
683*38fd1498Szrj     case DW_FORM_data2:
684*38fd1498Szrj       val->encoding = ATTR_VAL_UINT;
685*38fd1498Szrj       val->u.uint = read_uint16 (buf);
686*38fd1498Szrj       return 1;
687*38fd1498Szrj     case DW_FORM_data4:
688*38fd1498Szrj       val->encoding = ATTR_VAL_UINT;
689*38fd1498Szrj       val->u.uint = read_uint32 (buf);
690*38fd1498Szrj       return 1;
691*38fd1498Szrj     case DW_FORM_data8:
692*38fd1498Szrj       val->encoding = ATTR_VAL_UINT;
693*38fd1498Szrj       val->u.uint = read_uint64 (buf);
694*38fd1498Szrj       return 1;
695*38fd1498Szrj     case DW_FORM_string:
696*38fd1498Szrj       val->encoding = ATTR_VAL_STRING;
697*38fd1498Szrj       val->u.string = (const char *) buf->buf;
698*38fd1498Szrj       return advance (buf, strnlen ((const char *) buf->buf, buf->left) + 1);
699*38fd1498Szrj     case DW_FORM_block:
700*38fd1498Szrj       val->encoding = ATTR_VAL_BLOCK;
701*38fd1498Szrj       return advance (buf, read_uleb128 (buf));
702*38fd1498Szrj     case DW_FORM_block1:
703*38fd1498Szrj       val->encoding = ATTR_VAL_BLOCK;
704*38fd1498Szrj       return advance (buf, read_byte (buf));
705*38fd1498Szrj     case DW_FORM_data1:
706*38fd1498Szrj       val->encoding = ATTR_VAL_UINT;
707*38fd1498Szrj       val->u.uint = read_byte (buf);
708*38fd1498Szrj       return 1;
709*38fd1498Szrj     case DW_FORM_flag:
710*38fd1498Szrj       val->encoding = ATTR_VAL_UINT;
711*38fd1498Szrj       val->u.uint = read_byte (buf);
712*38fd1498Szrj       return 1;
713*38fd1498Szrj     case DW_FORM_sdata:
714*38fd1498Szrj       val->encoding = ATTR_VAL_SINT;
715*38fd1498Szrj       val->u.sint = read_sleb128 (buf);
716*38fd1498Szrj       return 1;
717*38fd1498Szrj     case DW_FORM_strp:
718*38fd1498Szrj       {
719*38fd1498Szrj 	uint64_t offset;
720*38fd1498Szrj 
721*38fd1498Szrj 	offset = read_offset (buf, is_dwarf64);
722*38fd1498Szrj 	if (offset >= dwarf_str_size)
723*38fd1498Szrj 	  {
724*38fd1498Szrj 	    dwarf_buf_error (buf, "DW_FORM_strp out of range");
725*38fd1498Szrj 	    return 0;
726*38fd1498Szrj 	  }
727*38fd1498Szrj 	val->encoding = ATTR_VAL_STRING;
728*38fd1498Szrj 	val->u.string = (const char *) dwarf_str + offset;
729*38fd1498Szrj 	return 1;
730*38fd1498Szrj       }
731*38fd1498Szrj     case DW_FORM_udata:
732*38fd1498Szrj       val->encoding = ATTR_VAL_UINT;
733*38fd1498Szrj       val->u.uint = read_uleb128 (buf);
734*38fd1498Szrj       return 1;
735*38fd1498Szrj     case DW_FORM_ref_addr:
736*38fd1498Szrj       val->encoding = ATTR_VAL_REF_INFO;
737*38fd1498Szrj       if (version == 2)
738*38fd1498Szrj 	val->u.uint = read_address (buf, addrsize);
739*38fd1498Szrj       else
740*38fd1498Szrj 	val->u.uint = read_offset (buf, is_dwarf64);
741*38fd1498Szrj       return 1;
742*38fd1498Szrj     case DW_FORM_ref1:
743*38fd1498Szrj       val->encoding = ATTR_VAL_REF_UNIT;
744*38fd1498Szrj       val->u.uint = read_byte (buf);
745*38fd1498Szrj       return 1;
746*38fd1498Szrj     case DW_FORM_ref2:
747*38fd1498Szrj       val->encoding = ATTR_VAL_REF_UNIT;
748*38fd1498Szrj       val->u.uint = read_uint16 (buf);
749*38fd1498Szrj       return 1;
750*38fd1498Szrj     case DW_FORM_ref4:
751*38fd1498Szrj       val->encoding = ATTR_VAL_REF_UNIT;
752*38fd1498Szrj       val->u.uint = read_uint32 (buf);
753*38fd1498Szrj       return 1;
754*38fd1498Szrj     case DW_FORM_ref8:
755*38fd1498Szrj       val->encoding = ATTR_VAL_REF_UNIT;
756*38fd1498Szrj       val->u.uint = read_uint64 (buf);
757*38fd1498Szrj       return 1;
758*38fd1498Szrj     case DW_FORM_ref_udata:
759*38fd1498Szrj       val->encoding = ATTR_VAL_REF_UNIT;
760*38fd1498Szrj       val->u.uint = read_uleb128 (buf);
761*38fd1498Szrj       return 1;
762*38fd1498Szrj     case DW_FORM_indirect:
763*38fd1498Szrj       {
764*38fd1498Szrj 	uint64_t form;
765*38fd1498Szrj 
766*38fd1498Szrj 	form = read_uleb128 (buf);
767*38fd1498Szrj 	return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
768*38fd1498Szrj 			       version, addrsize, dwarf_str, dwarf_str_size,
769*38fd1498Szrj 			       val);
770*38fd1498Szrj       }
771*38fd1498Szrj     case DW_FORM_sec_offset:
772*38fd1498Szrj       val->encoding = ATTR_VAL_REF_SECTION;
773*38fd1498Szrj       val->u.uint = read_offset (buf, is_dwarf64);
774*38fd1498Szrj       return 1;
775*38fd1498Szrj     case DW_FORM_exprloc:
776*38fd1498Szrj       val->encoding = ATTR_VAL_EXPR;
777*38fd1498Szrj       return advance (buf, read_uleb128 (buf));
778*38fd1498Szrj     case DW_FORM_flag_present:
779*38fd1498Szrj       val->encoding = ATTR_VAL_UINT;
780*38fd1498Szrj       val->u.uint = 1;
781*38fd1498Szrj       return 1;
782*38fd1498Szrj     case DW_FORM_ref_sig8:
783*38fd1498Szrj       val->encoding = ATTR_VAL_REF_TYPE;
784*38fd1498Szrj       val->u.uint = read_uint64 (buf);
785*38fd1498Szrj       return 1;
786*38fd1498Szrj     case DW_FORM_GNU_addr_index:
787*38fd1498Szrj       val->encoding = ATTR_VAL_REF_SECTION;
788*38fd1498Szrj       val->u.uint = read_uleb128 (buf);
789*38fd1498Szrj       return 1;
790*38fd1498Szrj     case DW_FORM_GNU_str_index:
791*38fd1498Szrj       val->encoding = ATTR_VAL_REF_SECTION;
792*38fd1498Szrj       val->u.uint = read_uleb128 (buf);
793*38fd1498Szrj       return 1;
794*38fd1498Szrj     case DW_FORM_GNU_ref_alt:
795*38fd1498Szrj       val->encoding = ATTR_VAL_REF_SECTION;
796*38fd1498Szrj       val->u.uint = read_offset (buf, is_dwarf64);
797*38fd1498Szrj       return 1;
798*38fd1498Szrj     case DW_FORM_GNU_strp_alt:
799*38fd1498Szrj       val->encoding = ATTR_VAL_REF_SECTION;
800*38fd1498Szrj       val->u.uint = read_offset (buf, is_dwarf64);
801*38fd1498Szrj       return 1;
802*38fd1498Szrj     default:
803*38fd1498Szrj       dwarf_buf_error (buf, "unrecognized DWARF form");
804*38fd1498Szrj       return 0;
805*38fd1498Szrj     }
806*38fd1498Szrj }
807*38fd1498Szrj 
808*38fd1498Szrj /* Compare function_addrs for qsort.  When ranges are nested, make the
809*38fd1498Szrj    smallest one sort last.  */
810*38fd1498Szrj 
811*38fd1498Szrj static int
function_addrs_compare(const void * v1,const void * v2)812*38fd1498Szrj function_addrs_compare (const void *v1, const void *v2)
813*38fd1498Szrj {
814*38fd1498Szrj   const struct function_addrs *a1 = (const struct function_addrs *) v1;
815*38fd1498Szrj   const struct function_addrs *a2 = (const struct function_addrs *) v2;
816*38fd1498Szrj 
817*38fd1498Szrj   if (a1->low < a2->low)
818*38fd1498Szrj     return -1;
819*38fd1498Szrj   if (a1->low > a2->low)
820*38fd1498Szrj     return 1;
821*38fd1498Szrj   if (a1->high < a2->high)
822*38fd1498Szrj     return 1;
823*38fd1498Szrj   if (a1->high > a2->high)
824*38fd1498Szrj     return -1;
825*38fd1498Szrj   return strcmp (a1->function->name, a2->function->name);
826*38fd1498Szrj }
827*38fd1498Szrj 
828*38fd1498Szrj /* Compare a PC against a function_addrs for bsearch.  Note that if
829*38fd1498Szrj    there are multiple ranges containing PC, which one will be returned
830*38fd1498Szrj    is unpredictable.  We compensate for that in dwarf_fileline.  */
831*38fd1498Szrj 
832*38fd1498Szrj static int
function_addrs_search(const void * vkey,const void * ventry)833*38fd1498Szrj function_addrs_search (const void *vkey, const void *ventry)
834*38fd1498Szrj {
835*38fd1498Szrj   const uintptr_t *key = (const uintptr_t *) vkey;
836*38fd1498Szrj   const struct function_addrs *entry = (const struct function_addrs *) ventry;
837*38fd1498Szrj   uintptr_t pc;
838*38fd1498Szrj 
839*38fd1498Szrj   pc = *key;
840*38fd1498Szrj   if (pc < entry->low)
841*38fd1498Szrj     return -1;
842*38fd1498Szrj   else if (pc >= entry->high)
843*38fd1498Szrj     return 1;
844*38fd1498Szrj   else
845*38fd1498Szrj     return 0;
846*38fd1498Szrj }
847*38fd1498Szrj 
848*38fd1498Szrj /* Add a new compilation unit address range to a vector.  Returns 1 on
849*38fd1498Szrj    success, 0 on failure.  */
850*38fd1498Szrj 
851*38fd1498Szrj static int
add_unit_addr(struct backtrace_state * state,uintptr_t base_address,struct unit_addrs addrs,backtrace_error_callback error_callback,void * data,struct unit_addrs_vector * vec)852*38fd1498Szrj add_unit_addr (struct backtrace_state *state, uintptr_t base_address,
853*38fd1498Szrj 	       struct unit_addrs addrs,
854*38fd1498Szrj 	       backtrace_error_callback error_callback, void *data,
855*38fd1498Szrj 	       struct unit_addrs_vector *vec)
856*38fd1498Szrj {
857*38fd1498Szrj   struct unit_addrs *p;
858*38fd1498Szrj 
859*38fd1498Szrj   /* Add in the base address of the module here, so that we can look
860*38fd1498Szrj      up the PC directly.  */
861*38fd1498Szrj   addrs.low += base_address;
862*38fd1498Szrj   addrs.high += base_address;
863*38fd1498Szrj 
864*38fd1498Szrj   /* Try to merge with the last entry.  */
865*38fd1498Szrj   if (vec->count > 0)
866*38fd1498Szrj     {
867*38fd1498Szrj       p = (struct unit_addrs *) vec->vec.base + (vec->count - 1);
868*38fd1498Szrj       if ((addrs.low == p->high || addrs.low == p->high + 1)
869*38fd1498Szrj 	  && addrs.u == p->u)
870*38fd1498Szrj 	{
871*38fd1498Szrj 	  if (addrs.high > p->high)
872*38fd1498Szrj 	    p->high = addrs.high;
873*38fd1498Szrj 	  return 1;
874*38fd1498Szrj 	}
875*38fd1498Szrj     }
876*38fd1498Szrj 
877*38fd1498Szrj   p = ((struct unit_addrs *)
878*38fd1498Szrj        backtrace_vector_grow (state, sizeof (struct unit_addrs),
879*38fd1498Szrj 			      error_callback, data, &vec->vec));
880*38fd1498Szrj   if (p == NULL)
881*38fd1498Szrj     return 0;
882*38fd1498Szrj 
883*38fd1498Szrj   *p = addrs;
884*38fd1498Szrj   ++vec->count;
885*38fd1498Szrj   return 1;
886*38fd1498Szrj }
887*38fd1498Szrj 
888*38fd1498Szrj /* Free a unit address vector.  */
889*38fd1498Szrj 
890*38fd1498Szrj static void
free_unit_addrs_vector(struct backtrace_state * state,struct unit_addrs_vector * vec,backtrace_error_callback error_callback,void * data)891*38fd1498Szrj free_unit_addrs_vector (struct backtrace_state *state,
892*38fd1498Szrj 			struct unit_addrs_vector *vec,
893*38fd1498Szrj 			backtrace_error_callback error_callback, void *data)
894*38fd1498Szrj {
895*38fd1498Szrj   struct unit_addrs *addrs;
896*38fd1498Szrj   size_t i;
897*38fd1498Szrj 
898*38fd1498Szrj   addrs = (struct unit_addrs *) vec->vec.base;
899*38fd1498Szrj   for (i = 0; i < vec->count; ++i)
900*38fd1498Szrj     free_abbrevs (state, &addrs[i].u->abbrevs, error_callback, data);
901*38fd1498Szrj }
902*38fd1498Szrj 
903*38fd1498Szrj /* Compare unit_addrs for qsort.  When ranges are nested, make the
904*38fd1498Szrj    smallest one sort last.  */
905*38fd1498Szrj 
906*38fd1498Szrj static int
unit_addrs_compare(const void * v1,const void * v2)907*38fd1498Szrj unit_addrs_compare (const void *v1, const void *v2)
908*38fd1498Szrj {
909*38fd1498Szrj   const struct unit_addrs *a1 = (const struct unit_addrs *) v1;
910*38fd1498Szrj   const struct unit_addrs *a2 = (const struct unit_addrs *) v2;
911*38fd1498Szrj 
912*38fd1498Szrj   if (a1->low < a2->low)
913*38fd1498Szrj     return -1;
914*38fd1498Szrj   if (a1->low > a2->low)
915*38fd1498Szrj     return 1;
916*38fd1498Szrj   if (a1->high < a2->high)
917*38fd1498Szrj     return 1;
918*38fd1498Szrj   if (a1->high > a2->high)
919*38fd1498Szrj     return -1;
920*38fd1498Szrj   if (a1->u->lineoff < a2->u->lineoff)
921*38fd1498Szrj     return -1;
922*38fd1498Szrj   if (a1->u->lineoff > a2->u->lineoff)
923*38fd1498Szrj     return 1;
924*38fd1498Szrj   return 0;
925*38fd1498Szrj }
926*38fd1498Szrj 
927*38fd1498Szrj /* Compare a PC against a unit_addrs for bsearch.  Note that if there
928*38fd1498Szrj    are multiple ranges containing PC, which one will be returned is
929*38fd1498Szrj    unpredictable.  We compensate for that in dwarf_fileline.  */
930*38fd1498Szrj 
931*38fd1498Szrj static int
unit_addrs_search(const void * vkey,const void * ventry)932*38fd1498Szrj unit_addrs_search (const void *vkey, const void *ventry)
933*38fd1498Szrj {
934*38fd1498Szrj   const uintptr_t *key = (const uintptr_t *) vkey;
935*38fd1498Szrj   const struct unit_addrs *entry = (const struct unit_addrs *) ventry;
936*38fd1498Szrj   uintptr_t pc;
937*38fd1498Szrj 
938*38fd1498Szrj   pc = *key;
939*38fd1498Szrj   if (pc < entry->low)
940*38fd1498Szrj     return -1;
941*38fd1498Szrj   else if (pc >= entry->high)
942*38fd1498Szrj     return 1;
943*38fd1498Szrj   else
944*38fd1498Szrj     return 0;
945*38fd1498Szrj }
946*38fd1498Szrj 
947*38fd1498Szrj /* Sort the line vector by PC.  We want a stable sort here to maintain
948*38fd1498Szrj    the order of lines for the same PC values.  Since the sequence is
949*38fd1498Szrj    being sorted in place, their addresses cannot be relied on to
950*38fd1498Szrj    maintain stability.  That is the purpose of the index member.  */
951*38fd1498Szrj 
952*38fd1498Szrj static int
line_compare(const void * v1,const void * v2)953*38fd1498Szrj line_compare (const void *v1, const void *v2)
954*38fd1498Szrj {
955*38fd1498Szrj   const struct line *ln1 = (const struct line *) v1;
956*38fd1498Szrj   const struct line *ln2 = (const struct line *) v2;
957*38fd1498Szrj 
958*38fd1498Szrj   if (ln1->pc < ln2->pc)
959*38fd1498Szrj     return -1;
960*38fd1498Szrj   else if (ln1->pc > ln2->pc)
961*38fd1498Szrj     return 1;
962*38fd1498Szrj   else if (ln1->idx < ln2->idx)
963*38fd1498Szrj     return -1;
964*38fd1498Szrj   else if (ln1->idx > ln2->idx)
965*38fd1498Szrj     return 1;
966*38fd1498Szrj   else
967*38fd1498Szrj     return 0;
968*38fd1498Szrj }
969*38fd1498Szrj 
970*38fd1498Szrj /* Find a PC in a line vector.  We always allocate an extra entry at
971*38fd1498Szrj    the end of the lines vector, so that this routine can safely look
972*38fd1498Szrj    at the next entry.  Note that when there are multiple mappings for
973*38fd1498Szrj    the same PC value, this will return the last one.  */
974*38fd1498Szrj 
975*38fd1498Szrj static int
line_search(const void * vkey,const void * ventry)976*38fd1498Szrj line_search (const void *vkey, const void *ventry)
977*38fd1498Szrj {
978*38fd1498Szrj   const uintptr_t *key = (const uintptr_t *) vkey;
979*38fd1498Szrj   const struct line *entry = (const struct line *) ventry;
980*38fd1498Szrj   uintptr_t pc;
981*38fd1498Szrj 
982*38fd1498Szrj   pc = *key;
983*38fd1498Szrj   if (pc < entry->pc)
984*38fd1498Szrj     return -1;
985*38fd1498Szrj   else if (pc >= (entry + 1)->pc)
986*38fd1498Szrj     return 1;
987*38fd1498Szrj   else
988*38fd1498Szrj     return 0;
989*38fd1498Szrj }
990*38fd1498Szrj 
991*38fd1498Szrj /* Sort the abbrevs by the abbrev code.  This function is passed to
992*38fd1498Szrj    both qsort and bsearch.  */
993*38fd1498Szrj 
994*38fd1498Szrj static int
abbrev_compare(const void * v1,const void * v2)995*38fd1498Szrj abbrev_compare (const void *v1, const void *v2)
996*38fd1498Szrj {
997*38fd1498Szrj   const struct abbrev *a1 = (const struct abbrev *) v1;
998*38fd1498Szrj   const struct abbrev *a2 = (const struct abbrev *) v2;
999*38fd1498Szrj 
1000*38fd1498Szrj   if (a1->code < a2->code)
1001*38fd1498Szrj     return -1;
1002*38fd1498Szrj   else if (a1->code > a2->code)
1003*38fd1498Szrj     return 1;
1004*38fd1498Szrj   else
1005*38fd1498Szrj     {
1006*38fd1498Szrj       /* This really shouldn't happen.  It means there are two
1007*38fd1498Szrj 	 different abbrevs with the same code, and that means we don't
1008*38fd1498Szrj 	 know which one lookup_abbrev should return.  */
1009*38fd1498Szrj       return 0;
1010*38fd1498Szrj     }
1011*38fd1498Szrj }
1012*38fd1498Szrj 
1013*38fd1498Szrj /* Read the abbreviation table for a compilation unit.  Returns 1 on
1014*38fd1498Szrj    success, 0 on failure.  */
1015*38fd1498Szrj 
1016*38fd1498Szrj 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)1017*38fd1498Szrj read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
1018*38fd1498Szrj 	      const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
1019*38fd1498Szrj 	      int is_bigendian, backtrace_error_callback error_callback,
1020*38fd1498Szrj 	      void *data, struct abbrevs *abbrevs)
1021*38fd1498Szrj {
1022*38fd1498Szrj   struct dwarf_buf abbrev_buf;
1023*38fd1498Szrj   struct dwarf_buf count_buf;
1024*38fd1498Szrj   size_t num_abbrevs;
1025*38fd1498Szrj 
1026*38fd1498Szrj   abbrevs->num_abbrevs = 0;
1027*38fd1498Szrj   abbrevs->abbrevs = NULL;
1028*38fd1498Szrj 
1029*38fd1498Szrj   if (abbrev_offset >= dwarf_abbrev_size)
1030*38fd1498Szrj     {
1031*38fd1498Szrj       error_callback (data, "abbrev offset out of range", 0);
1032*38fd1498Szrj       return 0;
1033*38fd1498Szrj     }
1034*38fd1498Szrj 
1035*38fd1498Szrj   abbrev_buf.name = ".debug_abbrev";
1036*38fd1498Szrj   abbrev_buf.start = dwarf_abbrev;
1037*38fd1498Szrj   abbrev_buf.buf = dwarf_abbrev + abbrev_offset;
1038*38fd1498Szrj   abbrev_buf.left = dwarf_abbrev_size - abbrev_offset;
1039*38fd1498Szrj   abbrev_buf.is_bigendian = is_bigendian;
1040*38fd1498Szrj   abbrev_buf.error_callback = error_callback;
1041*38fd1498Szrj   abbrev_buf.data = data;
1042*38fd1498Szrj   abbrev_buf.reported_underflow = 0;
1043*38fd1498Szrj 
1044*38fd1498Szrj   /* Count the number of abbrevs in this list.  */
1045*38fd1498Szrj 
1046*38fd1498Szrj   count_buf = abbrev_buf;
1047*38fd1498Szrj   num_abbrevs = 0;
1048*38fd1498Szrj   while (read_uleb128 (&count_buf) != 0)
1049*38fd1498Szrj     {
1050*38fd1498Szrj       if (count_buf.reported_underflow)
1051*38fd1498Szrj 	return 0;
1052*38fd1498Szrj       ++num_abbrevs;
1053*38fd1498Szrj       // Skip tag.
1054*38fd1498Szrj       read_uleb128 (&count_buf);
1055*38fd1498Szrj       // Skip has_children.
1056*38fd1498Szrj       read_byte (&count_buf);
1057*38fd1498Szrj       // Skip attributes.
1058*38fd1498Szrj       while (read_uleb128 (&count_buf) != 0)
1059*38fd1498Szrj 	read_uleb128 (&count_buf);
1060*38fd1498Szrj       // Skip form of last attribute.
1061*38fd1498Szrj       read_uleb128 (&count_buf);
1062*38fd1498Szrj     }
1063*38fd1498Szrj 
1064*38fd1498Szrj   if (count_buf.reported_underflow)
1065*38fd1498Szrj     return 0;
1066*38fd1498Szrj 
1067*38fd1498Szrj   if (num_abbrevs == 0)
1068*38fd1498Szrj     return 1;
1069*38fd1498Szrj 
1070*38fd1498Szrj   abbrevs->num_abbrevs = num_abbrevs;
1071*38fd1498Szrj   abbrevs->abbrevs = ((struct abbrev *)
1072*38fd1498Szrj 		      backtrace_alloc (state,
1073*38fd1498Szrj 				       num_abbrevs * sizeof (struct abbrev),
1074*38fd1498Szrj 				       error_callback, data));
1075*38fd1498Szrj   if (abbrevs->abbrevs == NULL)
1076*38fd1498Szrj     return 0;
1077*38fd1498Szrj   memset (abbrevs->abbrevs, 0, num_abbrevs * sizeof (struct abbrev));
1078*38fd1498Szrj 
1079*38fd1498Szrj   num_abbrevs = 0;
1080*38fd1498Szrj   while (1)
1081*38fd1498Szrj     {
1082*38fd1498Szrj       uint64_t code;
1083*38fd1498Szrj       struct abbrev a;
1084*38fd1498Szrj       size_t num_attrs;
1085*38fd1498Szrj       struct attr *attrs;
1086*38fd1498Szrj 
1087*38fd1498Szrj       if (abbrev_buf.reported_underflow)
1088*38fd1498Szrj 	goto fail;
1089*38fd1498Szrj 
1090*38fd1498Szrj       code = read_uleb128 (&abbrev_buf);
1091*38fd1498Szrj       if (code == 0)
1092*38fd1498Szrj 	break;
1093*38fd1498Szrj 
1094*38fd1498Szrj       a.code = code;
1095*38fd1498Szrj       a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf);
1096*38fd1498Szrj       a.has_children = read_byte (&abbrev_buf);
1097*38fd1498Szrj 
1098*38fd1498Szrj       count_buf = abbrev_buf;
1099*38fd1498Szrj       num_attrs = 0;
1100*38fd1498Szrj       while (read_uleb128 (&count_buf) != 0)
1101*38fd1498Szrj 	{
1102*38fd1498Szrj 	  ++num_attrs;
1103*38fd1498Szrj 	  read_uleb128 (&count_buf);
1104*38fd1498Szrj 	}
1105*38fd1498Szrj 
1106*38fd1498Szrj       if (num_attrs == 0)
1107*38fd1498Szrj 	{
1108*38fd1498Szrj 	  attrs = NULL;
1109*38fd1498Szrj 	  read_uleb128 (&abbrev_buf);
1110*38fd1498Szrj 	  read_uleb128 (&abbrev_buf);
1111*38fd1498Szrj 	}
1112*38fd1498Szrj       else
1113*38fd1498Szrj 	{
1114*38fd1498Szrj 	  attrs = ((struct attr *)
1115*38fd1498Szrj 		   backtrace_alloc (state, num_attrs * sizeof *attrs,
1116*38fd1498Szrj 				    error_callback, data));
1117*38fd1498Szrj 	  if (attrs == NULL)
1118*38fd1498Szrj 	    goto fail;
1119*38fd1498Szrj 	  num_attrs = 0;
1120*38fd1498Szrj 	  while (1)
1121*38fd1498Szrj 	    {
1122*38fd1498Szrj 	      uint64_t name;
1123*38fd1498Szrj 	      uint64_t form;
1124*38fd1498Szrj 
1125*38fd1498Szrj 	      name = read_uleb128 (&abbrev_buf);
1126*38fd1498Szrj 	      form = read_uleb128 (&abbrev_buf);
1127*38fd1498Szrj 	      if (name == 0)
1128*38fd1498Szrj 		break;
1129*38fd1498Szrj 	      attrs[num_attrs].name = (enum dwarf_attribute) name;
1130*38fd1498Szrj 	      attrs[num_attrs].form = (enum dwarf_form) form;
1131*38fd1498Szrj 	      ++num_attrs;
1132*38fd1498Szrj 	    }
1133*38fd1498Szrj 	}
1134*38fd1498Szrj 
1135*38fd1498Szrj       a.num_attrs = num_attrs;
1136*38fd1498Szrj       a.attrs = attrs;
1137*38fd1498Szrj 
1138*38fd1498Szrj       abbrevs->abbrevs[num_abbrevs] = a;
1139*38fd1498Szrj       ++num_abbrevs;
1140*38fd1498Szrj     }
1141*38fd1498Szrj 
1142*38fd1498Szrj   backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,
1143*38fd1498Szrj 		   sizeof (struct abbrev), abbrev_compare);
1144*38fd1498Szrj 
1145*38fd1498Szrj   return 1;
1146*38fd1498Szrj 
1147*38fd1498Szrj  fail:
1148*38fd1498Szrj   free_abbrevs (state, abbrevs, error_callback, data);
1149*38fd1498Szrj   return 0;
1150*38fd1498Szrj }
1151*38fd1498Szrj 
1152*38fd1498Szrj /* Return the abbrev information for an abbrev code.  */
1153*38fd1498Szrj 
1154*38fd1498Szrj static const struct abbrev *
lookup_abbrev(struct abbrevs * abbrevs,uint64_t code,backtrace_error_callback error_callback,void * data)1155*38fd1498Szrj lookup_abbrev (struct abbrevs *abbrevs, uint64_t code,
1156*38fd1498Szrj 	       backtrace_error_callback error_callback, void *data)
1157*38fd1498Szrj {
1158*38fd1498Szrj   struct abbrev key;
1159*38fd1498Szrj   void *p;
1160*38fd1498Szrj 
1161*38fd1498Szrj   /* With GCC, where abbrevs are simply numbered in order, we should
1162*38fd1498Szrj      be able to just look up the entry.  */
1163*38fd1498Szrj   if (code - 1 < abbrevs->num_abbrevs
1164*38fd1498Szrj       && abbrevs->abbrevs[code - 1].code == code)
1165*38fd1498Szrj     return &abbrevs->abbrevs[code - 1];
1166*38fd1498Szrj 
1167*38fd1498Szrj   /* Otherwise we have to search.  */
1168*38fd1498Szrj   memset (&key, 0, sizeof key);
1169*38fd1498Szrj   key.code = code;
1170*38fd1498Szrj   p = bsearch (&key, abbrevs->abbrevs, abbrevs->num_abbrevs,
1171*38fd1498Szrj 	       sizeof (struct abbrev), abbrev_compare);
1172*38fd1498Szrj   if (p == NULL)
1173*38fd1498Szrj     {
1174*38fd1498Szrj       error_callback (data, "invalid abbreviation code", 0);
1175*38fd1498Szrj       return NULL;
1176*38fd1498Szrj     }
1177*38fd1498Szrj   return (const struct abbrev *) p;
1178*38fd1498Szrj }
1179*38fd1498Szrj 
1180*38fd1498Szrj /* Add non-contiguous address ranges for a compilation unit.  Returns
1181*38fd1498Szrj    1 on success, 0 on failure.  */
1182*38fd1498Szrj 
1183*38fd1498Szrj static int
add_unit_ranges(struct backtrace_state * state,uintptr_t base_address,struct unit * u,uint64_t ranges,uint64_t base,int is_bigendian,const unsigned char * dwarf_ranges,size_t dwarf_ranges_size,backtrace_error_callback error_callback,void * data,struct unit_addrs_vector * addrs)1184*38fd1498Szrj add_unit_ranges (struct backtrace_state *state, uintptr_t base_address,
1185*38fd1498Szrj 		 struct unit *u, uint64_t ranges, uint64_t base,
1186*38fd1498Szrj 		 int is_bigendian, const unsigned char *dwarf_ranges,
1187*38fd1498Szrj 		 size_t dwarf_ranges_size,
1188*38fd1498Szrj 		 backtrace_error_callback error_callback, void *data,
1189*38fd1498Szrj 		 struct unit_addrs_vector *addrs)
1190*38fd1498Szrj {
1191*38fd1498Szrj   struct dwarf_buf ranges_buf;
1192*38fd1498Szrj 
1193*38fd1498Szrj   if (ranges >= dwarf_ranges_size)
1194*38fd1498Szrj     {
1195*38fd1498Szrj       error_callback (data, "ranges offset out of range", 0);
1196*38fd1498Szrj       return 0;
1197*38fd1498Szrj     }
1198*38fd1498Szrj 
1199*38fd1498Szrj   ranges_buf.name = ".debug_ranges";
1200*38fd1498Szrj   ranges_buf.start = dwarf_ranges;
1201*38fd1498Szrj   ranges_buf.buf = dwarf_ranges + ranges;
1202*38fd1498Szrj   ranges_buf.left = dwarf_ranges_size - ranges;
1203*38fd1498Szrj   ranges_buf.is_bigendian = is_bigendian;
1204*38fd1498Szrj   ranges_buf.error_callback = error_callback;
1205*38fd1498Szrj   ranges_buf.data = data;
1206*38fd1498Szrj   ranges_buf.reported_underflow = 0;
1207*38fd1498Szrj 
1208*38fd1498Szrj   while (1)
1209*38fd1498Szrj     {
1210*38fd1498Szrj       uint64_t low;
1211*38fd1498Szrj       uint64_t high;
1212*38fd1498Szrj 
1213*38fd1498Szrj       if (ranges_buf.reported_underflow)
1214*38fd1498Szrj 	return 0;
1215*38fd1498Szrj 
1216*38fd1498Szrj       low = read_address (&ranges_buf, u->addrsize);
1217*38fd1498Szrj       high = read_address (&ranges_buf, u->addrsize);
1218*38fd1498Szrj 
1219*38fd1498Szrj       if (low == 0 && high == 0)
1220*38fd1498Szrj 	break;
1221*38fd1498Szrj 
1222*38fd1498Szrj       if (is_highest_address (low, u->addrsize))
1223*38fd1498Szrj 	base = high;
1224*38fd1498Szrj       else
1225*38fd1498Szrj 	{
1226*38fd1498Szrj 	  struct unit_addrs a;
1227*38fd1498Szrj 
1228*38fd1498Szrj 	  a.low = low + base;
1229*38fd1498Szrj 	  a.high = high + base;
1230*38fd1498Szrj 	  a.u = u;
1231*38fd1498Szrj 	  if (!add_unit_addr (state, base_address, a, error_callback, data,
1232*38fd1498Szrj 			      addrs))
1233*38fd1498Szrj 	    return 0;
1234*38fd1498Szrj 	}
1235*38fd1498Szrj     }
1236*38fd1498Szrj 
1237*38fd1498Szrj   if (ranges_buf.reported_underflow)
1238*38fd1498Szrj     return 0;
1239*38fd1498Szrj 
1240*38fd1498Szrj   return 1;
1241*38fd1498Szrj }
1242*38fd1498Szrj 
1243*38fd1498Szrj /* Find the address range covered by a compilation unit, reading from
1244*38fd1498Szrj    UNIT_BUF and adding values to U.  Returns 1 if all data could be
1245*38fd1498Szrj    read, 0 if there is some error.  */
1246*38fd1498Szrj 
1247*38fd1498Szrj static int
find_address_ranges(struct backtrace_state * state,uintptr_t base_address,struct dwarf_buf * unit_buf,const unsigned char * dwarf_str,size_t dwarf_str_size,const unsigned char * dwarf_ranges,size_t dwarf_ranges_size,int is_bigendian,backtrace_error_callback error_callback,void * data,struct unit * u,struct unit_addrs_vector * addrs)1248*38fd1498Szrj find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
1249*38fd1498Szrj 		     struct dwarf_buf *unit_buf,
1250*38fd1498Szrj 		     const unsigned char *dwarf_str, size_t dwarf_str_size,
1251*38fd1498Szrj 		     const unsigned char *dwarf_ranges,
1252*38fd1498Szrj 		     size_t dwarf_ranges_size,
1253*38fd1498Szrj 		     int is_bigendian, backtrace_error_callback error_callback,
1254*38fd1498Szrj 		     void *data, struct unit *u,
1255*38fd1498Szrj 		     struct unit_addrs_vector *addrs)
1256*38fd1498Szrj {
1257*38fd1498Szrj   while (unit_buf->left > 0)
1258*38fd1498Szrj     {
1259*38fd1498Szrj       uint64_t code;
1260*38fd1498Szrj       const struct abbrev *abbrev;
1261*38fd1498Szrj       uint64_t lowpc;
1262*38fd1498Szrj       int have_lowpc;
1263*38fd1498Szrj       uint64_t highpc;
1264*38fd1498Szrj       int have_highpc;
1265*38fd1498Szrj       int highpc_is_relative;
1266*38fd1498Szrj       uint64_t ranges;
1267*38fd1498Szrj       int have_ranges;
1268*38fd1498Szrj       size_t i;
1269*38fd1498Szrj 
1270*38fd1498Szrj       code = read_uleb128 (unit_buf);
1271*38fd1498Szrj       if (code == 0)
1272*38fd1498Szrj 	return 1;
1273*38fd1498Szrj 
1274*38fd1498Szrj       abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
1275*38fd1498Szrj       if (abbrev == NULL)
1276*38fd1498Szrj 	return 0;
1277*38fd1498Szrj 
1278*38fd1498Szrj       lowpc = 0;
1279*38fd1498Szrj       have_lowpc = 0;
1280*38fd1498Szrj       highpc = 0;
1281*38fd1498Szrj       have_highpc = 0;
1282*38fd1498Szrj       highpc_is_relative = 0;
1283*38fd1498Szrj       ranges = 0;
1284*38fd1498Szrj       have_ranges = 0;
1285*38fd1498Szrj       for (i = 0; i < abbrev->num_attrs; ++i)
1286*38fd1498Szrj 	{
1287*38fd1498Szrj 	  struct attr_val val;
1288*38fd1498Szrj 
1289*38fd1498Szrj 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
1290*38fd1498Szrj 			       u->is_dwarf64, u->version, u->addrsize,
1291*38fd1498Szrj 			       dwarf_str, dwarf_str_size, &val))
1292*38fd1498Szrj 	    return 0;
1293*38fd1498Szrj 
1294*38fd1498Szrj 	  switch (abbrev->attrs[i].name)
1295*38fd1498Szrj 	    {
1296*38fd1498Szrj 	    case DW_AT_low_pc:
1297*38fd1498Szrj 	      if (val.encoding == ATTR_VAL_ADDRESS)
1298*38fd1498Szrj 		{
1299*38fd1498Szrj 		  lowpc = val.u.uint;
1300*38fd1498Szrj 		  have_lowpc = 1;
1301*38fd1498Szrj 		}
1302*38fd1498Szrj 	      break;
1303*38fd1498Szrj 
1304*38fd1498Szrj 	    case DW_AT_high_pc:
1305*38fd1498Szrj 	      if (val.encoding == ATTR_VAL_ADDRESS)
1306*38fd1498Szrj 		{
1307*38fd1498Szrj 		  highpc = val.u.uint;
1308*38fd1498Szrj 		  have_highpc = 1;
1309*38fd1498Szrj 		}
1310*38fd1498Szrj 	      else if (val.encoding == ATTR_VAL_UINT)
1311*38fd1498Szrj 		{
1312*38fd1498Szrj 		  highpc = val.u.uint;
1313*38fd1498Szrj 		  have_highpc = 1;
1314*38fd1498Szrj 		  highpc_is_relative = 1;
1315*38fd1498Szrj 		}
1316*38fd1498Szrj 	      break;
1317*38fd1498Szrj 
1318*38fd1498Szrj 	    case DW_AT_ranges:
1319*38fd1498Szrj 	      if (val.encoding == ATTR_VAL_UINT
1320*38fd1498Szrj 		  || val.encoding == ATTR_VAL_REF_SECTION)
1321*38fd1498Szrj 		{
1322*38fd1498Szrj 		  ranges = val.u.uint;
1323*38fd1498Szrj 		  have_ranges = 1;
1324*38fd1498Szrj 		}
1325*38fd1498Szrj 	      break;
1326*38fd1498Szrj 
1327*38fd1498Szrj 	    case DW_AT_stmt_list:
1328*38fd1498Szrj 	      if (abbrev->tag == DW_TAG_compile_unit
1329*38fd1498Szrj 		  && (val.encoding == ATTR_VAL_UINT
1330*38fd1498Szrj 		      || val.encoding == ATTR_VAL_REF_SECTION))
1331*38fd1498Szrj 		u->lineoff = val.u.uint;
1332*38fd1498Szrj 	      break;
1333*38fd1498Szrj 
1334*38fd1498Szrj 	    case DW_AT_name:
1335*38fd1498Szrj 	      if (abbrev->tag == DW_TAG_compile_unit
1336*38fd1498Szrj 		  && val.encoding == ATTR_VAL_STRING)
1337*38fd1498Szrj 		u->filename = val.u.string;
1338*38fd1498Szrj 	      break;
1339*38fd1498Szrj 
1340*38fd1498Szrj 	    case DW_AT_comp_dir:
1341*38fd1498Szrj 	      if (abbrev->tag == DW_TAG_compile_unit
1342*38fd1498Szrj 		  && val.encoding == ATTR_VAL_STRING)
1343*38fd1498Szrj 		u->comp_dir = val.u.string;
1344*38fd1498Szrj 	      break;
1345*38fd1498Szrj 
1346*38fd1498Szrj 	    default:
1347*38fd1498Szrj 	      break;
1348*38fd1498Szrj 	    }
1349*38fd1498Szrj 	}
1350*38fd1498Szrj 
1351*38fd1498Szrj       if (abbrev->tag == DW_TAG_compile_unit
1352*38fd1498Szrj 	  || abbrev->tag == DW_TAG_subprogram)
1353*38fd1498Szrj 	{
1354*38fd1498Szrj 	  if (have_ranges)
1355*38fd1498Szrj 	    {
1356*38fd1498Szrj 	      if (!add_unit_ranges (state, base_address, u, ranges, lowpc,
1357*38fd1498Szrj 				    is_bigendian, dwarf_ranges,
1358*38fd1498Szrj 				    dwarf_ranges_size, error_callback,
1359*38fd1498Szrj 				    data, addrs))
1360*38fd1498Szrj 		return 0;
1361*38fd1498Szrj 	    }
1362*38fd1498Szrj 	  else if (have_lowpc && have_highpc)
1363*38fd1498Szrj 	    {
1364*38fd1498Szrj 	      struct unit_addrs a;
1365*38fd1498Szrj 
1366*38fd1498Szrj 	      if (highpc_is_relative)
1367*38fd1498Szrj 		highpc += lowpc;
1368*38fd1498Szrj 	      a.low = lowpc;
1369*38fd1498Szrj 	      a.high = highpc;
1370*38fd1498Szrj 	      a.u = u;
1371*38fd1498Szrj 
1372*38fd1498Szrj 	      if (!add_unit_addr (state, base_address, a, error_callback, data,
1373*38fd1498Szrj 				  addrs))
1374*38fd1498Szrj 		return 0;
1375*38fd1498Szrj 	    }
1376*38fd1498Szrj 
1377*38fd1498Szrj 	  /* If we found the PC range in the DW_TAG_compile_unit, we
1378*38fd1498Szrj 	     can stop now.  */
1379*38fd1498Szrj 	  if (abbrev->tag == DW_TAG_compile_unit
1380*38fd1498Szrj 	      && (have_ranges || (have_lowpc && have_highpc)))
1381*38fd1498Szrj 	    return 1;
1382*38fd1498Szrj 	}
1383*38fd1498Szrj 
1384*38fd1498Szrj       if (abbrev->has_children)
1385*38fd1498Szrj 	{
1386*38fd1498Szrj 	  if (!find_address_ranges (state, base_address, unit_buf,
1387*38fd1498Szrj 				    dwarf_str, dwarf_str_size,
1388*38fd1498Szrj 				    dwarf_ranges, dwarf_ranges_size,
1389*38fd1498Szrj 				    is_bigendian, error_callback, data,
1390*38fd1498Szrj 				    u, addrs))
1391*38fd1498Szrj 	    return 0;
1392*38fd1498Szrj 	}
1393*38fd1498Szrj     }
1394*38fd1498Szrj 
1395*38fd1498Szrj   return 1;
1396*38fd1498Szrj }
1397*38fd1498Szrj 
1398*38fd1498Szrj /* Build a mapping from address ranges to the compilation units where
1399*38fd1498Szrj    the line number information for that range can be found.  Returns 1
1400*38fd1498Szrj    on success, 0 on failure.  */
1401*38fd1498Szrj 
1402*38fd1498Szrj static int
build_address_map(struct backtrace_state * state,uintptr_t base_address,const unsigned char * dwarf_info,size_t dwarf_info_size,const unsigned char * dwarf_abbrev,size_t dwarf_abbrev_size,const unsigned char * dwarf_ranges,size_t dwarf_ranges_size,const unsigned char * dwarf_str,size_t dwarf_str_size,int is_bigendian,backtrace_error_callback error_callback,void * data,struct unit_addrs_vector * addrs)1403*38fd1498Szrj build_address_map (struct backtrace_state *state, uintptr_t base_address,
1404*38fd1498Szrj 		   const unsigned char *dwarf_info, size_t dwarf_info_size,
1405*38fd1498Szrj 		   const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
1406*38fd1498Szrj 		   const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
1407*38fd1498Szrj 		   const unsigned char *dwarf_str, size_t dwarf_str_size,
1408*38fd1498Szrj 		   int is_bigendian, backtrace_error_callback error_callback,
1409*38fd1498Szrj 		   void *data, struct unit_addrs_vector *addrs)
1410*38fd1498Szrj {
1411*38fd1498Szrj   struct dwarf_buf info;
1412*38fd1498Szrj   struct abbrevs abbrevs;
1413*38fd1498Szrj 
1414*38fd1498Szrj   memset (&addrs->vec, 0, sizeof addrs->vec);
1415*38fd1498Szrj   addrs->count = 0;
1416*38fd1498Szrj 
1417*38fd1498Szrj   /* Read through the .debug_info section.  FIXME: Should we use the
1418*38fd1498Szrj      .debug_aranges section?  gdb and addr2line don't use it, but I'm
1419*38fd1498Szrj      not sure why.  */
1420*38fd1498Szrj 
1421*38fd1498Szrj   info.name = ".debug_info";
1422*38fd1498Szrj   info.start = dwarf_info;
1423*38fd1498Szrj   info.buf = dwarf_info;
1424*38fd1498Szrj   info.left = dwarf_info_size;
1425*38fd1498Szrj   info.is_bigendian = is_bigendian;
1426*38fd1498Szrj   info.error_callback = error_callback;
1427*38fd1498Szrj   info.data = data;
1428*38fd1498Szrj   info.reported_underflow = 0;
1429*38fd1498Szrj 
1430*38fd1498Szrj   memset (&abbrevs, 0, sizeof abbrevs);
1431*38fd1498Szrj   while (info.left > 0)
1432*38fd1498Szrj     {
1433*38fd1498Szrj       const unsigned char *unit_data_start;
1434*38fd1498Szrj       uint64_t len;
1435*38fd1498Szrj       int is_dwarf64;
1436*38fd1498Szrj       struct dwarf_buf unit_buf;
1437*38fd1498Szrj       int version;
1438*38fd1498Szrj       uint64_t abbrev_offset;
1439*38fd1498Szrj       int addrsize;
1440*38fd1498Szrj       struct unit *u;
1441*38fd1498Szrj 
1442*38fd1498Szrj       if (info.reported_underflow)
1443*38fd1498Szrj 	goto fail;
1444*38fd1498Szrj 
1445*38fd1498Szrj       unit_data_start = info.buf;
1446*38fd1498Szrj 
1447*38fd1498Szrj       is_dwarf64 = 0;
1448*38fd1498Szrj       len = read_uint32 (&info);
1449*38fd1498Szrj       if (len == 0xffffffff)
1450*38fd1498Szrj 	{
1451*38fd1498Szrj 	  len = read_uint64 (&info);
1452*38fd1498Szrj 	  is_dwarf64 = 1;
1453*38fd1498Szrj 	}
1454*38fd1498Szrj 
1455*38fd1498Szrj       unit_buf = info;
1456*38fd1498Szrj       unit_buf.left = len;
1457*38fd1498Szrj 
1458*38fd1498Szrj       if (!advance (&info, len))
1459*38fd1498Szrj 	goto fail;
1460*38fd1498Szrj 
1461*38fd1498Szrj       version = read_uint16 (&unit_buf);
1462*38fd1498Szrj       if (version < 2 || version > 4)
1463*38fd1498Szrj 	{
1464*38fd1498Szrj 	  dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
1465*38fd1498Szrj 	  goto fail;
1466*38fd1498Szrj 	}
1467*38fd1498Szrj 
1468*38fd1498Szrj       abbrev_offset = read_offset (&unit_buf, is_dwarf64);
1469*38fd1498Szrj       if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size,
1470*38fd1498Szrj 			 is_bigendian, error_callback, data, &abbrevs))
1471*38fd1498Szrj 	goto fail;
1472*38fd1498Szrj 
1473*38fd1498Szrj       addrsize = read_byte (&unit_buf);
1474*38fd1498Szrj 
1475*38fd1498Szrj       u = ((struct unit *)
1476*38fd1498Szrj 	   backtrace_alloc (state, sizeof *u, error_callback, data));
1477*38fd1498Szrj       if (u == NULL)
1478*38fd1498Szrj 	goto fail;
1479*38fd1498Szrj       u->unit_data = unit_buf.buf;
1480*38fd1498Szrj       u->unit_data_len = unit_buf.left;
1481*38fd1498Szrj       u->unit_data_offset = unit_buf.buf - unit_data_start;
1482*38fd1498Szrj       u->version = version;
1483*38fd1498Szrj       u->is_dwarf64 = is_dwarf64;
1484*38fd1498Szrj       u->addrsize = addrsize;
1485*38fd1498Szrj       u->filename = NULL;
1486*38fd1498Szrj       u->comp_dir = NULL;
1487*38fd1498Szrj       u->abs_filename = NULL;
1488*38fd1498Szrj       u->lineoff = 0;
1489*38fd1498Szrj       u->abbrevs = abbrevs;
1490*38fd1498Szrj       memset (&abbrevs, 0, sizeof abbrevs);
1491*38fd1498Szrj 
1492*38fd1498Szrj       /* The actual line number mappings will be read as needed.  */
1493*38fd1498Szrj       u->lines = NULL;
1494*38fd1498Szrj       u->lines_count = 0;
1495*38fd1498Szrj       u->function_addrs = NULL;
1496*38fd1498Szrj       u->function_addrs_count = 0;
1497*38fd1498Szrj 
1498*38fd1498Szrj       if (!find_address_ranges (state, base_address, &unit_buf,
1499*38fd1498Szrj 				dwarf_str, dwarf_str_size,
1500*38fd1498Szrj 				dwarf_ranges, dwarf_ranges_size,
1501*38fd1498Szrj 				is_bigendian, error_callback, data,
1502*38fd1498Szrj 				u, addrs))
1503*38fd1498Szrj 	{
1504*38fd1498Szrj 	  free_abbrevs (state, &u->abbrevs, error_callback, data);
1505*38fd1498Szrj 	  backtrace_free (state, u, sizeof *u, error_callback, data);
1506*38fd1498Szrj 	  goto fail;
1507*38fd1498Szrj 	}
1508*38fd1498Szrj 
1509*38fd1498Szrj       if (unit_buf.reported_underflow)
1510*38fd1498Szrj 	{
1511*38fd1498Szrj 	  free_abbrevs (state, &u->abbrevs, error_callback, data);
1512*38fd1498Szrj 	  backtrace_free (state, u, sizeof *u, error_callback, data);
1513*38fd1498Szrj 	  goto fail;
1514*38fd1498Szrj 	}
1515*38fd1498Szrj     }
1516*38fd1498Szrj   if (info.reported_underflow)
1517*38fd1498Szrj     goto fail;
1518*38fd1498Szrj 
1519*38fd1498Szrj   return 1;
1520*38fd1498Szrj 
1521*38fd1498Szrj  fail:
1522*38fd1498Szrj   free_abbrevs (state, &abbrevs, error_callback, data);
1523*38fd1498Szrj   free_unit_addrs_vector (state, addrs, error_callback, data);
1524*38fd1498Szrj   return 0;
1525*38fd1498Szrj }
1526*38fd1498Szrj 
1527*38fd1498Szrj /* Add a new mapping to the vector of line mappings that we are
1528*38fd1498Szrj    building.  Returns 1 on success, 0 on failure.  */
1529*38fd1498Szrj 
1530*38fd1498Szrj 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)1531*38fd1498Szrj add_line (struct backtrace_state *state, struct dwarf_data *ddata,
1532*38fd1498Szrj 	  uintptr_t pc, const char *filename, int lineno,
1533*38fd1498Szrj 	  backtrace_error_callback error_callback, void *data,
1534*38fd1498Szrj 	  struct line_vector *vec)
1535*38fd1498Szrj {
1536*38fd1498Szrj   struct line *ln;
1537*38fd1498Szrj 
1538*38fd1498Szrj   /* If we are adding the same mapping, ignore it.  This can happen
1539*38fd1498Szrj      when using discriminators.  */
1540*38fd1498Szrj   if (vec->count > 0)
1541*38fd1498Szrj     {
1542*38fd1498Szrj       ln = (struct line *) vec->vec.base + (vec->count - 1);
1543*38fd1498Szrj       if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)
1544*38fd1498Szrj 	return 1;
1545*38fd1498Szrj     }
1546*38fd1498Szrj 
1547*38fd1498Szrj   ln = ((struct line *)
1548*38fd1498Szrj 	backtrace_vector_grow (state, sizeof (struct line), error_callback,
1549*38fd1498Szrj 			       data, &vec->vec));
1550*38fd1498Szrj   if (ln == NULL)
1551*38fd1498Szrj     return 0;
1552*38fd1498Szrj 
1553*38fd1498Szrj   /* Add in the base address here, so that we can look up the PC
1554*38fd1498Szrj      directly.  */
1555*38fd1498Szrj   ln->pc = pc + ddata->base_address;
1556*38fd1498Szrj 
1557*38fd1498Szrj   ln->filename = filename;
1558*38fd1498Szrj   ln->lineno = lineno;
1559*38fd1498Szrj   ln->idx = vec->count;
1560*38fd1498Szrj 
1561*38fd1498Szrj   ++vec->count;
1562*38fd1498Szrj 
1563*38fd1498Szrj   return 1;
1564*38fd1498Szrj }
1565*38fd1498Szrj 
1566*38fd1498Szrj /* Free the line header information.  */
1567*38fd1498Szrj 
1568*38fd1498Szrj static void
free_line_header(struct backtrace_state * state,struct line_header * hdr,backtrace_error_callback error_callback,void * data)1569*38fd1498Szrj free_line_header (struct backtrace_state *state, struct line_header *hdr,
1570*38fd1498Szrj 		  backtrace_error_callback error_callback, void *data)
1571*38fd1498Szrj {
1572*38fd1498Szrj   if (hdr->dirs_count != 0)
1573*38fd1498Szrj     backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *),
1574*38fd1498Szrj 		    error_callback, data);
1575*38fd1498Szrj   backtrace_free (state, hdr->filenames,
1576*38fd1498Szrj 		  hdr->filenames_count * sizeof (char *),
1577*38fd1498Szrj 		  error_callback, data);
1578*38fd1498Szrj }
1579*38fd1498Szrj 
1580*38fd1498Szrj /* Read the line header.  Return 1 on success, 0 on failure.  */
1581*38fd1498Szrj 
1582*38fd1498Szrj static int
read_line_header(struct backtrace_state * state,struct unit * u,int is_dwarf64,struct dwarf_buf * line_buf,struct line_header * hdr)1583*38fd1498Szrj read_line_header (struct backtrace_state *state, struct unit *u,
1584*38fd1498Szrj 		  int is_dwarf64, struct dwarf_buf *line_buf,
1585*38fd1498Szrj 		  struct line_header *hdr)
1586*38fd1498Szrj {
1587*38fd1498Szrj   uint64_t hdrlen;
1588*38fd1498Szrj   struct dwarf_buf hdr_buf;
1589*38fd1498Szrj   const unsigned char *p;
1590*38fd1498Szrj   const unsigned char *pend;
1591*38fd1498Szrj   size_t i;
1592*38fd1498Szrj 
1593*38fd1498Szrj   hdr->version = read_uint16 (line_buf);
1594*38fd1498Szrj   if (hdr->version < 2 || hdr->version > 4)
1595*38fd1498Szrj     {
1596*38fd1498Szrj       dwarf_buf_error (line_buf, "unsupported line number version");
1597*38fd1498Szrj       return 0;
1598*38fd1498Szrj     }
1599*38fd1498Szrj 
1600*38fd1498Szrj   hdrlen = read_offset (line_buf, is_dwarf64);
1601*38fd1498Szrj 
1602*38fd1498Szrj   hdr_buf = *line_buf;
1603*38fd1498Szrj   hdr_buf.left = hdrlen;
1604*38fd1498Szrj 
1605*38fd1498Szrj   if (!advance (line_buf, hdrlen))
1606*38fd1498Szrj     return 0;
1607*38fd1498Szrj 
1608*38fd1498Szrj   hdr->min_insn_len = read_byte (&hdr_buf);
1609*38fd1498Szrj   if (hdr->version < 4)
1610*38fd1498Szrj     hdr->max_ops_per_insn = 1;
1611*38fd1498Szrj   else
1612*38fd1498Szrj     hdr->max_ops_per_insn = read_byte (&hdr_buf);
1613*38fd1498Szrj 
1614*38fd1498Szrj   /* We don't care about default_is_stmt.  */
1615*38fd1498Szrj   read_byte (&hdr_buf);
1616*38fd1498Szrj 
1617*38fd1498Szrj   hdr->line_base = read_sbyte (&hdr_buf);
1618*38fd1498Szrj   hdr->line_range = read_byte (&hdr_buf);
1619*38fd1498Szrj 
1620*38fd1498Szrj   hdr->opcode_base = read_byte (&hdr_buf);
1621*38fd1498Szrj   hdr->opcode_lengths = hdr_buf.buf;
1622*38fd1498Szrj   if (!advance (&hdr_buf, hdr->opcode_base - 1))
1623*38fd1498Szrj     return 0;
1624*38fd1498Szrj 
1625*38fd1498Szrj   /* Count the number of directory entries.  */
1626*38fd1498Szrj   hdr->dirs_count = 0;
1627*38fd1498Szrj   p = hdr_buf.buf;
1628*38fd1498Szrj   pend = p + hdr_buf.left;
1629*38fd1498Szrj   while (p < pend && *p != '\0')
1630*38fd1498Szrj     {
1631*38fd1498Szrj       p += strnlen((const char *) p, pend - p) + 1;
1632*38fd1498Szrj       ++hdr->dirs_count;
1633*38fd1498Szrj     }
1634*38fd1498Szrj 
1635*38fd1498Szrj   hdr->dirs = NULL;
1636*38fd1498Szrj   if (hdr->dirs_count != 0)
1637*38fd1498Szrj     {
1638*38fd1498Szrj       hdr->dirs = ((const char **)
1639*38fd1498Szrj 		   backtrace_alloc (state,
1640*38fd1498Szrj 				    hdr->dirs_count * sizeof (const char *),
1641*38fd1498Szrj 				    line_buf->error_callback, line_buf->data));
1642*38fd1498Szrj       if (hdr->dirs == NULL)
1643*38fd1498Szrj 	return 0;
1644*38fd1498Szrj     }
1645*38fd1498Szrj 
1646*38fd1498Szrj   i = 0;
1647*38fd1498Szrj   while (*hdr_buf.buf != '\0')
1648*38fd1498Szrj     {
1649*38fd1498Szrj       if (hdr_buf.reported_underflow)
1650*38fd1498Szrj 	return 0;
1651*38fd1498Szrj 
1652*38fd1498Szrj       hdr->dirs[i] = (const char *) hdr_buf.buf;
1653*38fd1498Szrj       ++i;
1654*38fd1498Szrj       if (!advance (&hdr_buf,
1655*38fd1498Szrj 		    strnlen ((const char *) hdr_buf.buf, hdr_buf.left) + 1))
1656*38fd1498Szrj 	return 0;
1657*38fd1498Szrj     }
1658*38fd1498Szrj   if (!advance (&hdr_buf, 1))
1659*38fd1498Szrj     return 0;
1660*38fd1498Szrj 
1661*38fd1498Szrj   /* Count the number of file entries.  */
1662*38fd1498Szrj   hdr->filenames_count = 0;
1663*38fd1498Szrj   p = hdr_buf.buf;
1664*38fd1498Szrj   pend = p + hdr_buf.left;
1665*38fd1498Szrj   while (p < pend && *p != '\0')
1666*38fd1498Szrj     {
1667*38fd1498Szrj       p += strnlen ((const char *) p, pend - p) + 1;
1668*38fd1498Szrj       p += leb128_len (p);
1669*38fd1498Szrj       p += leb128_len (p);
1670*38fd1498Szrj       p += leb128_len (p);
1671*38fd1498Szrj       ++hdr->filenames_count;
1672*38fd1498Szrj     }
1673*38fd1498Szrj 
1674*38fd1498Szrj   hdr->filenames = ((const char **)
1675*38fd1498Szrj 		    backtrace_alloc (state,
1676*38fd1498Szrj 				     hdr->filenames_count * sizeof (char *),
1677*38fd1498Szrj 				     line_buf->error_callback,
1678*38fd1498Szrj 				     line_buf->data));
1679*38fd1498Szrj   if (hdr->filenames == NULL)
1680*38fd1498Szrj     return 0;
1681*38fd1498Szrj   i = 0;
1682*38fd1498Szrj   while (*hdr_buf.buf != '\0')
1683*38fd1498Szrj     {
1684*38fd1498Szrj       const char *filename;
1685*38fd1498Szrj       uint64_t dir_index;
1686*38fd1498Szrj 
1687*38fd1498Szrj       if (hdr_buf.reported_underflow)
1688*38fd1498Szrj 	return 0;
1689*38fd1498Szrj 
1690*38fd1498Szrj       filename = (const char *) hdr_buf.buf;
1691*38fd1498Szrj       if (!advance (&hdr_buf,
1692*38fd1498Szrj 		    strnlen ((const char *) hdr_buf.buf, hdr_buf.left) + 1))
1693*38fd1498Szrj 	return 0;
1694*38fd1498Szrj       dir_index = read_uleb128 (&hdr_buf);
1695*38fd1498Szrj       if (IS_ABSOLUTE_PATH (filename)
1696*38fd1498Szrj 	  || (dir_index == 0 && u->comp_dir == NULL))
1697*38fd1498Szrj 	hdr->filenames[i] = filename;
1698*38fd1498Szrj       else
1699*38fd1498Szrj 	{
1700*38fd1498Szrj 	  const char *dir;
1701*38fd1498Szrj 	  size_t dir_len;
1702*38fd1498Szrj 	  size_t filename_len;
1703*38fd1498Szrj 	  char *s;
1704*38fd1498Szrj 
1705*38fd1498Szrj 	  if (dir_index == 0)
1706*38fd1498Szrj 	    dir = u->comp_dir;
1707*38fd1498Szrj 	  else if (dir_index - 1 < hdr->dirs_count)
1708*38fd1498Szrj 	    dir = hdr->dirs[dir_index - 1];
1709*38fd1498Szrj 	  else
1710*38fd1498Szrj 	    {
1711*38fd1498Szrj 	      dwarf_buf_error (line_buf,
1712*38fd1498Szrj 			       ("invalid directory index in "
1713*38fd1498Szrj 				"line number program header"));
1714*38fd1498Szrj 	      return 0;
1715*38fd1498Szrj 	    }
1716*38fd1498Szrj 	  dir_len = strlen (dir);
1717*38fd1498Szrj 	  filename_len = strlen (filename);
1718*38fd1498Szrj 	  s = ((char *)
1719*38fd1498Szrj 	       backtrace_alloc (state, dir_len + filename_len + 2,
1720*38fd1498Szrj 				line_buf->error_callback, line_buf->data));
1721*38fd1498Szrj 	  if (s == NULL)
1722*38fd1498Szrj 	    return 0;
1723*38fd1498Szrj 	  memcpy (s, dir, dir_len);
1724*38fd1498Szrj 	  /* FIXME: If we are on a DOS-based file system, and the
1725*38fd1498Szrj 	     directory or the file name use backslashes, then we
1726*38fd1498Szrj 	     should use a backslash here.  */
1727*38fd1498Szrj 	  s[dir_len] = '/';
1728*38fd1498Szrj 	  memcpy (s + dir_len + 1, filename, filename_len + 1);
1729*38fd1498Szrj 	  hdr->filenames[i] = s;
1730*38fd1498Szrj 	}
1731*38fd1498Szrj 
1732*38fd1498Szrj       /* Ignore the modification time and size.  */
1733*38fd1498Szrj       read_uleb128 (&hdr_buf);
1734*38fd1498Szrj       read_uleb128 (&hdr_buf);
1735*38fd1498Szrj 
1736*38fd1498Szrj       ++i;
1737*38fd1498Szrj     }
1738*38fd1498Szrj 
1739*38fd1498Szrj   if (hdr_buf.reported_underflow)
1740*38fd1498Szrj     return 0;
1741*38fd1498Szrj 
1742*38fd1498Szrj   return 1;
1743*38fd1498Szrj }
1744*38fd1498Szrj 
1745*38fd1498Szrj /* Read the line program, adding line mappings to VEC.  Return 1 on
1746*38fd1498Szrj    success, 0 on failure.  */
1747*38fd1498Szrj 
1748*38fd1498Szrj 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)1749*38fd1498Szrj read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
1750*38fd1498Szrj 		   struct unit *u, const struct line_header *hdr,
1751*38fd1498Szrj 		   struct dwarf_buf *line_buf, struct line_vector *vec)
1752*38fd1498Szrj {
1753*38fd1498Szrj   uint64_t address;
1754*38fd1498Szrj   unsigned int op_index;
1755*38fd1498Szrj   const char *reset_filename;
1756*38fd1498Szrj   const char *filename;
1757*38fd1498Szrj   int lineno;
1758*38fd1498Szrj 
1759*38fd1498Szrj   address = 0;
1760*38fd1498Szrj   op_index = 0;
1761*38fd1498Szrj   if (hdr->filenames_count > 0)
1762*38fd1498Szrj     reset_filename = hdr->filenames[0];
1763*38fd1498Szrj   else
1764*38fd1498Szrj     reset_filename = "";
1765*38fd1498Szrj   filename = reset_filename;
1766*38fd1498Szrj   lineno = 1;
1767*38fd1498Szrj   while (line_buf->left > 0)
1768*38fd1498Szrj     {
1769*38fd1498Szrj       unsigned int op;
1770*38fd1498Szrj 
1771*38fd1498Szrj       op = read_byte (line_buf);
1772*38fd1498Szrj       if (op >= hdr->opcode_base)
1773*38fd1498Szrj 	{
1774*38fd1498Szrj 	  unsigned int advance;
1775*38fd1498Szrj 
1776*38fd1498Szrj 	  /* Special opcode.  */
1777*38fd1498Szrj 	  op -= hdr->opcode_base;
1778*38fd1498Szrj 	  advance = op / hdr->line_range;
1779*38fd1498Szrj 	  address += (hdr->min_insn_len * (op_index + advance)
1780*38fd1498Szrj 		      / hdr->max_ops_per_insn);
1781*38fd1498Szrj 	  op_index = (op_index + advance) % hdr->max_ops_per_insn;
1782*38fd1498Szrj 	  lineno += hdr->line_base + (int) (op % hdr->line_range);
1783*38fd1498Szrj 	  add_line (state, ddata, address, filename, lineno,
1784*38fd1498Szrj 		    line_buf->error_callback, line_buf->data, vec);
1785*38fd1498Szrj 	}
1786*38fd1498Szrj       else if (op == DW_LNS_extended_op)
1787*38fd1498Szrj 	{
1788*38fd1498Szrj 	  uint64_t len;
1789*38fd1498Szrj 
1790*38fd1498Szrj 	  len = read_uleb128 (line_buf);
1791*38fd1498Szrj 	  op = read_byte (line_buf);
1792*38fd1498Szrj 	  switch (op)
1793*38fd1498Szrj 	    {
1794*38fd1498Szrj 	    case DW_LNE_end_sequence:
1795*38fd1498Szrj 	      /* FIXME: Should we mark the high PC here?  It seems
1796*38fd1498Szrj 		 that we already have that information from the
1797*38fd1498Szrj 		 compilation unit.  */
1798*38fd1498Szrj 	      address = 0;
1799*38fd1498Szrj 	      op_index = 0;
1800*38fd1498Szrj 	      filename = reset_filename;
1801*38fd1498Szrj 	      lineno = 1;
1802*38fd1498Szrj 	      break;
1803*38fd1498Szrj 	    case DW_LNE_set_address:
1804*38fd1498Szrj 	      address = read_address (line_buf, u->addrsize);
1805*38fd1498Szrj 	      break;
1806*38fd1498Szrj 	    case DW_LNE_define_file:
1807*38fd1498Szrj 	      {
1808*38fd1498Szrj 		const char *f;
1809*38fd1498Szrj 		unsigned int dir_index;
1810*38fd1498Szrj 
1811*38fd1498Szrj 		f = (const char *) line_buf->buf;
1812*38fd1498Szrj 		if (!advance (line_buf, strnlen (f, line_buf->left) + 1))
1813*38fd1498Szrj 		  return 0;
1814*38fd1498Szrj 		dir_index = read_uleb128 (line_buf);
1815*38fd1498Szrj 		/* Ignore that time and length.  */
1816*38fd1498Szrj 		read_uleb128 (line_buf);
1817*38fd1498Szrj 		read_uleb128 (line_buf);
1818*38fd1498Szrj 		if (IS_ABSOLUTE_PATH (f))
1819*38fd1498Szrj 		  filename = f;
1820*38fd1498Szrj 		else
1821*38fd1498Szrj 		  {
1822*38fd1498Szrj 		    const char *dir;
1823*38fd1498Szrj 		    size_t dir_len;
1824*38fd1498Szrj 		    size_t f_len;
1825*38fd1498Szrj 		    char *p;
1826*38fd1498Szrj 
1827*38fd1498Szrj 		    if (dir_index == 0)
1828*38fd1498Szrj 		      dir = u->comp_dir;
1829*38fd1498Szrj 		    else if (dir_index - 1 < hdr->dirs_count)
1830*38fd1498Szrj 		      dir = hdr->dirs[dir_index - 1];
1831*38fd1498Szrj 		    else
1832*38fd1498Szrj 		      {
1833*38fd1498Szrj 			dwarf_buf_error (line_buf,
1834*38fd1498Szrj 					 ("invalid directory index "
1835*38fd1498Szrj 					  "in line number program"));
1836*38fd1498Szrj 			return 0;
1837*38fd1498Szrj 		      }
1838*38fd1498Szrj 		    dir_len = strlen (dir);
1839*38fd1498Szrj 		    f_len = strlen (f);
1840*38fd1498Szrj 		    p = ((char *)
1841*38fd1498Szrj 			 backtrace_alloc (state, dir_len + f_len + 2,
1842*38fd1498Szrj 					  line_buf->error_callback,
1843*38fd1498Szrj 					  line_buf->data));
1844*38fd1498Szrj 		    if (p == NULL)
1845*38fd1498Szrj 		      return 0;
1846*38fd1498Szrj 		    memcpy (p, dir, dir_len);
1847*38fd1498Szrj 		    /* FIXME: If we are on a DOS-based file system,
1848*38fd1498Szrj 		       and the directory or the file name use
1849*38fd1498Szrj 		       backslashes, then we should use a backslash
1850*38fd1498Szrj 		       here.  */
1851*38fd1498Szrj 		    p[dir_len] = '/';
1852*38fd1498Szrj 		    memcpy (p + dir_len + 1, f, f_len + 1);
1853*38fd1498Szrj 		    filename = p;
1854*38fd1498Szrj 		  }
1855*38fd1498Szrj 	      }
1856*38fd1498Szrj 	      break;
1857*38fd1498Szrj 	    case DW_LNE_set_discriminator:
1858*38fd1498Szrj 	      /* We don't care about discriminators.  */
1859*38fd1498Szrj 	      read_uleb128 (line_buf);
1860*38fd1498Szrj 	      break;
1861*38fd1498Szrj 	    default:
1862*38fd1498Szrj 	      if (!advance (line_buf, len - 1))
1863*38fd1498Szrj 		return 0;
1864*38fd1498Szrj 	      break;
1865*38fd1498Szrj 	    }
1866*38fd1498Szrj 	}
1867*38fd1498Szrj       else
1868*38fd1498Szrj 	{
1869*38fd1498Szrj 	  switch (op)
1870*38fd1498Szrj 	    {
1871*38fd1498Szrj 	    case DW_LNS_copy:
1872*38fd1498Szrj 	      add_line (state, ddata, address, filename, lineno,
1873*38fd1498Szrj 			line_buf->error_callback, line_buf->data, vec);
1874*38fd1498Szrj 	      break;
1875*38fd1498Szrj 	    case DW_LNS_advance_pc:
1876*38fd1498Szrj 	      {
1877*38fd1498Szrj 		uint64_t advance;
1878*38fd1498Szrj 
1879*38fd1498Szrj 		advance = read_uleb128 (line_buf);
1880*38fd1498Szrj 		address += (hdr->min_insn_len * (op_index + advance)
1881*38fd1498Szrj 			    / hdr->max_ops_per_insn);
1882*38fd1498Szrj 		op_index = (op_index + advance) % hdr->max_ops_per_insn;
1883*38fd1498Szrj 	      }
1884*38fd1498Szrj 	      break;
1885*38fd1498Szrj 	    case DW_LNS_advance_line:
1886*38fd1498Szrj 	      lineno += (int) read_sleb128 (line_buf);
1887*38fd1498Szrj 	      break;
1888*38fd1498Szrj 	    case DW_LNS_set_file:
1889*38fd1498Szrj 	      {
1890*38fd1498Szrj 		uint64_t fileno;
1891*38fd1498Szrj 
1892*38fd1498Szrj 		fileno = read_uleb128 (line_buf);
1893*38fd1498Szrj 		if (fileno == 0)
1894*38fd1498Szrj 		  filename = "";
1895*38fd1498Szrj 		else
1896*38fd1498Szrj 		  {
1897*38fd1498Szrj 		    if (fileno - 1 >= hdr->filenames_count)
1898*38fd1498Szrj 		      {
1899*38fd1498Szrj 			dwarf_buf_error (line_buf,
1900*38fd1498Szrj 					 ("invalid file number in "
1901*38fd1498Szrj 					  "line number program"));
1902*38fd1498Szrj 			return 0;
1903*38fd1498Szrj 		      }
1904*38fd1498Szrj 		    filename = hdr->filenames[fileno - 1];
1905*38fd1498Szrj 		  }
1906*38fd1498Szrj 	      }
1907*38fd1498Szrj 	      break;
1908*38fd1498Szrj 	    case DW_LNS_set_column:
1909*38fd1498Szrj 	      read_uleb128 (line_buf);
1910*38fd1498Szrj 	      break;
1911*38fd1498Szrj 	    case DW_LNS_negate_stmt:
1912*38fd1498Szrj 	      break;
1913*38fd1498Szrj 	    case DW_LNS_set_basic_block:
1914*38fd1498Szrj 	      break;
1915*38fd1498Szrj 	    case DW_LNS_const_add_pc:
1916*38fd1498Szrj 	      {
1917*38fd1498Szrj 		unsigned int advance;
1918*38fd1498Szrj 
1919*38fd1498Szrj 		op = 255 - hdr->opcode_base;
1920*38fd1498Szrj 		advance = op / hdr->line_range;
1921*38fd1498Szrj 		address += (hdr->min_insn_len * (op_index + advance)
1922*38fd1498Szrj 			    / hdr->max_ops_per_insn);
1923*38fd1498Szrj 		op_index = (op_index + advance) % hdr->max_ops_per_insn;
1924*38fd1498Szrj 	      }
1925*38fd1498Szrj 	      break;
1926*38fd1498Szrj 	    case DW_LNS_fixed_advance_pc:
1927*38fd1498Szrj 	      address += read_uint16 (line_buf);
1928*38fd1498Szrj 	      op_index = 0;
1929*38fd1498Szrj 	      break;
1930*38fd1498Szrj 	    case DW_LNS_set_prologue_end:
1931*38fd1498Szrj 	      break;
1932*38fd1498Szrj 	    case DW_LNS_set_epilogue_begin:
1933*38fd1498Szrj 	      break;
1934*38fd1498Szrj 	    case DW_LNS_set_isa:
1935*38fd1498Szrj 	      read_uleb128 (line_buf);
1936*38fd1498Szrj 	      break;
1937*38fd1498Szrj 	    default:
1938*38fd1498Szrj 	      {
1939*38fd1498Szrj 		unsigned int i;
1940*38fd1498Szrj 
1941*38fd1498Szrj 		for (i = hdr->opcode_lengths[op - 1]; i > 0; --i)
1942*38fd1498Szrj 		  read_uleb128 (line_buf);
1943*38fd1498Szrj 	      }
1944*38fd1498Szrj 	      break;
1945*38fd1498Szrj 	    }
1946*38fd1498Szrj 	}
1947*38fd1498Szrj     }
1948*38fd1498Szrj 
1949*38fd1498Szrj   return 1;
1950*38fd1498Szrj }
1951*38fd1498Szrj 
1952*38fd1498Szrj /* Read the line number information for a compilation unit.  Returns 1
1953*38fd1498Szrj    on success, 0 on failure.  */
1954*38fd1498Szrj 
1955*38fd1498Szrj 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)1956*38fd1498Szrj read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
1957*38fd1498Szrj 		backtrace_error_callback error_callback, void *data,
1958*38fd1498Szrj 		struct unit *u, struct line_header *hdr, struct line **lines,
1959*38fd1498Szrj 		size_t *lines_count)
1960*38fd1498Szrj {
1961*38fd1498Szrj   struct line_vector vec;
1962*38fd1498Szrj   struct dwarf_buf line_buf;
1963*38fd1498Szrj   uint64_t len;
1964*38fd1498Szrj   int is_dwarf64;
1965*38fd1498Szrj   struct line *ln;
1966*38fd1498Szrj 
1967*38fd1498Szrj   memset (&vec.vec, 0, sizeof vec.vec);
1968*38fd1498Szrj   vec.count = 0;
1969*38fd1498Szrj 
1970*38fd1498Szrj   memset (hdr, 0, sizeof *hdr);
1971*38fd1498Szrj 
1972*38fd1498Szrj   if (u->lineoff != (off_t) (size_t) u->lineoff
1973*38fd1498Szrj       || (size_t) u->lineoff >= ddata->dwarf_line_size)
1974*38fd1498Szrj     {
1975*38fd1498Szrj       error_callback (data, "unit line offset out of range", 0);
1976*38fd1498Szrj       goto fail;
1977*38fd1498Szrj     }
1978*38fd1498Szrj 
1979*38fd1498Szrj   line_buf.name = ".debug_line";
1980*38fd1498Szrj   line_buf.start = ddata->dwarf_line;
1981*38fd1498Szrj   line_buf.buf = ddata->dwarf_line + u->lineoff;
1982*38fd1498Szrj   line_buf.left = ddata->dwarf_line_size - u->lineoff;
1983*38fd1498Szrj   line_buf.is_bigendian = ddata->is_bigendian;
1984*38fd1498Szrj   line_buf.error_callback = error_callback;
1985*38fd1498Szrj   line_buf.data = data;
1986*38fd1498Szrj   line_buf.reported_underflow = 0;
1987*38fd1498Szrj 
1988*38fd1498Szrj   is_dwarf64 = 0;
1989*38fd1498Szrj   len = read_uint32 (&line_buf);
1990*38fd1498Szrj   if (len == 0xffffffff)
1991*38fd1498Szrj     {
1992*38fd1498Szrj       len = read_uint64 (&line_buf);
1993*38fd1498Szrj       is_dwarf64 = 1;
1994*38fd1498Szrj     }
1995*38fd1498Szrj   line_buf.left = len;
1996*38fd1498Szrj 
1997*38fd1498Szrj   if (!read_line_header (state, u, is_dwarf64, &line_buf, hdr))
1998*38fd1498Szrj     goto fail;
1999*38fd1498Szrj 
2000*38fd1498Szrj   if (!read_line_program (state, ddata, u, hdr, &line_buf, &vec))
2001*38fd1498Szrj     goto fail;
2002*38fd1498Szrj 
2003*38fd1498Szrj   if (line_buf.reported_underflow)
2004*38fd1498Szrj     goto fail;
2005*38fd1498Szrj 
2006*38fd1498Szrj   if (vec.count == 0)
2007*38fd1498Szrj     {
2008*38fd1498Szrj       /* This is not a failure in the sense of a generating an error,
2009*38fd1498Szrj 	 but it is a failure in that sense that we have no useful
2010*38fd1498Szrj 	 information.  */
2011*38fd1498Szrj       goto fail;
2012*38fd1498Szrj     }
2013*38fd1498Szrj 
2014*38fd1498Szrj   /* Allocate one extra entry at the end.  */
2015*38fd1498Szrj   ln = ((struct line *)
2016*38fd1498Szrj 	backtrace_vector_grow (state, sizeof (struct line), error_callback,
2017*38fd1498Szrj 			       data, &vec.vec));
2018*38fd1498Szrj   if (ln == NULL)
2019*38fd1498Szrj     goto fail;
2020*38fd1498Szrj   ln->pc = (uintptr_t) -1;
2021*38fd1498Szrj   ln->filename = NULL;
2022*38fd1498Szrj   ln->lineno = 0;
2023*38fd1498Szrj   ln->idx = 0;
2024*38fd1498Szrj 
2025*38fd1498Szrj   if (!backtrace_vector_release (state, &vec.vec, error_callback, data))
2026*38fd1498Szrj     goto fail;
2027*38fd1498Szrj 
2028*38fd1498Szrj   ln = (struct line *) vec.vec.base;
2029*38fd1498Szrj   backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);
2030*38fd1498Szrj 
2031*38fd1498Szrj   *lines = ln;
2032*38fd1498Szrj   *lines_count = vec.count;
2033*38fd1498Szrj 
2034*38fd1498Szrj   return 1;
2035*38fd1498Szrj 
2036*38fd1498Szrj  fail:
2037*38fd1498Szrj   vec.vec.alc += vec.vec.size;
2038*38fd1498Szrj   vec.vec.size = 0;
2039*38fd1498Szrj   backtrace_vector_release (state, &vec.vec, error_callback, data);
2040*38fd1498Szrj   free_line_header (state, hdr, error_callback, data);
2041*38fd1498Szrj   *lines = (struct line *) (uintptr_t) -1;
2042*38fd1498Szrj   *lines_count = 0;
2043*38fd1498Szrj   return 0;
2044*38fd1498Szrj }
2045*38fd1498Szrj 
2046*38fd1498Szrj /* Read the name of a function from a DIE referenced by a
2047*38fd1498Szrj    DW_AT_abstract_origin or DW_AT_specification tag.  OFFSET is within
2048*38fd1498Szrj    the same compilation unit.  */
2049*38fd1498Szrj 
2050*38fd1498Szrj static const char *
read_referenced_name(struct dwarf_data * ddata,struct unit * u,uint64_t offset,backtrace_error_callback error_callback,void * data)2051*38fd1498Szrj read_referenced_name (struct dwarf_data *ddata, struct unit *u,
2052*38fd1498Szrj 		      uint64_t offset, backtrace_error_callback error_callback,
2053*38fd1498Szrj 		      void *data)
2054*38fd1498Szrj {
2055*38fd1498Szrj   struct dwarf_buf unit_buf;
2056*38fd1498Szrj   uint64_t code;
2057*38fd1498Szrj   const struct abbrev *abbrev;
2058*38fd1498Szrj   const char *ret;
2059*38fd1498Szrj   size_t i;
2060*38fd1498Szrj 
2061*38fd1498Szrj   /* OFFSET is from the start of the data for this compilation unit.
2062*38fd1498Szrj      U->unit_data is the data, but it starts U->unit_data_offset bytes
2063*38fd1498Szrj      from the beginning.  */
2064*38fd1498Szrj 
2065*38fd1498Szrj   if (offset < u->unit_data_offset
2066*38fd1498Szrj       || offset - u->unit_data_offset >= u->unit_data_len)
2067*38fd1498Szrj     {
2068*38fd1498Szrj       error_callback (data,
2069*38fd1498Szrj 		      "abstract origin or specification out of range",
2070*38fd1498Szrj 		      0);
2071*38fd1498Szrj       return NULL;
2072*38fd1498Szrj     }
2073*38fd1498Szrj 
2074*38fd1498Szrj   offset -= u->unit_data_offset;
2075*38fd1498Szrj 
2076*38fd1498Szrj   unit_buf.name = ".debug_info";
2077*38fd1498Szrj   unit_buf.start = ddata->dwarf_info;
2078*38fd1498Szrj   unit_buf.buf = u->unit_data + offset;
2079*38fd1498Szrj   unit_buf.left = u->unit_data_len - offset;
2080*38fd1498Szrj   unit_buf.is_bigendian = ddata->is_bigendian;
2081*38fd1498Szrj   unit_buf.error_callback = error_callback;
2082*38fd1498Szrj   unit_buf.data = data;
2083*38fd1498Szrj   unit_buf.reported_underflow = 0;
2084*38fd1498Szrj 
2085*38fd1498Szrj   code = read_uleb128 (&unit_buf);
2086*38fd1498Szrj   if (code == 0)
2087*38fd1498Szrj     {
2088*38fd1498Szrj       dwarf_buf_error (&unit_buf, "invalid abstract origin or specification");
2089*38fd1498Szrj       return NULL;
2090*38fd1498Szrj     }
2091*38fd1498Szrj 
2092*38fd1498Szrj   abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
2093*38fd1498Szrj   if (abbrev == NULL)
2094*38fd1498Szrj     return NULL;
2095*38fd1498Szrj 
2096*38fd1498Szrj   ret = NULL;
2097*38fd1498Szrj   for (i = 0; i < abbrev->num_attrs; ++i)
2098*38fd1498Szrj     {
2099*38fd1498Szrj       struct attr_val val;
2100*38fd1498Szrj 
2101*38fd1498Szrj       if (!read_attribute (abbrev->attrs[i].form, &unit_buf,
2102*38fd1498Szrj 			   u->is_dwarf64, u->version, u->addrsize,
2103*38fd1498Szrj 			   ddata->dwarf_str, ddata->dwarf_str_size,
2104*38fd1498Szrj 			   &val))
2105*38fd1498Szrj 	return NULL;
2106*38fd1498Szrj 
2107*38fd1498Szrj       switch (abbrev->attrs[i].name)
2108*38fd1498Szrj 	{
2109*38fd1498Szrj 	case DW_AT_name:
2110*38fd1498Szrj 	  /* We prefer the linkage name if get one.  */
2111*38fd1498Szrj 	  if (val.encoding == ATTR_VAL_STRING)
2112*38fd1498Szrj 	    ret = val.u.string;
2113*38fd1498Szrj 	  break;
2114*38fd1498Szrj 
2115*38fd1498Szrj 	case DW_AT_linkage_name:
2116*38fd1498Szrj 	case DW_AT_MIPS_linkage_name:
2117*38fd1498Szrj 	  if (val.encoding == ATTR_VAL_STRING)
2118*38fd1498Szrj 	    return val.u.string;
2119*38fd1498Szrj 	  break;
2120*38fd1498Szrj 
2121*38fd1498Szrj 	case DW_AT_specification:
2122*38fd1498Szrj 	  if (abbrev->attrs[i].form == DW_FORM_ref_addr
2123*38fd1498Szrj 	      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
2124*38fd1498Szrj 	    {
2125*38fd1498Szrj 	      /* This refers to a specification defined in some other
2126*38fd1498Szrj 		 compilation unit.  We can handle this case if we
2127*38fd1498Szrj 		 must, but it's harder.  */
2128*38fd1498Szrj 	      break;
2129*38fd1498Szrj 	    }
2130*38fd1498Szrj 	  if (val.encoding == ATTR_VAL_UINT
2131*38fd1498Szrj 	      || val.encoding == ATTR_VAL_REF_UNIT)
2132*38fd1498Szrj 	    {
2133*38fd1498Szrj 	      const char *name;
2134*38fd1498Szrj 
2135*38fd1498Szrj 	      name = read_referenced_name (ddata, u, val.u.uint,
2136*38fd1498Szrj 					   error_callback, data);
2137*38fd1498Szrj 	      if (name != NULL)
2138*38fd1498Szrj 		ret = name;
2139*38fd1498Szrj 	    }
2140*38fd1498Szrj 	  break;
2141*38fd1498Szrj 
2142*38fd1498Szrj 	default:
2143*38fd1498Szrj 	  break;
2144*38fd1498Szrj 	}
2145*38fd1498Szrj     }
2146*38fd1498Szrj 
2147*38fd1498Szrj   return ret;
2148*38fd1498Szrj }
2149*38fd1498Szrj 
2150*38fd1498Szrj /* Add a single range to U that maps to function.  Returns 1 on
2151*38fd1498Szrj    success, 0 on error.  */
2152*38fd1498Szrj 
2153*38fd1498Szrj static int
add_function_range(struct backtrace_state * state,struct dwarf_data * ddata,struct function * function,uint64_t lowpc,uint64_t highpc,backtrace_error_callback error_callback,void * data,struct function_vector * vec)2154*38fd1498Szrj add_function_range (struct backtrace_state *state, struct dwarf_data *ddata,
2155*38fd1498Szrj 		    struct function *function, uint64_t lowpc, uint64_t highpc,
2156*38fd1498Szrj 		    backtrace_error_callback error_callback,
2157*38fd1498Szrj 		    void *data, struct function_vector *vec)
2158*38fd1498Szrj {
2159*38fd1498Szrj   struct function_addrs *p;
2160*38fd1498Szrj 
2161*38fd1498Szrj   /* Add in the base address here, so that we can look up the PC
2162*38fd1498Szrj      directly.  */
2163*38fd1498Szrj   lowpc += ddata->base_address;
2164*38fd1498Szrj   highpc += ddata->base_address;
2165*38fd1498Szrj 
2166*38fd1498Szrj   if (vec->count > 0)
2167*38fd1498Szrj     {
2168*38fd1498Szrj       p = (struct function_addrs *) vec->vec.base + vec->count - 1;
2169*38fd1498Szrj       if ((lowpc == p->high || lowpc == p->high + 1)
2170*38fd1498Szrj 	  && function == p->function)
2171*38fd1498Szrj 	{
2172*38fd1498Szrj 	  if (highpc > p->high)
2173*38fd1498Szrj 	    p->high = highpc;
2174*38fd1498Szrj 	  return 1;
2175*38fd1498Szrj 	}
2176*38fd1498Szrj     }
2177*38fd1498Szrj 
2178*38fd1498Szrj   p = ((struct function_addrs *)
2179*38fd1498Szrj        backtrace_vector_grow (state, sizeof (struct function_addrs),
2180*38fd1498Szrj 			      error_callback, data, &vec->vec));
2181*38fd1498Szrj   if (p == NULL)
2182*38fd1498Szrj     return 0;
2183*38fd1498Szrj 
2184*38fd1498Szrj   p->low = lowpc;
2185*38fd1498Szrj   p->high = highpc;
2186*38fd1498Szrj   p->function = function;
2187*38fd1498Szrj   ++vec->count;
2188*38fd1498Szrj   return 1;
2189*38fd1498Szrj }
2190*38fd1498Szrj 
2191*38fd1498Szrj /* Add PC ranges to U that map to FUNCTION.  Returns 1 on success, 0
2192*38fd1498Szrj    on error.  */
2193*38fd1498Szrj 
2194*38fd1498Szrj static int
add_function_ranges(struct backtrace_state * state,struct dwarf_data * ddata,struct unit * u,struct function * function,uint64_t ranges,uint64_t base,backtrace_error_callback error_callback,void * data,struct function_vector * vec)2195*38fd1498Szrj add_function_ranges (struct backtrace_state *state, struct dwarf_data *ddata,
2196*38fd1498Szrj 		     struct unit *u, struct function *function,
2197*38fd1498Szrj 		     uint64_t ranges, uint64_t base,
2198*38fd1498Szrj 		     backtrace_error_callback error_callback, void *data,
2199*38fd1498Szrj 		     struct function_vector *vec)
2200*38fd1498Szrj {
2201*38fd1498Szrj   struct dwarf_buf ranges_buf;
2202*38fd1498Szrj 
2203*38fd1498Szrj   if (ranges >= ddata->dwarf_ranges_size)
2204*38fd1498Szrj     {
2205*38fd1498Szrj       error_callback (data, "function ranges offset out of range", 0);
2206*38fd1498Szrj       return 0;
2207*38fd1498Szrj     }
2208*38fd1498Szrj 
2209*38fd1498Szrj   ranges_buf.name = ".debug_ranges";
2210*38fd1498Szrj   ranges_buf.start = ddata->dwarf_ranges;
2211*38fd1498Szrj   ranges_buf.buf = ddata->dwarf_ranges + ranges;
2212*38fd1498Szrj   ranges_buf.left = ddata->dwarf_ranges_size - ranges;
2213*38fd1498Szrj   ranges_buf.is_bigendian = ddata->is_bigendian;
2214*38fd1498Szrj   ranges_buf.error_callback = error_callback;
2215*38fd1498Szrj   ranges_buf.data = data;
2216*38fd1498Szrj   ranges_buf.reported_underflow = 0;
2217*38fd1498Szrj 
2218*38fd1498Szrj   while (1)
2219*38fd1498Szrj     {
2220*38fd1498Szrj       uint64_t low;
2221*38fd1498Szrj       uint64_t high;
2222*38fd1498Szrj 
2223*38fd1498Szrj       if (ranges_buf.reported_underflow)
2224*38fd1498Szrj 	return 0;
2225*38fd1498Szrj 
2226*38fd1498Szrj       low = read_address (&ranges_buf, u->addrsize);
2227*38fd1498Szrj       high = read_address (&ranges_buf, u->addrsize);
2228*38fd1498Szrj 
2229*38fd1498Szrj       if (low == 0 && high == 0)
2230*38fd1498Szrj 	break;
2231*38fd1498Szrj 
2232*38fd1498Szrj       if (is_highest_address (low, u->addrsize))
2233*38fd1498Szrj 	base = high;
2234*38fd1498Szrj       else
2235*38fd1498Szrj 	{
2236*38fd1498Szrj 	  if (!add_function_range (state, ddata, function, low + base,
2237*38fd1498Szrj 				   high + base, error_callback, data, vec))
2238*38fd1498Szrj 	    return 0;
2239*38fd1498Szrj 	}
2240*38fd1498Szrj     }
2241*38fd1498Szrj 
2242*38fd1498Szrj   if (ranges_buf.reported_underflow)
2243*38fd1498Szrj     return 0;
2244*38fd1498Szrj 
2245*38fd1498Szrj   return 1;
2246*38fd1498Szrj }
2247*38fd1498Szrj 
2248*38fd1498Szrj /* Read one entry plus all its children.  Add function addresses to
2249*38fd1498Szrj    VEC.  Returns 1 on success, 0 on error.  */
2250*38fd1498Szrj 
2251*38fd1498Szrj 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)2252*38fd1498Szrj read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
2253*38fd1498Szrj 		     struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
2254*38fd1498Szrj 		     const struct line_header *lhdr,
2255*38fd1498Szrj 		     backtrace_error_callback error_callback, void *data,
2256*38fd1498Szrj 		     struct function_vector *vec_function,
2257*38fd1498Szrj 		     struct function_vector *vec_inlined)
2258*38fd1498Szrj {
2259*38fd1498Szrj   while (unit_buf->left > 0)
2260*38fd1498Szrj     {
2261*38fd1498Szrj       uint64_t code;
2262*38fd1498Szrj       const struct abbrev *abbrev;
2263*38fd1498Szrj       int is_function;
2264*38fd1498Szrj       struct function *function;
2265*38fd1498Szrj       struct function_vector *vec;
2266*38fd1498Szrj       size_t i;
2267*38fd1498Szrj       uint64_t lowpc;
2268*38fd1498Szrj       int have_lowpc;
2269*38fd1498Szrj       uint64_t highpc;
2270*38fd1498Szrj       int have_highpc;
2271*38fd1498Szrj       int highpc_is_relative;
2272*38fd1498Szrj       uint64_t ranges;
2273*38fd1498Szrj       int have_ranges;
2274*38fd1498Szrj 
2275*38fd1498Szrj       code = read_uleb128 (unit_buf);
2276*38fd1498Szrj       if (code == 0)
2277*38fd1498Szrj 	return 1;
2278*38fd1498Szrj 
2279*38fd1498Szrj       abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
2280*38fd1498Szrj       if (abbrev == NULL)
2281*38fd1498Szrj 	return 0;
2282*38fd1498Szrj 
2283*38fd1498Szrj       is_function = (abbrev->tag == DW_TAG_subprogram
2284*38fd1498Szrj 		     || abbrev->tag == DW_TAG_entry_point
2285*38fd1498Szrj 		     || abbrev->tag == DW_TAG_inlined_subroutine);
2286*38fd1498Szrj 
2287*38fd1498Szrj       if (abbrev->tag == DW_TAG_inlined_subroutine)
2288*38fd1498Szrj 	vec = vec_inlined;
2289*38fd1498Szrj       else
2290*38fd1498Szrj 	vec = vec_function;
2291*38fd1498Szrj 
2292*38fd1498Szrj       function = NULL;
2293*38fd1498Szrj       if (is_function)
2294*38fd1498Szrj 	{
2295*38fd1498Szrj 	  function = ((struct function *)
2296*38fd1498Szrj 		      backtrace_alloc (state, sizeof *function,
2297*38fd1498Szrj 				       error_callback, data));
2298*38fd1498Szrj 	  if (function == NULL)
2299*38fd1498Szrj 	    return 0;
2300*38fd1498Szrj 	  memset (function, 0, sizeof *function);
2301*38fd1498Szrj 	}
2302*38fd1498Szrj 
2303*38fd1498Szrj       lowpc = 0;
2304*38fd1498Szrj       have_lowpc = 0;
2305*38fd1498Szrj       highpc = 0;
2306*38fd1498Szrj       have_highpc = 0;
2307*38fd1498Szrj       highpc_is_relative = 0;
2308*38fd1498Szrj       ranges = 0;
2309*38fd1498Szrj       have_ranges = 0;
2310*38fd1498Szrj       for (i = 0; i < abbrev->num_attrs; ++i)
2311*38fd1498Szrj 	{
2312*38fd1498Szrj 	  struct attr_val val;
2313*38fd1498Szrj 
2314*38fd1498Szrj 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
2315*38fd1498Szrj 			       u->is_dwarf64, u->version, u->addrsize,
2316*38fd1498Szrj 			       ddata->dwarf_str, ddata->dwarf_str_size,
2317*38fd1498Szrj 			       &val))
2318*38fd1498Szrj 	    return 0;
2319*38fd1498Szrj 
2320*38fd1498Szrj 	  /* The compile unit sets the base address for any address
2321*38fd1498Szrj 	     ranges in the function entries.  */
2322*38fd1498Szrj 	  if (abbrev->tag == DW_TAG_compile_unit
2323*38fd1498Szrj 	      && abbrev->attrs[i].name == DW_AT_low_pc
2324*38fd1498Szrj 	      && val.encoding == ATTR_VAL_ADDRESS)
2325*38fd1498Szrj 	    base = val.u.uint;
2326*38fd1498Szrj 
2327*38fd1498Szrj 	  if (is_function)
2328*38fd1498Szrj 	    {
2329*38fd1498Szrj 	      switch (abbrev->attrs[i].name)
2330*38fd1498Szrj 		{
2331*38fd1498Szrj 		case DW_AT_call_file:
2332*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_UINT)
2333*38fd1498Szrj 		    {
2334*38fd1498Szrj 		      if (val.u.uint == 0)
2335*38fd1498Szrj 			function->caller_filename = "";
2336*38fd1498Szrj 		      else
2337*38fd1498Szrj 			{
2338*38fd1498Szrj 			  if (val.u.uint - 1 >= lhdr->filenames_count)
2339*38fd1498Szrj 			    {
2340*38fd1498Szrj 			      dwarf_buf_error (unit_buf,
2341*38fd1498Szrj 					       ("invalid file number in "
2342*38fd1498Szrj 						"DW_AT_call_file attribute"));
2343*38fd1498Szrj 			      return 0;
2344*38fd1498Szrj 			    }
2345*38fd1498Szrj 			  function->caller_filename =
2346*38fd1498Szrj 			    lhdr->filenames[val.u.uint - 1];
2347*38fd1498Szrj 			}
2348*38fd1498Szrj 		    }
2349*38fd1498Szrj 		  break;
2350*38fd1498Szrj 
2351*38fd1498Szrj 		case DW_AT_call_line:
2352*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_UINT)
2353*38fd1498Szrj 		    function->caller_lineno = val.u.uint;
2354*38fd1498Szrj 		  break;
2355*38fd1498Szrj 
2356*38fd1498Szrj 		case DW_AT_abstract_origin:
2357*38fd1498Szrj 		case DW_AT_specification:
2358*38fd1498Szrj 		  if (abbrev->attrs[i].form == DW_FORM_ref_addr
2359*38fd1498Szrj 		      || abbrev->attrs[i].form == DW_FORM_ref_sig8)
2360*38fd1498Szrj 		    {
2361*38fd1498Szrj 		      /* This refers to an abstract origin defined in
2362*38fd1498Szrj 			 some other compilation unit.  We can handle
2363*38fd1498Szrj 			 this case if we must, but it's harder.  */
2364*38fd1498Szrj 		      break;
2365*38fd1498Szrj 		    }
2366*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_UINT
2367*38fd1498Szrj 		      || val.encoding == ATTR_VAL_REF_UNIT)
2368*38fd1498Szrj 		    {
2369*38fd1498Szrj 		      const char *name;
2370*38fd1498Szrj 
2371*38fd1498Szrj 		      name = read_referenced_name (ddata, u, val.u.uint,
2372*38fd1498Szrj 						   error_callback, data);
2373*38fd1498Szrj 		      if (name != NULL)
2374*38fd1498Szrj 			function->name = name;
2375*38fd1498Szrj 		    }
2376*38fd1498Szrj 		  break;
2377*38fd1498Szrj 
2378*38fd1498Szrj 		case DW_AT_name:
2379*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_STRING)
2380*38fd1498Szrj 		    {
2381*38fd1498Szrj 		      /* Don't override a name we found in some other
2382*38fd1498Szrj 			 way, as it will normally be more
2383*38fd1498Szrj 			 useful--e.g., this name is normally not
2384*38fd1498Szrj 			 mangled.  */
2385*38fd1498Szrj 		      if (function->name == NULL)
2386*38fd1498Szrj 			function->name = val.u.string;
2387*38fd1498Szrj 		    }
2388*38fd1498Szrj 		  break;
2389*38fd1498Szrj 
2390*38fd1498Szrj 		case DW_AT_linkage_name:
2391*38fd1498Szrj 		case DW_AT_MIPS_linkage_name:
2392*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_STRING)
2393*38fd1498Szrj 		    function->name = val.u.string;
2394*38fd1498Szrj 		  break;
2395*38fd1498Szrj 
2396*38fd1498Szrj 		case DW_AT_low_pc:
2397*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_ADDRESS)
2398*38fd1498Szrj 		    {
2399*38fd1498Szrj 		      lowpc = val.u.uint;
2400*38fd1498Szrj 		      have_lowpc = 1;
2401*38fd1498Szrj 		    }
2402*38fd1498Szrj 		  break;
2403*38fd1498Szrj 
2404*38fd1498Szrj 		case DW_AT_high_pc:
2405*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_ADDRESS)
2406*38fd1498Szrj 		    {
2407*38fd1498Szrj 		      highpc = val.u.uint;
2408*38fd1498Szrj 		      have_highpc = 1;
2409*38fd1498Szrj 		    }
2410*38fd1498Szrj 		  else if (val.encoding == ATTR_VAL_UINT)
2411*38fd1498Szrj 		    {
2412*38fd1498Szrj 		      highpc = val.u.uint;
2413*38fd1498Szrj 		      have_highpc = 1;
2414*38fd1498Szrj 		      highpc_is_relative = 1;
2415*38fd1498Szrj 		    }
2416*38fd1498Szrj 		  break;
2417*38fd1498Szrj 
2418*38fd1498Szrj 		case DW_AT_ranges:
2419*38fd1498Szrj 		  if (val.encoding == ATTR_VAL_UINT
2420*38fd1498Szrj 		      || val.encoding == ATTR_VAL_REF_SECTION)
2421*38fd1498Szrj 		    {
2422*38fd1498Szrj 		      ranges = val.u.uint;
2423*38fd1498Szrj 		      have_ranges = 1;
2424*38fd1498Szrj 		    }
2425*38fd1498Szrj 		  break;
2426*38fd1498Szrj 
2427*38fd1498Szrj 		default:
2428*38fd1498Szrj 		  break;
2429*38fd1498Szrj 		}
2430*38fd1498Szrj 	    }
2431*38fd1498Szrj 	}
2432*38fd1498Szrj 
2433*38fd1498Szrj       /* If we couldn't find a name for the function, we have no use
2434*38fd1498Szrj 	 for it.  */
2435*38fd1498Szrj       if (is_function && function->name == NULL)
2436*38fd1498Szrj 	{
2437*38fd1498Szrj 	  backtrace_free (state, function, sizeof *function,
2438*38fd1498Szrj 			  error_callback, data);
2439*38fd1498Szrj 	  is_function = 0;
2440*38fd1498Szrj 	}
2441*38fd1498Szrj 
2442*38fd1498Szrj       if (is_function)
2443*38fd1498Szrj 	{
2444*38fd1498Szrj 	  if (have_ranges)
2445*38fd1498Szrj 	    {
2446*38fd1498Szrj 	      if (!add_function_ranges (state, ddata, u, function, ranges,
2447*38fd1498Szrj 					base, error_callback, data, vec))
2448*38fd1498Szrj 		return 0;
2449*38fd1498Szrj 	    }
2450*38fd1498Szrj 	  else if (have_lowpc && have_highpc)
2451*38fd1498Szrj 	    {
2452*38fd1498Szrj 	      if (highpc_is_relative)
2453*38fd1498Szrj 		highpc += lowpc;
2454*38fd1498Szrj 	      if (!add_function_range (state, ddata, function, lowpc, highpc,
2455*38fd1498Szrj 				       error_callback, data, vec))
2456*38fd1498Szrj 		return 0;
2457*38fd1498Szrj 	    }
2458*38fd1498Szrj 	  else
2459*38fd1498Szrj 	    {
2460*38fd1498Szrj 	      backtrace_free (state, function, sizeof *function,
2461*38fd1498Szrj 			      error_callback, data);
2462*38fd1498Szrj 	      is_function = 0;
2463*38fd1498Szrj 	    }
2464*38fd1498Szrj 	}
2465*38fd1498Szrj 
2466*38fd1498Szrj       if (abbrev->has_children)
2467*38fd1498Szrj 	{
2468*38fd1498Szrj 	  if (!is_function)
2469*38fd1498Szrj 	    {
2470*38fd1498Szrj 	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
2471*38fd1498Szrj 					error_callback, data, vec_function,
2472*38fd1498Szrj 					vec_inlined))
2473*38fd1498Szrj 		return 0;
2474*38fd1498Szrj 	    }
2475*38fd1498Szrj 	  else
2476*38fd1498Szrj 	    {
2477*38fd1498Szrj 	      struct function_vector fvec;
2478*38fd1498Szrj 
2479*38fd1498Szrj 	      /* Gather any information for inlined functions in
2480*38fd1498Szrj 		 FVEC.  */
2481*38fd1498Szrj 
2482*38fd1498Szrj 	      memset (&fvec, 0, sizeof fvec);
2483*38fd1498Szrj 
2484*38fd1498Szrj 	      if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
2485*38fd1498Szrj 					error_callback, data, vec_function,
2486*38fd1498Szrj 					&fvec))
2487*38fd1498Szrj 		return 0;
2488*38fd1498Szrj 
2489*38fd1498Szrj 	      if (fvec.count > 0)
2490*38fd1498Szrj 		{
2491*38fd1498Szrj 		  struct function_addrs *faddrs;
2492*38fd1498Szrj 
2493*38fd1498Szrj 		  if (!backtrace_vector_release (state, &fvec.vec,
2494*38fd1498Szrj 						 error_callback, data))
2495*38fd1498Szrj 		    return 0;
2496*38fd1498Szrj 
2497*38fd1498Szrj 		  faddrs = (struct function_addrs *) fvec.vec.base;
2498*38fd1498Szrj 		  backtrace_qsort (faddrs, fvec.count,
2499*38fd1498Szrj 				   sizeof (struct function_addrs),
2500*38fd1498Szrj 				   function_addrs_compare);
2501*38fd1498Szrj 
2502*38fd1498Szrj 		  function->function_addrs = faddrs;
2503*38fd1498Szrj 		  function->function_addrs_count = fvec.count;
2504*38fd1498Szrj 		}
2505*38fd1498Szrj 	    }
2506*38fd1498Szrj 	}
2507*38fd1498Szrj     }
2508*38fd1498Szrj 
2509*38fd1498Szrj   return 1;
2510*38fd1498Szrj }
2511*38fd1498Szrj 
2512*38fd1498Szrj /* Read function name information for a compilation unit.  We look
2513*38fd1498Szrj    through the whole unit looking for function tags.  */
2514*38fd1498Szrj 
2515*38fd1498Szrj 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)2516*38fd1498Szrj read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
2517*38fd1498Szrj 		    const struct line_header *lhdr,
2518*38fd1498Szrj 		    backtrace_error_callback error_callback, void *data,
2519*38fd1498Szrj 		    struct unit *u, struct function_vector *fvec,
2520*38fd1498Szrj 		    struct function_addrs **ret_addrs,
2521*38fd1498Szrj 		    size_t *ret_addrs_count)
2522*38fd1498Szrj {
2523*38fd1498Szrj   struct function_vector lvec;
2524*38fd1498Szrj   struct function_vector *pfvec;
2525*38fd1498Szrj   struct dwarf_buf unit_buf;
2526*38fd1498Szrj   struct function_addrs *addrs;
2527*38fd1498Szrj   size_t addrs_count;
2528*38fd1498Szrj 
2529*38fd1498Szrj   /* Use FVEC if it is not NULL.  Otherwise use our own vector.  */
2530*38fd1498Szrj   if (fvec != NULL)
2531*38fd1498Szrj     pfvec = fvec;
2532*38fd1498Szrj   else
2533*38fd1498Szrj     {
2534*38fd1498Szrj       memset (&lvec, 0, sizeof lvec);
2535*38fd1498Szrj       pfvec = &lvec;
2536*38fd1498Szrj     }
2537*38fd1498Szrj 
2538*38fd1498Szrj   unit_buf.name = ".debug_info";
2539*38fd1498Szrj   unit_buf.start = ddata->dwarf_info;
2540*38fd1498Szrj   unit_buf.buf = u->unit_data;
2541*38fd1498Szrj   unit_buf.left = u->unit_data_len;
2542*38fd1498Szrj   unit_buf.is_bigendian = ddata->is_bigendian;
2543*38fd1498Szrj   unit_buf.error_callback = error_callback;
2544*38fd1498Szrj   unit_buf.data = data;
2545*38fd1498Szrj   unit_buf.reported_underflow = 0;
2546*38fd1498Szrj 
2547*38fd1498Szrj   while (unit_buf.left > 0)
2548*38fd1498Szrj     {
2549*38fd1498Szrj       if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,
2550*38fd1498Szrj 				error_callback, data, pfvec, pfvec))
2551*38fd1498Szrj 	return;
2552*38fd1498Szrj     }
2553*38fd1498Szrj 
2554*38fd1498Szrj   if (pfvec->count == 0)
2555*38fd1498Szrj     return;
2556*38fd1498Szrj 
2557*38fd1498Szrj   addrs_count = pfvec->count;
2558*38fd1498Szrj 
2559*38fd1498Szrj   if (fvec == NULL)
2560*38fd1498Szrj     {
2561*38fd1498Szrj       if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))
2562*38fd1498Szrj 	return;
2563*38fd1498Szrj       addrs = (struct function_addrs *) pfvec->vec.base;
2564*38fd1498Szrj     }
2565*38fd1498Szrj   else
2566*38fd1498Szrj     {
2567*38fd1498Szrj       /* Finish this list of addresses, but leave the remaining space in
2568*38fd1498Szrj 	 the vector available for the next function unit.  */
2569*38fd1498Szrj       addrs = ((struct function_addrs *)
2570*38fd1498Szrj 	       backtrace_vector_finish (state, &fvec->vec,
2571*38fd1498Szrj 					error_callback, data));
2572*38fd1498Szrj       if (addrs == NULL)
2573*38fd1498Szrj 	return;
2574*38fd1498Szrj       fvec->count = 0;
2575*38fd1498Szrj     }
2576*38fd1498Szrj 
2577*38fd1498Szrj   backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),
2578*38fd1498Szrj 		   function_addrs_compare);
2579*38fd1498Szrj 
2580*38fd1498Szrj   *ret_addrs = addrs;
2581*38fd1498Szrj   *ret_addrs_count = addrs_count;
2582*38fd1498Szrj }
2583*38fd1498Szrj 
2584*38fd1498Szrj /* See if PC is inlined in FUNCTION.  If it is, print out the inlined
2585*38fd1498Szrj    information, and update FILENAME and LINENO for the caller.
2586*38fd1498Szrj    Returns whatever CALLBACK returns, or 0 to keep going.  */
2587*38fd1498Szrj 
2588*38fd1498Szrj static int
report_inlined_functions(uintptr_t pc,struct function * function,backtrace_full_callback callback,void * data,const char ** filename,int * lineno)2589*38fd1498Szrj report_inlined_functions (uintptr_t pc, struct function *function,
2590*38fd1498Szrj 			  backtrace_full_callback callback, void *data,
2591*38fd1498Szrj 			  const char **filename, int *lineno)
2592*38fd1498Szrj {
2593*38fd1498Szrj   struct function_addrs *function_addrs;
2594*38fd1498Szrj   struct function *inlined;
2595*38fd1498Szrj   int ret;
2596*38fd1498Szrj 
2597*38fd1498Szrj   if (function->function_addrs_count == 0)
2598*38fd1498Szrj     return 0;
2599*38fd1498Szrj 
2600*38fd1498Szrj   function_addrs = ((struct function_addrs *)
2601*38fd1498Szrj 		    bsearch (&pc, function->function_addrs,
2602*38fd1498Szrj 			     function->function_addrs_count,
2603*38fd1498Szrj 			     sizeof (struct function_addrs),
2604*38fd1498Szrj 			     function_addrs_search));
2605*38fd1498Szrj   if (function_addrs == NULL)
2606*38fd1498Szrj     return 0;
2607*38fd1498Szrj 
2608*38fd1498Szrj   while (((size_t) (function_addrs - function->function_addrs) + 1
2609*38fd1498Szrj 	  < function->function_addrs_count)
2610*38fd1498Szrj 	 && pc >= (function_addrs + 1)->low
2611*38fd1498Szrj 	 && pc < (function_addrs + 1)->high)
2612*38fd1498Szrj     ++function_addrs;
2613*38fd1498Szrj 
2614*38fd1498Szrj   /* We found an inlined call.  */
2615*38fd1498Szrj 
2616*38fd1498Szrj   inlined = function_addrs->function;
2617*38fd1498Szrj 
2618*38fd1498Szrj   /* Report any calls inlined into this one.  */
2619*38fd1498Szrj   ret = report_inlined_functions (pc, inlined, callback, data,
2620*38fd1498Szrj 				  filename, lineno);
2621*38fd1498Szrj   if (ret != 0)
2622*38fd1498Szrj     return ret;
2623*38fd1498Szrj 
2624*38fd1498Szrj   /* Report this inlined call.  */
2625*38fd1498Szrj   ret = callback (data, pc, *filename, *lineno, inlined->name);
2626*38fd1498Szrj   if (ret != 0)
2627*38fd1498Szrj     return ret;
2628*38fd1498Szrj 
2629*38fd1498Szrj   /* Our caller will report the caller of the inlined function; tell
2630*38fd1498Szrj      it the appropriate filename and line number.  */
2631*38fd1498Szrj   *filename = inlined->caller_filename;
2632*38fd1498Szrj   *lineno = inlined->caller_lineno;
2633*38fd1498Szrj 
2634*38fd1498Szrj   return 0;
2635*38fd1498Szrj }
2636*38fd1498Szrj 
2637*38fd1498Szrj /* Look for a PC in the DWARF mapping for one module.  On success,
2638*38fd1498Szrj    call CALLBACK and return whatever it returns.  On error, call
2639*38fd1498Szrj    ERROR_CALLBACK and return 0.  Sets *FOUND to 1 if the PC is found,
2640*38fd1498Szrj    0 if not.  */
2641*38fd1498Szrj 
2642*38fd1498Szrj 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)2643*38fd1498Szrj dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
2644*38fd1498Szrj 		 uintptr_t pc, backtrace_full_callback callback,
2645*38fd1498Szrj 		 backtrace_error_callback error_callback, void *data,
2646*38fd1498Szrj 		 int *found)
2647*38fd1498Szrj {
2648*38fd1498Szrj   struct unit_addrs *entry;
2649*38fd1498Szrj   struct unit *u;
2650*38fd1498Szrj   int new_data;
2651*38fd1498Szrj   struct line *lines;
2652*38fd1498Szrj   struct line *ln;
2653*38fd1498Szrj   struct function_addrs *function_addrs;
2654*38fd1498Szrj   struct function *function;
2655*38fd1498Szrj   const char *filename;
2656*38fd1498Szrj   int lineno;
2657*38fd1498Szrj   int ret;
2658*38fd1498Szrj 
2659*38fd1498Szrj   *found = 1;
2660*38fd1498Szrj 
2661*38fd1498Szrj   /* Find an address range that includes PC.  */
2662*38fd1498Szrj   entry = bsearch (&pc, ddata->addrs, ddata->addrs_count,
2663*38fd1498Szrj 		   sizeof (struct unit_addrs), unit_addrs_search);
2664*38fd1498Szrj 
2665*38fd1498Szrj   if (entry == NULL)
2666*38fd1498Szrj     {
2667*38fd1498Szrj       *found = 0;
2668*38fd1498Szrj       return 0;
2669*38fd1498Szrj     }
2670*38fd1498Szrj 
2671*38fd1498Szrj   /* If there are multiple ranges that contain PC, use the last one,
2672*38fd1498Szrj      in order to produce predictable results.  If we assume that all
2673*38fd1498Szrj      ranges are properly nested, then the last range will be the
2674*38fd1498Szrj      smallest one.  */
2675*38fd1498Szrj   while ((size_t) (entry - ddata->addrs) + 1 < ddata->addrs_count
2676*38fd1498Szrj 	 && pc >= (entry + 1)->low
2677*38fd1498Szrj 	 && pc < (entry + 1)->high)
2678*38fd1498Szrj     ++entry;
2679*38fd1498Szrj 
2680*38fd1498Szrj   /* We need the lines, lines_count, function_addrs,
2681*38fd1498Szrj      function_addrs_count fields of u.  If they are not set, we need
2682*38fd1498Szrj      to set them.  When running in threaded mode, we need to allow for
2683*38fd1498Szrj      the possibility that some other thread is setting them
2684*38fd1498Szrj      simultaneously.  */
2685*38fd1498Szrj 
2686*38fd1498Szrj   u = entry->u;
2687*38fd1498Szrj   lines = u->lines;
2688*38fd1498Szrj 
2689*38fd1498Szrj   /* Skip units with no useful line number information by walking
2690*38fd1498Szrj      backward.  Useless line number information is marked by setting
2691*38fd1498Szrj      lines == -1.  */
2692*38fd1498Szrj   while (entry > ddata->addrs
2693*38fd1498Szrj 	 && pc >= (entry - 1)->low
2694*38fd1498Szrj 	 && pc < (entry - 1)->high)
2695*38fd1498Szrj     {
2696*38fd1498Szrj       if (state->threaded)
2697*38fd1498Szrj 	lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);
2698*38fd1498Szrj 
2699*38fd1498Szrj       if (lines != (struct line *) (uintptr_t) -1)
2700*38fd1498Szrj 	break;
2701*38fd1498Szrj 
2702*38fd1498Szrj       --entry;
2703*38fd1498Szrj 
2704*38fd1498Szrj       u = entry->u;
2705*38fd1498Szrj       lines = u->lines;
2706*38fd1498Szrj     }
2707*38fd1498Szrj 
2708*38fd1498Szrj   if (state->threaded)
2709*38fd1498Szrj     lines = backtrace_atomic_load_pointer (&u->lines);
2710*38fd1498Szrj 
2711*38fd1498Szrj   new_data = 0;
2712*38fd1498Szrj   if (lines == NULL)
2713*38fd1498Szrj     {
2714*38fd1498Szrj       size_t function_addrs_count;
2715*38fd1498Szrj       struct line_header lhdr;
2716*38fd1498Szrj       size_t count;
2717*38fd1498Szrj 
2718*38fd1498Szrj       /* We have never read the line information for this unit.  Read
2719*38fd1498Szrj 	 it now.  */
2720*38fd1498Szrj 
2721*38fd1498Szrj       function_addrs = NULL;
2722*38fd1498Szrj       function_addrs_count = 0;
2723*38fd1498Szrj       if (read_line_info (state, ddata, error_callback, data, entry->u, &lhdr,
2724*38fd1498Szrj 			  &lines, &count))
2725*38fd1498Szrj 	{
2726*38fd1498Szrj 	  struct function_vector *pfvec;
2727*38fd1498Szrj 
2728*38fd1498Szrj 	  /* If not threaded, reuse DDATA->FVEC for better memory
2729*38fd1498Szrj 	     consumption.  */
2730*38fd1498Szrj 	  if (state->threaded)
2731*38fd1498Szrj 	    pfvec = NULL;
2732*38fd1498Szrj 	  else
2733*38fd1498Szrj 	    pfvec = &ddata->fvec;
2734*38fd1498Szrj 	  read_function_info (state, ddata, &lhdr, error_callback, data,
2735*38fd1498Szrj 			      entry->u, pfvec, &function_addrs,
2736*38fd1498Szrj 			      &function_addrs_count);
2737*38fd1498Szrj 	  free_line_header (state, &lhdr, error_callback, data);
2738*38fd1498Szrj 	  new_data = 1;
2739*38fd1498Szrj 	}
2740*38fd1498Szrj 
2741*38fd1498Szrj       /* Atomically store the information we just read into the unit.
2742*38fd1498Szrj 	 If another thread is simultaneously writing, it presumably
2743*38fd1498Szrj 	 read the same information, and we don't care which one we
2744*38fd1498Szrj 	 wind up with; we just leak the other one.  We do have to
2745*38fd1498Szrj 	 write the lines field last, so that the acquire-loads above
2746*38fd1498Szrj 	 ensure that the other fields are set.  */
2747*38fd1498Szrj 
2748*38fd1498Szrj       if (!state->threaded)
2749*38fd1498Szrj 	{
2750*38fd1498Szrj 	  u->lines_count = count;
2751*38fd1498Szrj 	  u->function_addrs = function_addrs;
2752*38fd1498Szrj 	  u->function_addrs_count = function_addrs_count;
2753*38fd1498Szrj 	  u->lines = lines;
2754*38fd1498Szrj 	}
2755*38fd1498Szrj       else
2756*38fd1498Szrj 	{
2757*38fd1498Szrj 	  backtrace_atomic_store_size_t (&u->lines_count, count);
2758*38fd1498Szrj 	  backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);
2759*38fd1498Szrj 	  backtrace_atomic_store_size_t (&u->function_addrs_count,
2760*38fd1498Szrj 					 function_addrs_count);
2761*38fd1498Szrj 	  backtrace_atomic_store_pointer (&u->lines, lines);
2762*38fd1498Szrj 	}
2763*38fd1498Szrj     }
2764*38fd1498Szrj 
2765*38fd1498Szrj   /* Now all fields of U have been initialized.  */
2766*38fd1498Szrj 
2767*38fd1498Szrj   if (lines == (struct line *) (uintptr_t) -1)
2768*38fd1498Szrj     {
2769*38fd1498Szrj       /* If reading the line number information failed in some way,
2770*38fd1498Szrj 	 try again to see if there is a better compilation unit for
2771*38fd1498Szrj 	 this PC.  */
2772*38fd1498Szrj       if (new_data)
2773*38fd1498Szrj 	return dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
2774*38fd1498Szrj 				data, found);
2775*38fd1498Szrj       return callback (data, pc, NULL, 0, NULL);
2776*38fd1498Szrj     }
2777*38fd1498Szrj 
2778*38fd1498Szrj   /* Search for PC within this unit.  */
2779*38fd1498Szrj 
2780*38fd1498Szrj   ln = (struct line *) bsearch (&pc, lines, entry->u->lines_count,
2781*38fd1498Szrj 				sizeof (struct line), line_search);
2782*38fd1498Szrj   if (ln == NULL)
2783*38fd1498Szrj     {
2784*38fd1498Szrj       /* The PC is between the low_pc and high_pc attributes of the
2785*38fd1498Szrj 	 compilation unit, but no entry in the line table covers it.
2786*38fd1498Szrj 	 This implies that the start of the compilation unit has no
2787*38fd1498Szrj 	 line number information.  */
2788*38fd1498Szrj 
2789*38fd1498Szrj       if (entry->u->abs_filename == NULL)
2790*38fd1498Szrj 	{
2791*38fd1498Szrj 	  const char *filename;
2792*38fd1498Szrj 
2793*38fd1498Szrj 	  filename = entry->u->filename;
2794*38fd1498Szrj 	  if (filename != NULL
2795*38fd1498Szrj 	      && !IS_ABSOLUTE_PATH (filename)
2796*38fd1498Szrj 	      && entry->u->comp_dir != NULL)
2797*38fd1498Szrj 	    {
2798*38fd1498Szrj 	      size_t filename_len;
2799*38fd1498Szrj 	      const char *dir;
2800*38fd1498Szrj 	      size_t dir_len;
2801*38fd1498Szrj 	      char *s;
2802*38fd1498Szrj 
2803*38fd1498Szrj 	      filename_len = strlen (filename);
2804*38fd1498Szrj 	      dir = entry->u->comp_dir;
2805*38fd1498Szrj 	      dir_len = strlen (dir);
2806*38fd1498Szrj 	      s = (char *) backtrace_alloc (state, dir_len + filename_len + 2,
2807*38fd1498Szrj 					    error_callback, data);
2808*38fd1498Szrj 	      if (s == NULL)
2809*38fd1498Szrj 		{
2810*38fd1498Szrj 		  *found = 0;
2811*38fd1498Szrj 		  return 0;
2812*38fd1498Szrj 		}
2813*38fd1498Szrj 	      memcpy (s, dir, dir_len);
2814*38fd1498Szrj 	      /* FIXME: Should use backslash if DOS file system.  */
2815*38fd1498Szrj 	      s[dir_len] = '/';
2816*38fd1498Szrj 	      memcpy (s + dir_len + 1, filename, filename_len + 1);
2817*38fd1498Szrj 	      filename = s;
2818*38fd1498Szrj 	    }
2819*38fd1498Szrj 	  entry->u->abs_filename = filename;
2820*38fd1498Szrj 	}
2821*38fd1498Szrj 
2822*38fd1498Szrj       return callback (data, pc, entry->u->abs_filename, 0, NULL);
2823*38fd1498Szrj     }
2824*38fd1498Szrj 
2825*38fd1498Szrj   /* Search for function name within this unit.  */
2826*38fd1498Szrj 
2827*38fd1498Szrj   if (entry->u->function_addrs_count == 0)
2828*38fd1498Szrj     return callback (data, pc, ln->filename, ln->lineno, NULL);
2829*38fd1498Szrj 
2830*38fd1498Szrj   function_addrs = ((struct function_addrs *)
2831*38fd1498Szrj 		    bsearch (&pc, entry->u->function_addrs,
2832*38fd1498Szrj 			     entry->u->function_addrs_count,
2833*38fd1498Szrj 			     sizeof (struct function_addrs),
2834*38fd1498Szrj 			     function_addrs_search));
2835*38fd1498Szrj   if (function_addrs == NULL)
2836*38fd1498Szrj     return callback (data, pc, ln->filename, ln->lineno, NULL);
2837*38fd1498Szrj 
2838*38fd1498Szrj   /* If there are multiple function ranges that contain PC, use the
2839*38fd1498Szrj      last one, in order to produce predictable results.  */
2840*38fd1498Szrj 
2841*38fd1498Szrj   while (((size_t) (function_addrs - entry->u->function_addrs + 1)
2842*38fd1498Szrj 	  < entry->u->function_addrs_count)
2843*38fd1498Szrj 	 && pc >= (function_addrs + 1)->low
2844*38fd1498Szrj 	 && pc < (function_addrs + 1)->high)
2845*38fd1498Szrj     ++function_addrs;
2846*38fd1498Szrj 
2847*38fd1498Szrj   function = function_addrs->function;
2848*38fd1498Szrj 
2849*38fd1498Szrj   filename = ln->filename;
2850*38fd1498Szrj   lineno = ln->lineno;
2851*38fd1498Szrj 
2852*38fd1498Szrj   ret = report_inlined_functions (pc, function, callback, data,
2853*38fd1498Szrj 				  &filename, &lineno);
2854*38fd1498Szrj   if (ret != 0)
2855*38fd1498Szrj     return ret;
2856*38fd1498Szrj 
2857*38fd1498Szrj   return callback (data, pc, filename, lineno, function->name);
2858*38fd1498Szrj }
2859*38fd1498Szrj 
2860*38fd1498Szrj 
2861*38fd1498Szrj /* Return the file/line information for a PC using the DWARF mapping
2862*38fd1498Szrj    we built earlier.  */
2863*38fd1498Szrj 
2864*38fd1498Szrj static int
dwarf_fileline(struct backtrace_state * state,uintptr_t pc,backtrace_full_callback callback,backtrace_error_callback error_callback,void * data)2865*38fd1498Szrj dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
2866*38fd1498Szrj 		backtrace_full_callback callback,
2867*38fd1498Szrj 		backtrace_error_callback error_callback, void *data)
2868*38fd1498Szrj {
2869*38fd1498Szrj   struct dwarf_data *ddata;
2870*38fd1498Szrj   int found;
2871*38fd1498Szrj   int ret;
2872*38fd1498Szrj 
2873*38fd1498Szrj   if (!state->threaded)
2874*38fd1498Szrj     {
2875*38fd1498Szrj       for (ddata = (struct dwarf_data *) state->fileline_data;
2876*38fd1498Szrj 	   ddata != NULL;
2877*38fd1498Szrj 	   ddata = ddata->next)
2878*38fd1498Szrj 	{
2879*38fd1498Szrj 	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
2880*38fd1498Szrj 				 data, &found);
2881*38fd1498Szrj 	  if (ret != 0 || found)
2882*38fd1498Szrj 	    return ret;
2883*38fd1498Szrj 	}
2884*38fd1498Szrj     }
2885*38fd1498Szrj   else
2886*38fd1498Szrj     {
2887*38fd1498Szrj       struct dwarf_data **pp;
2888*38fd1498Szrj 
2889*38fd1498Szrj       pp = (struct dwarf_data **) (void *) &state->fileline_data;
2890*38fd1498Szrj       while (1)
2891*38fd1498Szrj 	{
2892*38fd1498Szrj 	  ddata = backtrace_atomic_load_pointer (pp);
2893*38fd1498Szrj 	  if (ddata == NULL)
2894*38fd1498Szrj 	    break;
2895*38fd1498Szrj 
2896*38fd1498Szrj 	  ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
2897*38fd1498Szrj 				 data, &found);
2898*38fd1498Szrj 	  if (ret != 0 || found)
2899*38fd1498Szrj 	    return ret;
2900*38fd1498Szrj 
2901*38fd1498Szrj 	  pp = &ddata->next;
2902*38fd1498Szrj 	}
2903*38fd1498Szrj     }
2904*38fd1498Szrj 
2905*38fd1498Szrj   /* FIXME: See if any libraries have been dlopen'ed.  */
2906*38fd1498Szrj 
2907*38fd1498Szrj   return callback (data, pc, NULL, 0, NULL);
2908*38fd1498Szrj }
2909*38fd1498Szrj 
2910*38fd1498Szrj /* Initialize our data structures from the DWARF debug info for a
2911*38fd1498Szrj    file.  Return NULL on failure.  */
2912*38fd1498Szrj 
2913*38fd1498Szrj static struct dwarf_data *
build_dwarf_data(struct backtrace_state * state,uintptr_t base_address,const unsigned char * dwarf_info,size_t dwarf_info_size,const unsigned char * dwarf_line,size_t dwarf_line_size,const unsigned char * dwarf_abbrev,size_t dwarf_abbrev_size,const unsigned char * dwarf_ranges,size_t dwarf_ranges_size,const unsigned char * dwarf_str,size_t dwarf_str_size,int is_bigendian,backtrace_error_callback error_callback,void * data)2914*38fd1498Szrj build_dwarf_data (struct backtrace_state *state,
2915*38fd1498Szrj 		  uintptr_t base_address,
2916*38fd1498Szrj 		  const unsigned char *dwarf_info,
2917*38fd1498Szrj 		  size_t dwarf_info_size,
2918*38fd1498Szrj 		  const unsigned char *dwarf_line,
2919*38fd1498Szrj 		  size_t dwarf_line_size,
2920*38fd1498Szrj 		  const unsigned char *dwarf_abbrev,
2921*38fd1498Szrj 		  size_t dwarf_abbrev_size,
2922*38fd1498Szrj 		  const unsigned char *dwarf_ranges,
2923*38fd1498Szrj 		  size_t dwarf_ranges_size,
2924*38fd1498Szrj 		  const unsigned char *dwarf_str,
2925*38fd1498Szrj 		  size_t dwarf_str_size,
2926*38fd1498Szrj 		  int is_bigendian,
2927*38fd1498Szrj 		  backtrace_error_callback error_callback,
2928*38fd1498Szrj 		  void *data)
2929*38fd1498Szrj {
2930*38fd1498Szrj   struct unit_addrs_vector addrs_vec;
2931*38fd1498Szrj   struct unit_addrs *addrs;
2932*38fd1498Szrj   size_t addrs_count;
2933*38fd1498Szrj   struct dwarf_data *fdata;
2934*38fd1498Szrj 
2935*38fd1498Szrj   if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size,
2936*38fd1498Szrj 			  dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges,
2937*38fd1498Szrj 			  dwarf_ranges_size, dwarf_str, dwarf_str_size,
2938*38fd1498Szrj 			  is_bigendian, error_callback, data, &addrs_vec))
2939*38fd1498Szrj     return NULL;
2940*38fd1498Szrj 
2941*38fd1498Szrj   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
2942*38fd1498Szrj     return NULL;
2943*38fd1498Szrj   addrs = (struct unit_addrs *) addrs_vec.vec.base;
2944*38fd1498Szrj   addrs_count = addrs_vec.count;
2945*38fd1498Szrj   backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
2946*38fd1498Szrj 		   unit_addrs_compare);
2947*38fd1498Szrj 
2948*38fd1498Szrj   fdata = ((struct dwarf_data *)
2949*38fd1498Szrj 	   backtrace_alloc (state, sizeof (struct dwarf_data),
2950*38fd1498Szrj 			    error_callback, data));
2951*38fd1498Szrj   if (fdata == NULL)
2952*38fd1498Szrj     return NULL;
2953*38fd1498Szrj 
2954*38fd1498Szrj   fdata->next = NULL;
2955*38fd1498Szrj   fdata->base_address = base_address;
2956*38fd1498Szrj   fdata->addrs = addrs;
2957*38fd1498Szrj   fdata->addrs_count = addrs_count;
2958*38fd1498Szrj   fdata->dwarf_info = dwarf_info;
2959*38fd1498Szrj   fdata->dwarf_info_size = dwarf_info_size;
2960*38fd1498Szrj   fdata->dwarf_line = dwarf_line;
2961*38fd1498Szrj   fdata->dwarf_line_size = dwarf_line_size;
2962*38fd1498Szrj   fdata->dwarf_ranges = dwarf_ranges;
2963*38fd1498Szrj   fdata->dwarf_ranges_size = dwarf_ranges_size;
2964*38fd1498Szrj   fdata->dwarf_str = dwarf_str;
2965*38fd1498Szrj   fdata->dwarf_str_size = dwarf_str_size;
2966*38fd1498Szrj   fdata->is_bigendian = is_bigendian;
2967*38fd1498Szrj   memset (&fdata->fvec, 0, sizeof fdata->fvec);
2968*38fd1498Szrj 
2969*38fd1498Szrj   return fdata;
2970*38fd1498Szrj }
2971*38fd1498Szrj 
2972*38fd1498Szrj /* Build our data structures from the DWARF sections for a module.
2973*38fd1498Szrj    Set FILELINE_FN and STATE->FILELINE_DATA.  Return 1 on success, 0
2974*38fd1498Szrj    on failure.  */
2975*38fd1498Szrj 
2976*38fd1498Szrj int
backtrace_dwarf_add(struct backtrace_state * state,uintptr_t base_address,const unsigned char * dwarf_info,size_t dwarf_info_size,const unsigned char * dwarf_line,size_t dwarf_line_size,const unsigned char * dwarf_abbrev,size_t dwarf_abbrev_size,const unsigned char * dwarf_ranges,size_t dwarf_ranges_size,const unsigned char * dwarf_str,size_t dwarf_str_size,int is_bigendian,backtrace_error_callback error_callback,void * data,fileline * fileline_fn)2977*38fd1498Szrj backtrace_dwarf_add (struct backtrace_state *state,
2978*38fd1498Szrj 		     uintptr_t base_address,
2979*38fd1498Szrj 		     const unsigned char *dwarf_info,
2980*38fd1498Szrj 		     size_t dwarf_info_size,
2981*38fd1498Szrj 		     const unsigned char *dwarf_line,
2982*38fd1498Szrj 		     size_t dwarf_line_size,
2983*38fd1498Szrj 		     const unsigned char *dwarf_abbrev,
2984*38fd1498Szrj 		     size_t dwarf_abbrev_size,
2985*38fd1498Szrj 		     const unsigned char *dwarf_ranges,
2986*38fd1498Szrj 		     size_t dwarf_ranges_size,
2987*38fd1498Szrj 		     const unsigned char *dwarf_str,
2988*38fd1498Szrj 		     size_t dwarf_str_size,
2989*38fd1498Szrj 		     int is_bigendian,
2990*38fd1498Szrj 		     backtrace_error_callback error_callback,
2991*38fd1498Szrj 		     void *data, fileline *fileline_fn)
2992*38fd1498Szrj {
2993*38fd1498Szrj   struct dwarf_data *fdata;
2994*38fd1498Szrj 
2995*38fd1498Szrj   fdata = build_dwarf_data (state, base_address, dwarf_info, dwarf_info_size,
2996*38fd1498Szrj 			    dwarf_line, dwarf_line_size, dwarf_abbrev,
2997*38fd1498Szrj 			    dwarf_abbrev_size, dwarf_ranges, dwarf_ranges_size,
2998*38fd1498Szrj 			    dwarf_str, dwarf_str_size, is_bigendian,
2999*38fd1498Szrj 			    error_callback, data);
3000*38fd1498Szrj   if (fdata == NULL)
3001*38fd1498Szrj     return 0;
3002*38fd1498Szrj 
3003*38fd1498Szrj   if (!state->threaded)
3004*38fd1498Szrj     {
3005*38fd1498Szrj       struct dwarf_data **pp;
3006*38fd1498Szrj 
3007*38fd1498Szrj       for (pp = (struct dwarf_data **) (void *) &state->fileline_data;
3008*38fd1498Szrj 	   *pp != NULL;
3009*38fd1498Szrj 	   pp = &(*pp)->next)
3010*38fd1498Szrj 	;
3011*38fd1498Szrj       *pp = fdata;
3012*38fd1498Szrj     }
3013*38fd1498Szrj   else
3014*38fd1498Szrj     {
3015*38fd1498Szrj       while (1)
3016*38fd1498Szrj 	{
3017*38fd1498Szrj 	  struct dwarf_data **pp;
3018*38fd1498Szrj 
3019*38fd1498Szrj 	  pp = (struct dwarf_data **) (void *) &state->fileline_data;
3020*38fd1498Szrj 
3021*38fd1498Szrj 	  while (1)
3022*38fd1498Szrj 	    {
3023*38fd1498Szrj 	      struct dwarf_data *p;
3024*38fd1498Szrj 
3025*38fd1498Szrj 	      p = backtrace_atomic_load_pointer (pp);
3026*38fd1498Szrj 
3027*38fd1498Szrj 	      if (p == NULL)
3028*38fd1498Szrj 		break;
3029*38fd1498Szrj 
3030*38fd1498Szrj 	      pp = &p->next;
3031*38fd1498Szrj 	    }
3032*38fd1498Szrj 
3033*38fd1498Szrj 	  if (__sync_bool_compare_and_swap (pp, NULL, fdata))
3034*38fd1498Szrj 	    break;
3035*38fd1498Szrj 	}
3036*38fd1498Szrj     }
3037*38fd1498Szrj 
3038*38fd1498Szrj   *fileline_fn = dwarf_fileline;
3039*38fd1498Szrj 
3040*38fd1498Szrj   return 1;
3041*38fd1498Szrj }
3042