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