xref: /aosp_15_r20/external/elfutils/libdw/dwarf_getsrclines.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Return line number information of CU.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2004-2010, 2013, 2014, 2015, 2016, 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker 
5*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker    it under the terms of either
7*7304104dSAndroid Build Coastguard Worker 
8*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker        your option) any later version
11*7304104dSAndroid Build Coastguard Worker 
12*7304104dSAndroid Build Coastguard Worker    or
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker        your option) any later version
17*7304104dSAndroid Build Coastguard Worker 
18*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
27*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
28*7304104dSAndroid Build Coastguard Worker 
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker 
33*7304104dSAndroid Build Coastguard Worker #include <assert.h>
34*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
35*7304104dSAndroid Build Coastguard Worker #include <string.h>
36*7304104dSAndroid Build Coastguard Worker #include <search.h>
37*7304104dSAndroid Build Coastguard Worker 
38*7304104dSAndroid Build Coastguard Worker #include "dwarf.h"
39*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
40*7304104dSAndroid Build Coastguard Worker 
41*7304104dSAndroid Build Coastguard Worker 
42*7304104dSAndroid Build Coastguard Worker struct filelist
43*7304104dSAndroid Build Coastguard Worker {
44*7304104dSAndroid Build Coastguard Worker   Dwarf_Fileinfo info;
45*7304104dSAndroid Build Coastguard Worker   struct filelist *next;
46*7304104dSAndroid Build Coastguard Worker };
47*7304104dSAndroid Build Coastguard Worker 
48*7304104dSAndroid Build Coastguard Worker struct linelist
49*7304104dSAndroid Build Coastguard Worker {
50*7304104dSAndroid Build Coastguard Worker   Dwarf_Line line;
51*7304104dSAndroid Build Coastguard Worker   struct linelist *next;
52*7304104dSAndroid Build Coastguard Worker   size_t sequence;
53*7304104dSAndroid Build Coastguard Worker };
54*7304104dSAndroid Build Coastguard Worker 
55*7304104dSAndroid Build Coastguard Worker 
56*7304104dSAndroid Build Coastguard Worker /* Compare by Dwarf_Line.addr, given pointers into an array of pointers.  */
57*7304104dSAndroid Build Coastguard Worker static int
compare_lines(const void * a,const void * b)58*7304104dSAndroid Build Coastguard Worker compare_lines (const void *a, const void *b)
59*7304104dSAndroid Build Coastguard Worker {
60*7304104dSAndroid Build Coastguard Worker   struct linelist *const *p1 = a;
61*7304104dSAndroid Build Coastguard Worker   struct linelist *const *p2 = b;
62*7304104dSAndroid Build Coastguard Worker   struct linelist *list1 = *p1;
63*7304104dSAndroid Build Coastguard Worker   struct linelist *list2 = *p2;
64*7304104dSAndroid Build Coastguard Worker   Dwarf_Line *line1 = &list1->line;
65*7304104dSAndroid Build Coastguard Worker   Dwarf_Line *line2 = &list2->line;
66*7304104dSAndroid Build Coastguard Worker 
67*7304104dSAndroid Build Coastguard Worker   if (line1->addr != line2->addr)
68*7304104dSAndroid Build Coastguard Worker     return (line1->addr < line2->addr) ? -1 : 1;
69*7304104dSAndroid Build Coastguard Worker 
70*7304104dSAndroid Build Coastguard Worker   /* An end_sequence marker precedes a normal record at the same address.  */
71*7304104dSAndroid Build Coastguard Worker   if (line1->end_sequence != line2->end_sequence)
72*7304104dSAndroid Build Coastguard Worker     return line2->end_sequence - line1->end_sequence;
73*7304104dSAndroid Build Coastguard Worker 
74*7304104dSAndroid Build Coastguard Worker   /* Otherwise, the linelist sequence maintains a stable sort.  */
75*7304104dSAndroid Build Coastguard Worker   return (list1->sequence < list2->sequence) ? -1
76*7304104dSAndroid Build Coastguard Worker     : (list1->sequence > list2->sequence) ? 1
77*7304104dSAndroid Build Coastguard Worker     : 0;
78*7304104dSAndroid Build Coastguard Worker }
79*7304104dSAndroid Build Coastguard Worker 
80*7304104dSAndroid Build Coastguard Worker struct line_state
81*7304104dSAndroid Build Coastguard Worker {
82*7304104dSAndroid Build Coastguard Worker   Dwarf_Word addr;
83*7304104dSAndroid Build Coastguard Worker   unsigned int op_index;
84*7304104dSAndroid Build Coastguard Worker   unsigned int file;
85*7304104dSAndroid Build Coastguard Worker   int64_t line;
86*7304104dSAndroid Build Coastguard Worker   unsigned int column;
87*7304104dSAndroid Build Coastguard Worker   uint_fast8_t is_stmt;
88*7304104dSAndroid Build Coastguard Worker   bool basic_block;
89*7304104dSAndroid Build Coastguard Worker   bool prologue_end;
90*7304104dSAndroid Build Coastguard Worker   bool epilogue_begin;
91*7304104dSAndroid Build Coastguard Worker   unsigned int isa;
92*7304104dSAndroid Build Coastguard Worker   unsigned int discriminator;
93*7304104dSAndroid Build Coastguard Worker   struct linelist *linelist;
94*7304104dSAndroid Build Coastguard Worker   size_t nlinelist;
95*7304104dSAndroid Build Coastguard Worker   unsigned int end_sequence;
96*7304104dSAndroid Build Coastguard Worker   unsigned int context;
97*7304104dSAndroid Build Coastguard Worker   unsigned int function_name;
98*7304104dSAndroid Build Coastguard Worker };
99*7304104dSAndroid Build Coastguard Worker 
100*7304104dSAndroid Build Coastguard Worker static inline void
run_advance_pc(struct line_state * state,unsigned int op_advance,uint_fast8_t minimum_instr_len,uint_fast8_t max_ops_per_instr)101*7304104dSAndroid Build Coastguard Worker run_advance_pc (struct line_state *state, unsigned int op_advance,
102*7304104dSAndroid Build Coastguard Worker                 uint_fast8_t minimum_instr_len, uint_fast8_t max_ops_per_instr)
103*7304104dSAndroid Build Coastguard Worker {
104*7304104dSAndroid Build Coastguard Worker   state->addr += minimum_instr_len * ((state->op_index + op_advance)
105*7304104dSAndroid Build Coastguard Worker 				      / max_ops_per_instr);
106*7304104dSAndroid Build Coastguard Worker   state->op_index = (state->op_index + op_advance) % max_ops_per_instr;
107*7304104dSAndroid Build Coastguard Worker }
108*7304104dSAndroid Build Coastguard Worker 
109*7304104dSAndroid Build Coastguard Worker static inline bool
add_new_line(struct line_state * state,struct linelist * new_line)110*7304104dSAndroid Build Coastguard Worker add_new_line (struct line_state *state, struct linelist *new_line)
111*7304104dSAndroid Build Coastguard Worker {
112*7304104dSAndroid Build Coastguard Worker   /* Set the line information.  For some fields we use bitfields,
113*7304104dSAndroid Build Coastguard Worker      so we would lose information if the encoded values are too large.
114*7304104dSAndroid Build Coastguard Worker      Check just for paranoia, and call the data "invalid" if it
115*7304104dSAndroid Build Coastguard Worker      violates our assumptions on reasonable limits for the values.  */
116*7304104dSAndroid Build Coastguard Worker   new_line->next = state->linelist;
117*7304104dSAndroid Build Coastguard Worker   new_line->sequence = state->nlinelist;
118*7304104dSAndroid Build Coastguard Worker   state->linelist = new_line;
119*7304104dSAndroid Build Coastguard Worker   ++(state->nlinelist);
120*7304104dSAndroid Build Coastguard Worker 
121*7304104dSAndroid Build Coastguard Worker   /* Set the line information.  For some fields we use bitfields,
122*7304104dSAndroid Build Coastguard Worker      so we would lose information if the encoded values are too large.
123*7304104dSAndroid Build Coastguard Worker      Check just for paranoia, and call the data "invalid" if it
124*7304104dSAndroid Build Coastguard Worker      violates our assumptions on reasonable limits for the values.  */
125*7304104dSAndroid Build Coastguard Worker #define SET(field)						      \
126*7304104dSAndroid Build Coastguard Worker   do {								      \
127*7304104dSAndroid Build Coastguard Worker      new_line->line.field = state->field;			      \
128*7304104dSAndroid Build Coastguard Worker      if (unlikely (new_line->line.field != state->field))	      \
129*7304104dSAndroid Build Coastguard Worker        return true;						      \
130*7304104dSAndroid Build Coastguard Worker    } while (0)
131*7304104dSAndroid Build Coastguard Worker 
132*7304104dSAndroid Build Coastguard Worker   /* Same as above, but don't flag as "invalid" just use truncated
133*7304104dSAndroid Build Coastguard Worker      value.  Used for discriminator for which llvm might use a value
134*7304104dSAndroid Build Coastguard Worker      that won't fit 24 bits.  */
135*7304104dSAndroid Build Coastguard Worker #define SETX(field)						      \
136*7304104dSAndroid Build Coastguard Worker      new_line->line.field = state->field;			      \
137*7304104dSAndroid Build Coastguard Worker 
138*7304104dSAndroid Build Coastguard Worker   SET (addr);
139*7304104dSAndroid Build Coastguard Worker   SET (op_index);
140*7304104dSAndroid Build Coastguard Worker   SET (file);
141*7304104dSAndroid Build Coastguard Worker   SET (line);
142*7304104dSAndroid Build Coastguard Worker   SET (column);
143*7304104dSAndroid Build Coastguard Worker   SET (is_stmt);
144*7304104dSAndroid Build Coastguard Worker   SET (basic_block);
145*7304104dSAndroid Build Coastguard Worker   SET (end_sequence);
146*7304104dSAndroid Build Coastguard Worker   SET (prologue_end);
147*7304104dSAndroid Build Coastguard Worker   SET (epilogue_begin);
148*7304104dSAndroid Build Coastguard Worker   SET (isa);
149*7304104dSAndroid Build Coastguard Worker   SETX (discriminator);
150*7304104dSAndroid Build Coastguard Worker   SET (context);
151*7304104dSAndroid Build Coastguard Worker   SET (function_name);
152*7304104dSAndroid Build Coastguard Worker 
153*7304104dSAndroid Build Coastguard Worker #undef SET
154*7304104dSAndroid Build Coastguard Worker 
155*7304104dSAndroid Build Coastguard Worker   return false;
156*7304104dSAndroid Build Coastguard Worker }
157*7304104dSAndroid Build Coastguard Worker 
158*7304104dSAndroid Build Coastguard Worker static int
read_srclines(Dwarf * dbg,const unsigned char * linep,const unsigned char * lineendp,const char * comp_dir,unsigned address_size,Dwarf_Lines ** linesp,Dwarf_Files ** filesp)159*7304104dSAndroid Build Coastguard Worker read_srclines (Dwarf *dbg,
160*7304104dSAndroid Build Coastguard Worker 	       const unsigned char *linep, const unsigned char *lineendp,
161*7304104dSAndroid Build Coastguard Worker 	       const char *comp_dir, unsigned address_size,
162*7304104dSAndroid Build Coastguard Worker 	       Dwarf_Lines **linesp, Dwarf_Files **filesp)
163*7304104dSAndroid Build Coastguard Worker {
164*7304104dSAndroid Build Coastguard Worker   int res = -1;
165*7304104dSAndroid Build Coastguard Worker 
166*7304104dSAndroid Build Coastguard Worker   struct filelist *filelist = NULL;
167*7304104dSAndroid Build Coastguard Worker   size_t nfilelist = 0;
168*7304104dSAndroid Build Coastguard Worker   size_t ndirlist = 0;
169*7304104dSAndroid Build Coastguard Worker 
170*7304104dSAndroid Build Coastguard Worker   /* If there are a large number of lines, files or dirs don't blow up
171*7304104dSAndroid Build Coastguard Worker      the stack.  Stack allocate some entries, only dynamically malloc
172*7304104dSAndroid Build Coastguard Worker      when more than MAX.  */
173*7304104dSAndroid Build Coastguard Worker #define MAX_STACK_ALLOC 4096
174*7304104dSAndroid Build Coastguard Worker #define MAX_STACK_LINES (MAX_STACK_ALLOC / 2)
175*7304104dSAndroid Build Coastguard Worker #define MAX_STACK_FILES (MAX_STACK_ALLOC / 4)
176*7304104dSAndroid Build Coastguard Worker #define MAX_STACK_DIRS  (MAX_STACK_ALLOC / 16)
177*7304104dSAndroid Build Coastguard Worker 
178*7304104dSAndroid Build Coastguard Worker   /* Initial statement program state (except for stmt_list, see below).  */
179*7304104dSAndroid Build Coastguard Worker   struct line_state state =
180*7304104dSAndroid Build Coastguard Worker     {
181*7304104dSAndroid Build Coastguard Worker       .linelist = NULL,
182*7304104dSAndroid Build Coastguard Worker       .nlinelist = 0,
183*7304104dSAndroid Build Coastguard Worker       .addr = 0,
184*7304104dSAndroid Build Coastguard Worker       .op_index = 0,
185*7304104dSAndroid Build Coastguard Worker       .file = 1,
186*7304104dSAndroid Build Coastguard Worker       /* We only store int but want to check for overflow (see SET above).  */
187*7304104dSAndroid Build Coastguard Worker       .line = 1,
188*7304104dSAndroid Build Coastguard Worker       .column = 0,
189*7304104dSAndroid Build Coastguard Worker       .basic_block = false,
190*7304104dSAndroid Build Coastguard Worker       .prologue_end = false,
191*7304104dSAndroid Build Coastguard Worker       .epilogue_begin = false,
192*7304104dSAndroid Build Coastguard Worker       .isa = 0,
193*7304104dSAndroid Build Coastguard Worker       .discriminator = 0,
194*7304104dSAndroid Build Coastguard Worker       .context = 0,
195*7304104dSAndroid Build Coastguard Worker       .function_name = 0
196*7304104dSAndroid Build Coastguard Worker     };
197*7304104dSAndroid Build Coastguard Worker 
198*7304104dSAndroid Build Coastguard Worker   /* The dirs normally go on the stack, but if there are too many
199*7304104dSAndroid Build Coastguard Worker      we alloc them all.  Set up stack storage early, so we can check on
200*7304104dSAndroid Build Coastguard Worker      error if we need to free them or not.  */
201*7304104dSAndroid Build Coastguard Worker   struct dirlist
202*7304104dSAndroid Build Coastguard Worker   {
203*7304104dSAndroid Build Coastguard Worker     const char *dir;
204*7304104dSAndroid Build Coastguard Worker     size_t len;
205*7304104dSAndroid Build Coastguard Worker   };
206*7304104dSAndroid Build Coastguard Worker   struct dirlist dirstack[MAX_STACK_DIRS];
207*7304104dSAndroid Build Coastguard Worker   struct dirlist *dirarray = dirstack;
208*7304104dSAndroid Build Coastguard Worker 
209*7304104dSAndroid Build Coastguard Worker   if (unlikely (linep + 4 > lineendp))
210*7304104dSAndroid Build Coastguard Worker     {
211*7304104dSAndroid Build Coastguard Worker     invalid_data:
212*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
213*7304104dSAndroid Build Coastguard Worker       goto out;
214*7304104dSAndroid Build Coastguard Worker     }
215*7304104dSAndroid Build Coastguard Worker 
216*7304104dSAndroid Build Coastguard Worker   Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
217*7304104dSAndroid Build Coastguard Worker   unsigned int length = 4;
218*7304104dSAndroid Build Coastguard Worker   if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
219*7304104dSAndroid Build Coastguard Worker     {
220*7304104dSAndroid Build Coastguard Worker       if (unlikely (linep + 8 > lineendp))
221*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
222*7304104dSAndroid Build Coastguard Worker       unit_length = read_8ubyte_unaligned_inc (dbg, linep);
223*7304104dSAndroid Build Coastguard Worker       length = 8;
224*7304104dSAndroid Build Coastguard Worker     }
225*7304104dSAndroid Build Coastguard Worker 
226*7304104dSAndroid Build Coastguard Worker   /* Check whether we have enough room in the section.  */
227*7304104dSAndroid Build Coastguard Worker   if (unlikely (unit_length > (size_t) (lineendp - linep)))
228*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
229*7304104dSAndroid Build Coastguard Worker   lineendp = linep + unit_length;
230*7304104dSAndroid Build Coastguard Worker 
231*7304104dSAndroid Build Coastguard Worker   /* The next element of the header is the version identifier.  */
232*7304104dSAndroid Build Coastguard Worker   if ((size_t) (lineendp - linep) < 2)
233*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
234*7304104dSAndroid Build Coastguard Worker   uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
235*7304104dSAndroid Build Coastguard Worker   if (unlikely (version < 2) || unlikely (version > 5))
236*7304104dSAndroid Build Coastguard Worker     {
237*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_VERSION);
238*7304104dSAndroid Build Coastguard Worker       goto out;
239*7304104dSAndroid Build Coastguard Worker     }
240*7304104dSAndroid Build Coastguard Worker 
241*7304104dSAndroid Build Coastguard Worker   /* DWARF5 explicitly lists address and segment_selector sizes.  */
242*7304104dSAndroid Build Coastguard Worker   if (version >= 5)
243*7304104dSAndroid Build Coastguard Worker     {
244*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 2)
245*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
246*7304104dSAndroid Build Coastguard Worker       size_t line_address_size = *linep++;
247*7304104dSAndroid Build Coastguard Worker       size_t segment_selector_size = *linep++;
248*7304104dSAndroid Build Coastguard Worker       if (line_address_size != address_size || segment_selector_size != 0)
249*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
250*7304104dSAndroid Build Coastguard Worker     }
251*7304104dSAndroid Build Coastguard Worker 
252*7304104dSAndroid Build Coastguard Worker   /* Next comes the header length.  */
253*7304104dSAndroid Build Coastguard Worker   Dwarf_Word header_length;
254*7304104dSAndroid Build Coastguard Worker   if (length == 4)
255*7304104dSAndroid Build Coastguard Worker     {
256*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 4)
257*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
258*7304104dSAndroid Build Coastguard Worker       header_length = read_4ubyte_unaligned_inc (dbg, linep);
259*7304104dSAndroid Build Coastguard Worker     }
260*7304104dSAndroid Build Coastguard Worker   else
261*7304104dSAndroid Build Coastguard Worker     {
262*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 8)
263*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
264*7304104dSAndroid Build Coastguard Worker       header_length = read_8ubyte_unaligned_inc (dbg, linep);
265*7304104dSAndroid Build Coastguard Worker     }
266*7304104dSAndroid Build Coastguard Worker   const unsigned char *header_start = linep;
267*7304104dSAndroid Build Coastguard Worker 
268*7304104dSAndroid Build Coastguard Worker   /* Next the minimum instruction length.  */
269*7304104dSAndroid Build Coastguard Worker   uint_fast8_t minimum_instr_len = *linep++;
270*7304104dSAndroid Build Coastguard Worker 
271*7304104dSAndroid Build Coastguard Worker   /* Next the maximum operations per instruction, in version 4 format.  */
272*7304104dSAndroid Build Coastguard Worker   uint_fast8_t max_ops_per_instr = 1;
273*7304104dSAndroid Build Coastguard Worker   if (version >= 4)
274*7304104dSAndroid Build Coastguard Worker     {
275*7304104dSAndroid Build Coastguard Worker       if (unlikely ((size_t) (lineendp - linep) < 1))
276*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
277*7304104dSAndroid Build Coastguard Worker       max_ops_per_instr = *linep++;
278*7304104dSAndroid Build Coastguard Worker       if (unlikely (max_ops_per_instr == 0))
279*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
280*7304104dSAndroid Build Coastguard Worker     }
281*7304104dSAndroid Build Coastguard Worker 
282*7304104dSAndroid Build Coastguard Worker   /* 4 more bytes, is_stmt, line_base, line_range and opcode_base.  */
283*7304104dSAndroid Build Coastguard Worker   if ((size_t) (lineendp - linep) < 4)
284*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
285*7304104dSAndroid Build Coastguard Worker 
286*7304104dSAndroid Build Coastguard Worker   /* Then the flag determining the default value of the is_stmt
287*7304104dSAndroid Build Coastguard Worker      register.  */
288*7304104dSAndroid Build Coastguard Worker   uint_fast8_t default_is_stmt = *linep++;
289*7304104dSAndroid Build Coastguard Worker 
290*7304104dSAndroid Build Coastguard Worker   /* Now the line base.  */
291*7304104dSAndroid Build Coastguard Worker   int_fast8_t line_base = (int8_t) *linep++;
292*7304104dSAndroid Build Coastguard Worker 
293*7304104dSAndroid Build Coastguard Worker   /* And the line range.  */
294*7304104dSAndroid Build Coastguard Worker   uint_fast8_t line_range = *linep++;
295*7304104dSAndroid Build Coastguard Worker 
296*7304104dSAndroid Build Coastguard Worker   /* The opcode base.  */
297*7304104dSAndroid Build Coastguard Worker   uint_fast8_t opcode_base = *linep++;
298*7304104dSAndroid Build Coastguard Worker 
299*7304104dSAndroid Build Coastguard Worker   /* Remember array with the standard opcode length (-1 to account for
300*7304104dSAndroid Build Coastguard Worker      the opcode with value zero not being mentioned).  */
301*7304104dSAndroid Build Coastguard Worker   const uint8_t *standard_opcode_lengths = linep - 1;
302*7304104dSAndroid Build Coastguard Worker   if (unlikely (lineendp - linep < opcode_base - 1))
303*7304104dSAndroid Build Coastguard Worker     goto invalid_data;
304*7304104dSAndroid Build Coastguard Worker   linep += opcode_base - 1;
305*7304104dSAndroid Build Coastguard Worker 
306*7304104dSAndroid Build Coastguard Worker   /* To read DWARF5 dir and file lists we need to know the forms.  For
307*7304104dSAndroid Build Coastguard Worker      now we skip everything, except the DW_LNCT_path and
308*7304104dSAndroid Build Coastguard Worker      DW_LNCT_directory_index.  */
309*7304104dSAndroid Build Coastguard Worker   uint16_t forms[256];
310*7304104dSAndroid Build Coastguard Worker   unsigned char nforms = 0;
311*7304104dSAndroid Build Coastguard Worker   unsigned char form_path = -1; /* Which forms is DW_LNCT_path.  */
312*7304104dSAndroid Build Coastguard Worker   unsigned char form_idx = -1;  /* And which is DW_LNCT_directory_index.  */
313*7304104dSAndroid Build Coastguard Worker 
314*7304104dSAndroid Build Coastguard Worker   /* To read/skip form data.  */
315*7304104dSAndroid Build Coastguard Worker   Dwarf_CU fake_cu = {
316*7304104dSAndroid Build Coastguard Worker     .dbg = dbg,
317*7304104dSAndroid Build Coastguard Worker     .sec_idx = IDX_debug_line,
318*7304104dSAndroid Build Coastguard Worker     .version = 5,
319*7304104dSAndroid Build Coastguard Worker     .offset_size = length,
320*7304104dSAndroid Build Coastguard Worker     .address_size = address_size,
321*7304104dSAndroid Build Coastguard Worker     .startp = (void *) linep,
322*7304104dSAndroid Build Coastguard Worker     .endp = (void *) lineendp,
323*7304104dSAndroid Build Coastguard Worker   };
324*7304104dSAndroid Build Coastguard Worker 
325*7304104dSAndroid Build Coastguard Worker   /* First count the entries.  */
326*7304104dSAndroid Build Coastguard Worker   size_t ndirs = 0;
327*7304104dSAndroid Build Coastguard Worker   if (version < 5)
328*7304104dSAndroid Build Coastguard Worker     {
329*7304104dSAndroid Build Coastguard Worker       const unsigned char *dirp = linep;
330*7304104dSAndroid Build Coastguard Worker       while (dirp < lineendp && *dirp != 0)
331*7304104dSAndroid Build Coastguard Worker 	{
332*7304104dSAndroid Build Coastguard Worker 	  uint8_t *endp = memchr (dirp, '\0', lineendp - dirp);
333*7304104dSAndroid Build Coastguard Worker 	  if (endp == NULL)
334*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
335*7304104dSAndroid Build Coastguard Worker 	  ++ndirs;
336*7304104dSAndroid Build Coastguard Worker 	  dirp = endp + 1;
337*7304104dSAndroid Build Coastguard Worker 	}
338*7304104dSAndroid Build Coastguard Worker       if (dirp >= lineendp || *dirp != '\0')
339*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
340*7304104dSAndroid Build Coastguard Worker       ndirs = ndirs + 1; /* There is always the "unknown" dir.  */
341*7304104dSAndroid Build Coastguard Worker     }
342*7304104dSAndroid Build Coastguard Worker   else
343*7304104dSAndroid Build Coastguard Worker     {
344*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 1)
345*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
346*7304104dSAndroid Build Coastguard Worker       nforms = *linep++;
347*7304104dSAndroid Build Coastguard Worker       for (int i = 0; i < nforms; i++)
348*7304104dSAndroid Build Coastguard Worker 	{
349*7304104dSAndroid Build Coastguard Worker 	  uint16_t desc, form;
350*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
351*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
352*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (desc, linep, lineendp);
353*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
354*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
355*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (form, linep, lineendp);
356*7304104dSAndroid Build Coastguard Worker 
357*7304104dSAndroid Build Coastguard Worker 	  if (! libdw_valid_user_form (form))
358*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
359*7304104dSAndroid Build Coastguard Worker 
360*7304104dSAndroid Build Coastguard Worker 	  forms[i] = form;
361*7304104dSAndroid Build Coastguard Worker 	  if (desc == DW_LNCT_path)
362*7304104dSAndroid Build Coastguard Worker 	    form_path = i;
363*7304104dSAndroid Build Coastguard Worker 	}
364*7304104dSAndroid Build Coastguard Worker 
365*7304104dSAndroid Build Coastguard Worker       if (nforms > 0 && form_path == (unsigned char) -1)
366*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
367*7304104dSAndroid Build Coastguard Worker 
368*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 1)
369*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
370*7304104dSAndroid Build Coastguard Worker       get_uleb128 (ndirs, linep, lineendp);
371*7304104dSAndroid Build Coastguard Worker 
372*7304104dSAndroid Build Coastguard Worker       if (nforms == 0 && ndirs != 0)
373*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
374*7304104dSAndroid Build Coastguard Worker 
375*7304104dSAndroid Build Coastguard Worker       /* Assume there is at least 1 byte needed per form to describe
376*7304104dSAndroid Build Coastguard Worker 	 the directory.  Filters out insanely large ndirs.  */
377*7304104dSAndroid Build Coastguard Worker       if (nforms != 0 && ndirs > (size_t) (lineendp - linep) / nforms)
378*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
379*7304104dSAndroid Build Coastguard Worker     }
380*7304104dSAndroid Build Coastguard Worker 
381*7304104dSAndroid Build Coastguard Worker   /* Arrange the list in array form.  */
382*7304104dSAndroid Build Coastguard Worker   ndirlist = ndirs;
383*7304104dSAndroid Build Coastguard Worker   if (ndirlist >= MAX_STACK_DIRS)
384*7304104dSAndroid Build Coastguard Worker     {
385*7304104dSAndroid Build Coastguard Worker       if (ndirlist > SIZE_MAX / sizeof (*dirarray))
386*7304104dSAndroid Build Coastguard Worker 	goto no_mem;
387*7304104dSAndroid Build Coastguard Worker       dirarray = malloc (ndirlist * sizeof (*dirarray));
388*7304104dSAndroid Build Coastguard Worker       if (unlikely (dirarray == NULL))
389*7304104dSAndroid Build Coastguard Worker 	{
390*7304104dSAndroid Build Coastguard Worker 	no_mem:
391*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_NOMEM);
392*7304104dSAndroid Build Coastguard Worker 	  goto out;
393*7304104dSAndroid Build Coastguard Worker 	}
394*7304104dSAndroid Build Coastguard Worker     }
395*7304104dSAndroid Build Coastguard Worker 
396*7304104dSAndroid Build Coastguard Worker   /* Entry zero is implicit for older versions, but explicit for 5+.  */
397*7304104dSAndroid Build Coastguard Worker   struct dirlist comp_dir_elem;
398*7304104dSAndroid Build Coastguard Worker   if (version < 5)
399*7304104dSAndroid Build Coastguard Worker     {
400*7304104dSAndroid Build Coastguard Worker       /* First comes the list of directories.  Add the compilation
401*7304104dSAndroid Build Coastguard Worker 	 directory first since the index zero is used for it.  */
402*7304104dSAndroid Build Coastguard Worker       comp_dir_elem.dir = comp_dir;
403*7304104dSAndroid Build Coastguard Worker       comp_dir_elem.len = comp_dir ? strlen (comp_dir) : 0,
404*7304104dSAndroid Build Coastguard Worker       dirarray[0] = comp_dir_elem;
405*7304104dSAndroid Build Coastguard Worker       for (unsigned int n = 1; n < ndirlist; n++)
406*7304104dSAndroid Build Coastguard Worker 	{
407*7304104dSAndroid Build Coastguard Worker 	  dirarray[n].dir = (char *) linep;
408*7304104dSAndroid Build Coastguard Worker 	  uint8_t *endp = memchr (linep, '\0', lineendp - linep);
409*7304104dSAndroid Build Coastguard Worker 	  assert (endp != NULL); // Checked above when calculating ndirlist.
410*7304104dSAndroid Build Coastguard Worker 	  dirarray[n].len = endp - linep;
411*7304104dSAndroid Build Coastguard Worker 	  linep = endp + 1;
412*7304104dSAndroid Build Coastguard Worker 	}
413*7304104dSAndroid Build Coastguard Worker       /* Skip the final NUL byte.  */
414*7304104dSAndroid Build Coastguard Worker       assert (*linep == '\0'); // Checked above when calculating ndirlist.
415*7304104dSAndroid Build Coastguard Worker       ++linep;
416*7304104dSAndroid Build Coastguard Worker     }
417*7304104dSAndroid Build Coastguard Worker   else
418*7304104dSAndroid Build Coastguard Worker     {
419*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute attr;
420*7304104dSAndroid Build Coastguard Worker       attr.code = DW_AT_name;
421*7304104dSAndroid Build Coastguard Worker       attr.cu = &fake_cu;
422*7304104dSAndroid Build Coastguard Worker       for (unsigned int n = 0; n < ndirlist; n++)
423*7304104dSAndroid Build Coastguard Worker 	{
424*7304104dSAndroid Build Coastguard Worker 	  const char *dir = NULL;
425*7304104dSAndroid Build Coastguard Worker 	  for (unsigned char m = 0; m < nforms; m++)
426*7304104dSAndroid Build Coastguard Worker 	    {
427*7304104dSAndroid Build Coastguard Worker 	      if (m == form_path)
428*7304104dSAndroid Build Coastguard Worker 		{
429*7304104dSAndroid Build Coastguard Worker 		  attr.form = forms[m];
430*7304104dSAndroid Build Coastguard Worker 		  attr.valp = (void *) linep;
431*7304104dSAndroid Build Coastguard Worker 		  dir = dwarf_formstring (&attr);
432*7304104dSAndroid Build Coastguard Worker 		}
433*7304104dSAndroid Build Coastguard Worker 
434*7304104dSAndroid Build Coastguard Worker 	      size_t len = __libdw_form_val_len (&fake_cu, forms[m], linep);
435*7304104dSAndroid Build Coastguard Worker 	      if ((size_t) (lineendp - linep) < len)
436*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
437*7304104dSAndroid Build Coastguard Worker 
438*7304104dSAndroid Build Coastguard Worker 	      linep += len;
439*7304104dSAndroid Build Coastguard Worker 	    }
440*7304104dSAndroid Build Coastguard Worker 
441*7304104dSAndroid Build Coastguard Worker 	  if (dir == NULL)
442*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
443*7304104dSAndroid Build Coastguard Worker 
444*7304104dSAndroid Build Coastguard Worker 	  dirarray[n].dir = dir;
445*7304104dSAndroid Build Coastguard Worker 	  dirarray[n].len = strlen (dir);
446*7304104dSAndroid Build Coastguard Worker 	}
447*7304104dSAndroid Build Coastguard Worker     }
448*7304104dSAndroid Build Coastguard Worker 
449*7304104dSAndroid Build Coastguard Worker   /* File index zero doesn't exist for DWARF < 5.  Files are indexed
450*7304104dSAndroid Build Coastguard Worker      starting from 1.  But for DWARF5 they are indexed starting from
451*7304104dSAndroid Build Coastguard Worker      zero, but the default index is still 1.  In both cases the
452*7304104dSAndroid Build Coastguard Worker      "first" file is special and refers to the main compile unit file,
453*7304104dSAndroid Build Coastguard Worker      equal to the DW_AT_name of the DW_TAG_compile_unit.  */
454*7304104dSAndroid Build Coastguard Worker   struct filelist null_file =
455*7304104dSAndroid Build Coastguard Worker     {
456*7304104dSAndroid Build Coastguard Worker       .info =
457*7304104dSAndroid Build Coastguard Worker       {
458*7304104dSAndroid Build Coastguard Worker 	.name = "???",
459*7304104dSAndroid Build Coastguard Worker 	.mtime = 0,
460*7304104dSAndroid Build Coastguard Worker 	.length = 0
461*7304104dSAndroid Build Coastguard Worker       },
462*7304104dSAndroid Build Coastguard Worker       .next = NULL
463*7304104dSAndroid Build Coastguard Worker     };
464*7304104dSAndroid Build Coastguard Worker   filelist = &null_file;
465*7304104dSAndroid Build Coastguard Worker   nfilelist = 1;
466*7304104dSAndroid Build Coastguard Worker 
467*7304104dSAndroid Build Coastguard Worker   /* Allocate memory for a new file.  For the first MAX_STACK_FILES
468*7304104dSAndroid Build Coastguard Worker      entries just return a slot in the preallocated stack array.
469*7304104dSAndroid Build Coastguard Worker      This is slightly complicated because in DWARF < 5 new files could
470*7304104dSAndroid Build Coastguard Worker      be defined with DW_LNE_define_file after the normal file list was
471*7304104dSAndroid Build Coastguard Worker      read.  */
472*7304104dSAndroid Build Coastguard Worker   struct filelist flstack[MAX_STACK_FILES];
473*7304104dSAndroid Build Coastguard Worker #define NEW_FILE() ({							\
474*7304104dSAndroid Build Coastguard Worker   struct filelist *fl = (nfilelist < MAX_STACK_FILES			\
475*7304104dSAndroid Build Coastguard Worker 			   ? &flstack[nfilelist]			\
476*7304104dSAndroid Build Coastguard Worker 			   : malloc (sizeof (struct filelist)));	\
477*7304104dSAndroid Build Coastguard Worker   if (unlikely (fl == NULL))						\
478*7304104dSAndroid Build Coastguard Worker     goto no_mem;							\
479*7304104dSAndroid Build Coastguard Worker   ++nfilelist;								\
480*7304104dSAndroid Build Coastguard Worker   fl->next = filelist;							\
481*7304104dSAndroid Build Coastguard Worker   filelist = fl;							\
482*7304104dSAndroid Build Coastguard Worker   fl; })
483*7304104dSAndroid Build Coastguard Worker 
484*7304104dSAndroid Build Coastguard Worker   /* Now read the files.  */
485*7304104dSAndroid Build Coastguard Worker   if (version < 5)
486*7304104dSAndroid Build Coastguard Worker     {
487*7304104dSAndroid Build Coastguard Worker       if (unlikely (linep >= lineendp))
488*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
489*7304104dSAndroid Build Coastguard Worker       while (linep < lineendp && *linep != '\0')
490*7304104dSAndroid Build Coastguard Worker 	{
491*7304104dSAndroid Build Coastguard Worker 	  struct filelist *new_file = NEW_FILE ();
492*7304104dSAndroid Build Coastguard Worker 
493*7304104dSAndroid Build Coastguard Worker 	  /* First comes the file name.  */
494*7304104dSAndroid Build Coastguard Worker 	  char *fname = (char *) linep;
495*7304104dSAndroid Build Coastguard Worker 	  uint8_t *endp = memchr (fname, '\0', lineendp - linep);
496*7304104dSAndroid Build Coastguard Worker 	  if (endp == NULL)
497*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
498*7304104dSAndroid Build Coastguard Worker 	  size_t fnamelen = endp - (uint8_t *) fname;
499*7304104dSAndroid Build Coastguard Worker 	  linep = endp + 1;
500*7304104dSAndroid Build Coastguard Worker 
501*7304104dSAndroid Build Coastguard Worker 	  /* Then the index.  */
502*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word diridx;
503*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (linep >= lineendp))
504*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
505*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (diridx, linep, lineendp);
506*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (diridx >= ndirlist))
507*7304104dSAndroid Build Coastguard Worker 	    {
508*7304104dSAndroid Build Coastguard Worker 	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
509*7304104dSAndroid Build Coastguard Worker 	      goto out;
510*7304104dSAndroid Build Coastguard Worker 	    }
511*7304104dSAndroid Build Coastguard Worker 
512*7304104dSAndroid Build Coastguard Worker 	  if (*fname == '/')
513*7304104dSAndroid Build Coastguard Worker 	    /* It's an absolute path.  */
514*7304104dSAndroid Build Coastguard Worker 	    new_file->info.name = fname;
515*7304104dSAndroid Build Coastguard Worker 	  else
516*7304104dSAndroid Build Coastguard Worker 	    {
517*7304104dSAndroid Build Coastguard Worker 	      new_file->info.name = libdw_alloc (dbg, char, 1,
518*7304104dSAndroid Build Coastguard Worker 						 dirarray[diridx].len + 1
519*7304104dSAndroid Build Coastguard Worker 						 + fnamelen + 1);
520*7304104dSAndroid Build Coastguard Worker 	      char *cp = new_file->info.name;
521*7304104dSAndroid Build Coastguard Worker 
522*7304104dSAndroid Build Coastguard Worker 	      if (dirarray[diridx].dir != NULL)
523*7304104dSAndroid Build Coastguard Worker 		{
524*7304104dSAndroid Build Coastguard Worker 		  /* This value could be NULL in case the DW_AT_comp_dir
525*7304104dSAndroid Build Coastguard Worker 		     was not present.  We cannot do much in this case.
526*7304104dSAndroid Build Coastguard Worker 		     Just keep the file relative.  */
527*7304104dSAndroid Build Coastguard Worker 		  cp = stpcpy (cp, dirarray[diridx].dir);
528*7304104dSAndroid Build Coastguard Worker 		  *cp++ = '/';
529*7304104dSAndroid Build Coastguard Worker 		}
530*7304104dSAndroid Build Coastguard Worker 	      strcpy (cp, fname);
531*7304104dSAndroid Build Coastguard Worker 	      assert (strlen (new_file->info.name)
532*7304104dSAndroid Build Coastguard Worker 		      < dirarray[diridx].len + 1 + fnamelen + 1);
533*7304104dSAndroid Build Coastguard Worker 	    }
534*7304104dSAndroid Build Coastguard Worker 
535*7304104dSAndroid Build Coastguard Worker 	  /* Next comes the modification time.  */
536*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (linep >= lineendp))
537*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
538*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (new_file->info.mtime, linep, lineendp);
539*7304104dSAndroid Build Coastguard Worker 
540*7304104dSAndroid Build Coastguard Worker 	  /* Finally the length of the file.  */
541*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (linep >= lineendp))
542*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
543*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (new_file->info.length, linep, lineendp);
544*7304104dSAndroid Build Coastguard Worker 	}
545*7304104dSAndroid Build Coastguard Worker       if (linep >= lineendp || *linep != '\0')
546*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
547*7304104dSAndroid Build Coastguard Worker       /* Skip the final NUL byte.  */
548*7304104dSAndroid Build Coastguard Worker       ++linep;
549*7304104dSAndroid Build Coastguard Worker     }
550*7304104dSAndroid Build Coastguard Worker   else
551*7304104dSAndroid Build Coastguard Worker     {
552*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 1)
553*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
554*7304104dSAndroid Build Coastguard Worker       nforms = *linep++;
555*7304104dSAndroid Build Coastguard Worker       form_path = form_idx = -1;
556*7304104dSAndroid Build Coastguard Worker       for (int i = 0; i < nforms; i++)
557*7304104dSAndroid Build Coastguard Worker 	{
558*7304104dSAndroid Build Coastguard Worker 	  uint16_t desc, form;
559*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
560*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
561*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (desc, linep, lineendp);
562*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) (lineendp - linep) < 1)
563*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
564*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (form, linep, lineendp);
565*7304104dSAndroid Build Coastguard Worker 
566*7304104dSAndroid Build Coastguard Worker 	  if (! libdw_valid_user_form (form))
567*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
568*7304104dSAndroid Build Coastguard Worker 
569*7304104dSAndroid Build Coastguard Worker 	  forms[i] = form;
570*7304104dSAndroid Build Coastguard Worker 	  if (desc == DW_LNCT_path)
571*7304104dSAndroid Build Coastguard Worker 	    form_path = i;
572*7304104dSAndroid Build Coastguard Worker 	  else if (desc == DW_LNCT_directory_index)
573*7304104dSAndroid Build Coastguard Worker 	    form_idx = i;
574*7304104dSAndroid Build Coastguard Worker 	}
575*7304104dSAndroid Build Coastguard Worker 
576*7304104dSAndroid Build Coastguard Worker       if (nforms > 0 && (form_path == (unsigned char) -1
577*7304104dSAndroid Build Coastguard Worker 			 || form_idx == (unsigned char) -1))
578*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
579*7304104dSAndroid Build Coastguard Worker 
580*7304104dSAndroid Build Coastguard Worker       size_t nfiles;
581*7304104dSAndroid Build Coastguard Worker       if ((size_t) (lineendp - linep) < 1)
582*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
583*7304104dSAndroid Build Coastguard Worker       get_uleb128 (nfiles, linep, lineendp);
584*7304104dSAndroid Build Coastguard Worker 
585*7304104dSAndroid Build Coastguard Worker       if (nforms == 0 && nfiles != 0)
586*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
587*7304104dSAndroid Build Coastguard Worker 
588*7304104dSAndroid Build Coastguard Worker       /* Assume there is at least 1 byte needed per form to describe
589*7304104dSAndroid Build Coastguard Worker 	 the file.  Filters out insanely large nfiles.  */
590*7304104dSAndroid Build Coastguard Worker       if (nforms != 0 && nfiles > (size_t) (lineendp - linep) / nforms)
591*7304104dSAndroid Build Coastguard Worker 	goto invalid_data;
592*7304104dSAndroid Build Coastguard Worker 
593*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute attr;
594*7304104dSAndroid Build Coastguard Worker       attr.cu = &fake_cu;
595*7304104dSAndroid Build Coastguard Worker       for (unsigned int n = 0; n < nfiles; n++)
596*7304104dSAndroid Build Coastguard Worker 	{
597*7304104dSAndroid Build Coastguard Worker 	  const char *fname = NULL;
598*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Word diridx = (Dwarf_Word) -1;
599*7304104dSAndroid Build Coastguard Worker 	  for (unsigned char m = 0; m < nforms; m++)
600*7304104dSAndroid Build Coastguard Worker 	    {
601*7304104dSAndroid Build Coastguard Worker 	      if (m == form_path)
602*7304104dSAndroid Build Coastguard Worker 		{
603*7304104dSAndroid Build Coastguard Worker 		  attr.code = DW_AT_name;
604*7304104dSAndroid Build Coastguard Worker 		  attr.form = forms[m];
605*7304104dSAndroid Build Coastguard Worker 		  attr.valp = (void *) linep;
606*7304104dSAndroid Build Coastguard Worker 		  fname = dwarf_formstring (&attr);
607*7304104dSAndroid Build Coastguard Worker 		}
608*7304104dSAndroid Build Coastguard Worker 	      else if (m == form_idx)
609*7304104dSAndroid Build Coastguard Worker 		{
610*7304104dSAndroid Build Coastguard Worker 		  attr.code = DW_AT_decl_file; /* Close enough.  */
611*7304104dSAndroid Build Coastguard Worker 		  attr.form = forms[m];
612*7304104dSAndroid Build Coastguard Worker 		  attr.valp = (void *) linep;
613*7304104dSAndroid Build Coastguard Worker 		  if (dwarf_formudata (&attr, &diridx) != 0)
614*7304104dSAndroid Build Coastguard Worker 		    diridx = (Dwarf_Word) -1;
615*7304104dSAndroid Build Coastguard Worker 		}
616*7304104dSAndroid Build Coastguard Worker 
617*7304104dSAndroid Build Coastguard Worker 	      size_t len = __libdw_form_val_len (&fake_cu, forms[m], linep);
618*7304104dSAndroid Build Coastguard Worker 	      if ((size_t) (lineendp - linep) < len)
619*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
620*7304104dSAndroid Build Coastguard Worker 
621*7304104dSAndroid Build Coastguard Worker 	      linep += len;
622*7304104dSAndroid Build Coastguard Worker 	    }
623*7304104dSAndroid Build Coastguard Worker 
624*7304104dSAndroid Build Coastguard Worker 	  if (fname == NULL || diridx == (Dwarf_Word) -1)
625*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
626*7304104dSAndroid Build Coastguard Worker 
627*7304104dSAndroid Build Coastguard Worker 	  size_t fnamelen = strlen (fname);
628*7304104dSAndroid Build Coastguard Worker 
629*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (diridx >= ndirlist))
630*7304104dSAndroid Build Coastguard Worker 	    {
631*7304104dSAndroid Build Coastguard Worker 	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
632*7304104dSAndroid Build Coastguard Worker 	      goto out;
633*7304104dSAndroid Build Coastguard Worker 	    }
634*7304104dSAndroid Build Coastguard Worker 
635*7304104dSAndroid Build Coastguard Worker 	  /* Yes, weird.  Looks like an off-by-one in the spec.  */
636*7304104dSAndroid Build Coastguard Worker 	  struct filelist *new_file = n == 0 ? &null_file : NEW_FILE ();
637*7304104dSAndroid Build Coastguard Worker 
638*7304104dSAndroid Build Coastguard Worker 	  /* We follow the same rules as above for DWARF < 5, even
639*7304104dSAndroid Build Coastguard Worker 	     though the standard doesn't explicitly mention absolute
640*7304104dSAndroid Build Coastguard Worker 	     paths and ignoring the dir index.  */
641*7304104dSAndroid Build Coastguard Worker 	  if (*fname == '/')
642*7304104dSAndroid Build Coastguard Worker 	    /* It's an absolute path.  */
643*7304104dSAndroid Build Coastguard Worker 	    new_file->info.name = (char *) fname;
644*7304104dSAndroid Build Coastguard Worker 	  else
645*7304104dSAndroid Build Coastguard Worker 	    {
646*7304104dSAndroid Build Coastguard Worker 	      new_file->info.name = libdw_alloc (dbg, char, 1,
647*7304104dSAndroid Build Coastguard Worker 						 dirarray[diridx].len + 1
648*7304104dSAndroid Build Coastguard Worker 						 + fnamelen + 1);
649*7304104dSAndroid Build Coastguard Worker 	      char *cp = new_file->info.name;
650*7304104dSAndroid Build Coastguard Worker 
651*7304104dSAndroid Build Coastguard Worker 	      /* In the DWARF >= 5 case, dir can never be NULL.  */
652*7304104dSAndroid Build Coastguard Worker 	      cp = stpcpy (cp, dirarray[diridx].dir);
653*7304104dSAndroid Build Coastguard Worker 	      *cp++ = '/';
654*7304104dSAndroid Build Coastguard Worker 	      strcpy (cp, fname);
655*7304104dSAndroid Build Coastguard Worker 	      assert (strlen (new_file->info.name)
656*7304104dSAndroid Build Coastguard Worker 		      < dirarray[diridx].len + 1 + fnamelen + 1);
657*7304104dSAndroid Build Coastguard Worker 	    }
658*7304104dSAndroid Build Coastguard Worker 
659*7304104dSAndroid Build Coastguard Worker 	  /* For now we just ignore the modification time and file length.  */
660*7304104dSAndroid Build Coastguard Worker 	  new_file->info.mtime = 0;
661*7304104dSAndroid Build Coastguard Worker 	  new_file->info.length = 0;
662*7304104dSAndroid Build Coastguard Worker 	}
663*7304104dSAndroid Build Coastguard Worker     }
664*7304104dSAndroid Build Coastguard Worker 
665*7304104dSAndroid Build Coastguard Worker   unsigned int debug_str_offset = 0;
666*7304104dSAndroid Build Coastguard Worker   if (unlikely (linep == header_start + header_length - 4))
667*7304104dSAndroid Build Coastguard Worker     {
668*7304104dSAndroid Build Coastguard Worker       /* CUBINs contain an unsigned 4-byte offset */
669*7304104dSAndroid Build Coastguard Worker       debug_str_offset = read_4ubyte_unaligned_inc (dbg, linep);
670*7304104dSAndroid Build Coastguard Worker     }
671*7304104dSAndroid Build Coastguard Worker 
672*7304104dSAndroid Build Coastguard Worker   /* Consistency check.  */
673*7304104dSAndroid Build Coastguard Worker   if (unlikely (linep != header_start + header_length))
674*7304104dSAndroid Build Coastguard Worker     {
675*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_INVALID_DWARF);
676*7304104dSAndroid Build Coastguard Worker       goto out;
677*7304104dSAndroid Build Coastguard Worker     }
678*7304104dSAndroid Build Coastguard Worker 
679*7304104dSAndroid Build Coastguard Worker   /* We are about to process the statement program.  Most state machine
680*7304104dSAndroid Build Coastguard Worker      registers have already been initialize above.  Just add the is_stmt
681*7304104dSAndroid Build Coastguard Worker      default. See 6.2.2 in the v2.1 specification.  */
682*7304104dSAndroid Build Coastguard Worker   state.is_stmt = default_is_stmt;
683*7304104dSAndroid Build Coastguard Worker 
684*7304104dSAndroid Build Coastguard Worker   /* Apply the "operation advance" from a special opcode or
685*7304104dSAndroid Build Coastguard Worker      DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
686*7304104dSAndroid Build Coastguard Worker #define advance_pc(op_advance) \
687*7304104dSAndroid Build Coastguard Worker   run_advance_pc (&state, op_advance, minimum_instr_len, max_ops_per_instr)
688*7304104dSAndroid Build Coastguard Worker 
689*7304104dSAndroid Build Coastguard Worker   /* Process the instructions.  */
690*7304104dSAndroid Build Coastguard Worker 
691*7304104dSAndroid Build Coastguard Worker   /* Adds a new line to the matrix.  For the first MAX_STACK_LINES
692*7304104dSAndroid Build Coastguard Worker      entries just return a slot in the preallocated stack array.  */
693*7304104dSAndroid Build Coastguard Worker   struct linelist llstack[MAX_STACK_LINES];
694*7304104dSAndroid Build Coastguard Worker #define NEW_LINE(end_seq)						\
695*7304104dSAndroid Build Coastguard Worker   do {								\
696*7304104dSAndroid Build Coastguard Worker     struct linelist *ll = (state.nlinelist < MAX_STACK_LINES	\
697*7304104dSAndroid Build Coastguard Worker 			   ? &llstack[state.nlinelist]		\
698*7304104dSAndroid Build Coastguard Worker 			   : malloc (sizeof (struct linelist)));	\
699*7304104dSAndroid Build Coastguard Worker     if (unlikely (ll == NULL))					\
700*7304104dSAndroid Build Coastguard Worker       goto no_mem;						\
701*7304104dSAndroid Build Coastguard Worker     state.end_sequence = end_seq;				\
702*7304104dSAndroid Build Coastguard Worker     if (unlikely (add_new_line (&state, ll)))			\
703*7304104dSAndroid Build Coastguard Worker       goto invalid_data;						\
704*7304104dSAndroid Build Coastguard Worker   } while (0)
705*7304104dSAndroid Build Coastguard Worker 
706*7304104dSAndroid Build Coastguard Worker   while (linep < lineendp)
707*7304104dSAndroid Build Coastguard Worker     {
708*7304104dSAndroid Build Coastguard Worker       unsigned int opcode;
709*7304104dSAndroid Build Coastguard Worker       unsigned int u128;
710*7304104dSAndroid Build Coastguard Worker       int s128;
711*7304104dSAndroid Build Coastguard Worker 
712*7304104dSAndroid Build Coastguard Worker       /* Read the opcode.  */
713*7304104dSAndroid Build Coastguard Worker       opcode = *linep++;
714*7304104dSAndroid Build Coastguard Worker 
715*7304104dSAndroid Build Coastguard Worker       /* Is this a special opcode?  */
716*7304104dSAndroid Build Coastguard Worker       if (likely (opcode >= opcode_base))
717*7304104dSAndroid Build Coastguard Worker 	{
718*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (line_range == 0))
719*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
720*7304104dSAndroid Build Coastguard Worker 
721*7304104dSAndroid Build Coastguard Worker 	  /* Yes.  Handling this is quite easy since the opcode value
722*7304104dSAndroid Build Coastguard Worker 	     is computed with
723*7304104dSAndroid Build Coastguard Worker 
724*7304104dSAndroid Build Coastguard Worker 	     opcode = (desired line increment - line_base)
725*7304104dSAndroid Build Coastguard Worker 		       + (line_range * address advance) + opcode_base
726*7304104dSAndroid Build Coastguard Worker 	  */
727*7304104dSAndroid Build Coastguard Worker 	  int line_increment = (line_base
728*7304104dSAndroid Build Coastguard Worker 				+ (opcode - opcode_base) % line_range);
729*7304104dSAndroid Build Coastguard Worker 
730*7304104dSAndroid Build Coastguard Worker 	  /* Perform the increments.  */
731*7304104dSAndroid Build Coastguard Worker 	  state.line += line_increment;
732*7304104dSAndroid Build Coastguard Worker 	  advance_pc ((opcode - opcode_base) / line_range);
733*7304104dSAndroid Build Coastguard Worker 
734*7304104dSAndroid Build Coastguard Worker 	  /* Add a new line with the current state machine values.  */
735*7304104dSAndroid Build Coastguard Worker 	  NEW_LINE (0);
736*7304104dSAndroid Build Coastguard Worker 
737*7304104dSAndroid Build Coastguard Worker 	  /* Reset the flags.  */
738*7304104dSAndroid Build Coastguard Worker 	  state.basic_block = false;
739*7304104dSAndroid Build Coastguard Worker 	  state.prologue_end = false;
740*7304104dSAndroid Build Coastguard Worker 	  state.epilogue_begin = false;
741*7304104dSAndroid Build Coastguard Worker 	  state.discriminator = 0;
742*7304104dSAndroid Build Coastguard Worker 	}
743*7304104dSAndroid Build Coastguard Worker       else if (opcode == 0)
744*7304104dSAndroid Build Coastguard Worker 	{
745*7304104dSAndroid Build Coastguard Worker 	  /* This an extended opcode.  */
746*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (lineendp - linep < 2))
747*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
748*7304104dSAndroid Build Coastguard Worker 
749*7304104dSAndroid Build Coastguard Worker 	  /* The length.  */
750*7304104dSAndroid Build Coastguard Worker 	  uint_fast8_t len = *linep++;
751*7304104dSAndroid Build Coastguard Worker 
752*7304104dSAndroid Build Coastguard Worker 	  if (unlikely ((size_t) (lineendp - linep) < len))
753*7304104dSAndroid Build Coastguard Worker 	    goto invalid_data;
754*7304104dSAndroid Build Coastguard Worker 
755*7304104dSAndroid Build Coastguard Worker 	  /* The sub-opcode.  */
756*7304104dSAndroid Build Coastguard Worker 	  opcode = *linep++;
757*7304104dSAndroid Build Coastguard Worker 
758*7304104dSAndroid Build Coastguard Worker 	  switch (opcode)
759*7304104dSAndroid Build Coastguard Worker 	    {
760*7304104dSAndroid Build Coastguard Worker 	    case DW_LNE_end_sequence:
761*7304104dSAndroid Build Coastguard Worker 	      /* Add a new line with the current state machine values.
762*7304104dSAndroid Build Coastguard Worker 		 The is the end of the sequence.  */
763*7304104dSAndroid Build Coastguard Worker 	      NEW_LINE (1);
764*7304104dSAndroid Build Coastguard Worker 
765*7304104dSAndroid Build Coastguard Worker 	      /* Reset the registers.  */
766*7304104dSAndroid Build Coastguard Worker 	      state.addr = 0;
767*7304104dSAndroid Build Coastguard Worker 	      state.op_index = 0;
768*7304104dSAndroid Build Coastguard Worker 	      state.file = 1;
769*7304104dSAndroid Build Coastguard Worker 	      state.line = 1;
770*7304104dSAndroid Build Coastguard Worker 	      state.column = 0;
771*7304104dSAndroid Build Coastguard Worker 	      state.is_stmt = default_is_stmt;
772*7304104dSAndroid Build Coastguard Worker 	      state.basic_block = false;
773*7304104dSAndroid Build Coastguard Worker 	      state.prologue_end = false;
774*7304104dSAndroid Build Coastguard Worker 	      state.epilogue_begin = false;
775*7304104dSAndroid Build Coastguard Worker 	      state.isa = 0;
776*7304104dSAndroid Build Coastguard Worker 	      state.discriminator = 0;
777*7304104dSAndroid Build Coastguard Worker 	      state.context = 0;
778*7304104dSAndroid Build Coastguard Worker 	      state.function_name = 0;
779*7304104dSAndroid Build Coastguard Worker 	      break;
780*7304104dSAndroid Build Coastguard Worker 
781*7304104dSAndroid Build Coastguard Worker 	    case DW_LNE_set_address:
782*7304104dSAndroid Build Coastguard Worker 	      /* The value is an address.  The size is defined as
783*7304104dSAndroid Build Coastguard Worker 		 appropriate for the target machine.  We use the
784*7304104dSAndroid Build Coastguard Worker 		 address size field from the CU header.  */
785*7304104dSAndroid Build Coastguard Worker 	      state.op_index = 0;
786*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (lineendp - linep < (uint8_t) address_size))
787*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
788*7304104dSAndroid Build Coastguard Worker 	      if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
789*7304104dSAndroid Build Coastguard Worker 					    address_size, &state.addr))
790*7304104dSAndroid Build Coastguard Worker 		goto out;
791*7304104dSAndroid Build Coastguard Worker 	      break;
792*7304104dSAndroid Build Coastguard Worker 
793*7304104dSAndroid Build Coastguard Worker 	    case DW_LNE_define_file:
794*7304104dSAndroid Build Coastguard Worker 	      {
795*7304104dSAndroid Build Coastguard Worker 		char *fname = (char *) linep;
796*7304104dSAndroid Build Coastguard Worker 		uint8_t *endp = memchr (linep, '\0', lineendp - linep);
797*7304104dSAndroid Build Coastguard Worker 		if (endp == NULL)
798*7304104dSAndroid Build Coastguard Worker 		  goto invalid_data;
799*7304104dSAndroid Build Coastguard Worker 		size_t fnamelen = endp - linep;
800*7304104dSAndroid Build Coastguard Worker 		linep = endp + 1;
801*7304104dSAndroid Build Coastguard Worker 
802*7304104dSAndroid Build Coastguard Worker 		unsigned int diridx;
803*7304104dSAndroid Build Coastguard Worker 		if (unlikely (linep >= lineendp))
804*7304104dSAndroid Build Coastguard Worker 		  goto invalid_data;
805*7304104dSAndroid Build Coastguard Worker 		get_uleb128 (diridx, linep, lineendp);
806*7304104dSAndroid Build Coastguard Worker 		if (unlikely (diridx >= ndirlist))
807*7304104dSAndroid Build Coastguard Worker 		  {
808*7304104dSAndroid Build Coastguard Worker 		    __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
809*7304104dSAndroid Build Coastguard Worker 		    goto invalid_data;
810*7304104dSAndroid Build Coastguard Worker 		  }
811*7304104dSAndroid Build Coastguard Worker 		Dwarf_Word mtime;
812*7304104dSAndroid Build Coastguard Worker 		if (unlikely (linep >= lineendp))
813*7304104dSAndroid Build Coastguard Worker 		  goto invalid_data;
814*7304104dSAndroid Build Coastguard Worker 		get_uleb128 (mtime, linep, lineendp);
815*7304104dSAndroid Build Coastguard Worker 		Dwarf_Word filelength;
816*7304104dSAndroid Build Coastguard Worker 		if (unlikely (linep >= lineendp))
817*7304104dSAndroid Build Coastguard Worker 		  goto invalid_data;
818*7304104dSAndroid Build Coastguard Worker 		get_uleb128 (filelength, linep, lineendp);
819*7304104dSAndroid Build Coastguard Worker 
820*7304104dSAndroid Build Coastguard Worker 		struct filelist *new_file = NEW_FILE ();
821*7304104dSAndroid Build Coastguard Worker 		if (fname[0] == '/')
822*7304104dSAndroid Build Coastguard Worker 		  new_file->info.name = fname;
823*7304104dSAndroid Build Coastguard Worker 		else
824*7304104dSAndroid Build Coastguard Worker 		  {
825*7304104dSAndroid Build Coastguard Worker 		    new_file->info.name =
826*7304104dSAndroid Build Coastguard Worker 		      libdw_alloc (dbg, char, 1, (dirarray[diridx].len + 1
827*7304104dSAndroid Build Coastguard Worker 						  + fnamelen + 1));
828*7304104dSAndroid Build Coastguard Worker 		    char *cp = new_file->info.name;
829*7304104dSAndroid Build Coastguard Worker 
830*7304104dSAndroid Build Coastguard Worker 		    if (dirarray[diridx].dir != NULL)
831*7304104dSAndroid Build Coastguard Worker 		      /* This value could be NULL in case the
832*7304104dSAndroid Build Coastguard Worker 			 DW_AT_comp_dir was not present.  We
833*7304104dSAndroid Build Coastguard Worker 			 cannot do much in this case.  Just
834*7304104dSAndroid Build Coastguard Worker 			 keep the file relative.  */
835*7304104dSAndroid Build Coastguard Worker 		      {
836*7304104dSAndroid Build Coastguard Worker 			cp = stpcpy (cp, dirarray[diridx].dir);
837*7304104dSAndroid Build Coastguard Worker 			*cp++ = '/';
838*7304104dSAndroid Build Coastguard Worker 		      }
839*7304104dSAndroid Build Coastguard Worker 		    strcpy (cp, fname);
840*7304104dSAndroid Build Coastguard Worker 		  }
841*7304104dSAndroid Build Coastguard Worker 
842*7304104dSAndroid Build Coastguard Worker 		new_file->info.mtime = mtime;
843*7304104dSAndroid Build Coastguard Worker 		new_file->info.length = filelength;
844*7304104dSAndroid Build Coastguard Worker 	      }
845*7304104dSAndroid Build Coastguard Worker 	      break;
846*7304104dSAndroid Build Coastguard Worker 
847*7304104dSAndroid Build Coastguard Worker 	    case DW_LNE_set_discriminator:
848*7304104dSAndroid Build Coastguard Worker 	      /* Takes one ULEB128 parameter, the discriminator.  */
849*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
850*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
851*7304104dSAndroid Build Coastguard Worker 
852*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
853*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
854*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (state.discriminator, linep, lineendp);
855*7304104dSAndroid Build Coastguard Worker 	      break;
856*7304104dSAndroid Build Coastguard Worker 
857*7304104dSAndroid Build Coastguard Worker 	    case DW_LNE_NVIDIA_inlined_call:
858*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
859*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
860*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (state.context, linep, lineendp);
861*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
862*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
863*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (state.function_name, linep, lineendp);
864*7304104dSAndroid Build Coastguard Worker 	      state.function_name += debug_str_offset;
865*7304104dSAndroid Build Coastguard Worker 	      break;
866*7304104dSAndroid Build Coastguard Worker 
867*7304104dSAndroid Build Coastguard Worker 	    case DW_LNE_NVIDIA_set_function_name:
868*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
869*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
870*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (state.function_name, linep, lineendp);
871*7304104dSAndroid Build Coastguard Worker 	      state.function_name += debug_str_offset;
872*7304104dSAndroid Build Coastguard Worker 	      break;
873*7304104dSAndroid Build Coastguard Worker 
874*7304104dSAndroid Build Coastguard Worker 	    default:
875*7304104dSAndroid Build Coastguard Worker 	      /* Unknown, ignore it.  */
876*7304104dSAndroid Build Coastguard Worker 	      if (unlikely ((size_t) (lineendp - (linep - 1)) < len))
877*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
878*7304104dSAndroid Build Coastguard Worker 	      linep += len - 1;
879*7304104dSAndroid Build Coastguard Worker 	      break;
880*7304104dSAndroid Build Coastguard Worker 	    }
881*7304104dSAndroid Build Coastguard Worker 	}
882*7304104dSAndroid Build Coastguard Worker       else if (opcode <= DW_LNS_set_isa)
883*7304104dSAndroid Build Coastguard Worker 	{
884*7304104dSAndroid Build Coastguard Worker 	  /* This is a known standard opcode.  */
885*7304104dSAndroid Build Coastguard Worker 	  switch (opcode)
886*7304104dSAndroid Build Coastguard Worker 	    {
887*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_copy:
888*7304104dSAndroid Build Coastguard Worker 	      /* Takes no argument.  */
889*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 0))
890*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
891*7304104dSAndroid Build Coastguard Worker 
892*7304104dSAndroid Build Coastguard Worker 	      /* Add a new line with the current state machine values.  */
893*7304104dSAndroid Build Coastguard Worker 	      NEW_LINE (0);
894*7304104dSAndroid Build Coastguard Worker 
895*7304104dSAndroid Build Coastguard Worker 	      /* Reset the flags.  */
896*7304104dSAndroid Build Coastguard Worker 	      state.basic_block = false;
897*7304104dSAndroid Build Coastguard Worker 	      state.prologue_end = false;
898*7304104dSAndroid Build Coastguard Worker 	      state.epilogue_begin = false;
899*7304104dSAndroid Build Coastguard Worker 	      state.discriminator = 0;
900*7304104dSAndroid Build Coastguard Worker 	      break;
901*7304104dSAndroid Build Coastguard Worker 
902*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_advance_pc:
903*7304104dSAndroid Build Coastguard Worker 	      /* Takes one uleb128 parameter which is added to the
904*7304104dSAndroid Build Coastguard Worker 		 address.  */
905*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
906*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
907*7304104dSAndroid Build Coastguard Worker 
908*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
909*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
910*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, linep, lineendp);
911*7304104dSAndroid Build Coastguard Worker 	      advance_pc (u128);
912*7304104dSAndroid Build Coastguard Worker 	      break;
913*7304104dSAndroid Build Coastguard Worker 
914*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_advance_line:
915*7304104dSAndroid Build Coastguard Worker 	      /* Takes one sleb128 parameter which is added to the
916*7304104dSAndroid Build Coastguard Worker 		 line.  */
917*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
918*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
919*7304104dSAndroid Build Coastguard Worker 
920*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
921*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
922*7304104dSAndroid Build Coastguard Worker 	      get_sleb128 (s128, linep, lineendp);
923*7304104dSAndroid Build Coastguard Worker 	      state.line += s128;
924*7304104dSAndroid Build Coastguard Worker 	      break;
925*7304104dSAndroid Build Coastguard Worker 
926*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_set_file:
927*7304104dSAndroid Build Coastguard Worker 	      /* Takes one uleb128 parameter which is stored in file.  */
928*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
929*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
930*7304104dSAndroid Build Coastguard Worker 
931*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
932*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
933*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, linep, lineendp);
934*7304104dSAndroid Build Coastguard Worker 	      state.file = u128;
935*7304104dSAndroid Build Coastguard Worker 	      break;
936*7304104dSAndroid Build Coastguard Worker 
937*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_set_column:
938*7304104dSAndroid Build Coastguard Worker 	      /* Takes one uleb128 parameter which is stored in column.  */
939*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
940*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
941*7304104dSAndroid Build Coastguard Worker 
942*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
943*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
944*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, linep, lineendp);
945*7304104dSAndroid Build Coastguard Worker 	      state.column = u128;
946*7304104dSAndroid Build Coastguard Worker 	      break;
947*7304104dSAndroid Build Coastguard Worker 
948*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_negate_stmt:
949*7304104dSAndroid Build Coastguard Worker 	      /* Takes no argument.  */
950*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 0))
951*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
952*7304104dSAndroid Build Coastguard Worker 
953*7304104dSAndroid Build Coastguard Worker 	      state.is_stmt = 1 - state.is_stmt;
954*7304104dSAndroid Build Coastguard Worker 	      break;
955*7304104dSAndroid Build Coastguard Worker 
956*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_set_basic_block:
957*7304104dSAndroid Build Coastguard Worker 	      /* Takes no argument.  */
958*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 0))
959*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
960*7304104dSAndroid Build Coastguard Worker 
961*7304104dSAndroid Build Coastguard Worker 	      state.basic_block = true;
962*7304104dSAndroid Build Coastguard Worker 	      break;
963*7304104dSAndroid Build Coastguard Worker 
964*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_const_add_pc:
965*7304104dSAndroid Build Coastguard Worker 	      /* Takes no argument.  */
966*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 0))
967*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
968*7304104dSAndroid Build Coastguard Worker 
969*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (line_range == 0))
970*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
971*7304104dSAndroid Build Coastguard Worker 
972*7304104dSAndroid Build Coastguard Worker 	      advance_pc ((255 - opcode_base) / line_range);
973*7304104dSAndroid Build Coastguard Worker 	      break;
974*7304104dSAndroid Build Coastguard Worker 
975*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_fixed_advance_pc:
976*7304104dSAndroid Build Coastguard Worker 	      /* Takes one 16 bit parameter which is added to the
977*7304104dSAndroid Build Coastguard Worker 		 address.  */
978*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 1)
979*7304104dSAndroid Build Coastguard Worker 		  || unlikely (lineendp - linep < 2))
980*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
981*7304104dSAndroid Build Coastguard Worker 
982*7304104dSAndroid Build Coastguard Worker 	      state.addr += read_2ubyte_unaligned_inc (dbg, linep);
983*7304104dSAndroid Build Coastguard Worker 	      state.op_index = 0;
984*7304104dSAndroid Build Coastguard Worker 	      break;
985*7304104dSAndroid Build Coastguard Worker 
986*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_set_prologue_end:
987*7304104dSAndroid Build Coastguard Worker 	      /* Takes no argument.  */
988*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 0))
989*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
990*7304104dSAndroid Build Coastguard Worker 
991*7304104dSAndroid Build Coastguard Worker 	      state.prologue_end = true;
992*7304104dSAndroid Build Coastguard Worker 	      break;
993*7304104dSAndroid Build Coastguard Worker 
994*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_set_epilogue_begin:
995*7304104dSAndroid Build Coastguard Worker 	      /* Takes no argument.  */
996*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 0))
997*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
998*7304104dSAndroid Build Coastguard Worker 
999*7304104dSAndroid Build Coastguard Worker 	      state.epilogue_begin = true;
1000*7304104dSAndroid Build Coastguard Worker 	      break;
1001*7304104dSAndroid Build Coastguard Worker 
1002*7304104dSAndroid Build Coastguard Worker 	    case DW_LNS_set_isa:
1003*7304104dSAndroid Build Coastguard Worker 	      /* Takes one uleb128 parameter which is stored in isa.  */
1004*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
1005*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
1006*7304104dSAndroid Build Coastguard Worker 
1007*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
1008*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
1009*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (state.isa, linep, lineendp);
1010*7304104dSAndroid Build Coastguard Worker 	      break;
1011*7304104dSAndroid Build Coastguard Worker 	    }
1012*7304104dSAndroid Build Coastguard Worker 	}
1013*7304104dSAndroid Build Coastguard Worker       else
1014*7304104dSAndroid Build Coastguard Worker 	{
1015*7304104dSAndroid Build Coastguard Worker 	  /* This is a new opcode the generator but not we know about.
1016*7304104dSAndroid Build Coastguard Worker 	     Read the parameters associated with it but then discard
1017*7304104dSAndroid Build Coastguard Worker 	     everything.  Read all the parameters for this opcode.  */
1018*7304104dSAndroid Build Coastguard Worker 	  for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
1019*7304104dSAndroid Build Coastguard Worker 	    {
1020*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (linep >= lineendp))
1021*7304104dSAndroid Build Coastguard Worker 		goto invalid_data;
1022*7304104dSAndroid Build Coastguard Worker 	      get_uleb128 (u128, linep, lineendp);
1023*7304104dSAndroid Build Coastguard Worker 	    }
1024*7304104dSAndroid Build Coastguard Worker 
1025*7304104dSAndroid Build Coastguard Worker 	  /* Next round, ignore this opcode.  */
1026*7304104dSAndroid Build Coastguard Worker 	  continue;
1027*7304104dSAndroid Build Coastguard Worker 	}
1028*7304104dSAndroid Build Coastguard Worker     }
1029*7304104dSAndroid Build Coastguard Worker 
1030*7304104dSAndroid Build Coastguard Worker   /* Put all the files in an array.  */
1031*7304104dSAndroid Build Coastguard Worker   Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
1032*7304104dSAndroid Build Coastguard Worker 				    sizeof (Dwarf_Files)
1033*7304104dSAndroid Build Coastguard Worker 				    + nfilelist * sizeof (Dwarf_Fileinfo)
1034*7304104dSAndroid Build Coastguard Worker 				    + (ndirlist + 1) * sizeof (char *),
1035*7304104dSAndroid Build Coastguard Worker 				    1);
1036*7304104dSAndroid Build Coastguard Worker   const char **dirs = (void *) &files->info[nfilelist];
1037*7304104dSAndroid Build Coastguard Worker 
1038*7304104dSAndroid Build Coastguard Worker   struct filelist *fileslist = filelist;
1039*7304104dSAndroid Build Coastguard Worker   files->nfiles = nfilelist;
1040*7304104dSAndroid Build Coastguard Worker   for (size_t n = nfilelist; n > 0; n--)
1041*7304104dSAndroid Build Coastguard Worker     {
1042*7304104dSAndroid Build Coastguard Worker       files->info[n - 1] = fileslist->info;
1043*7304104dSAndroid Build Coastguard Worker       fileslist = fileslist->next;
1044*7304104dSAndroid Build Coastguard Worker     }
1045*7304104dSAndroid Build Coastguard Worker   assert (fileslist == NULL);
1046*7304104dSAndroid Build Coastguard Worker 
1047*7304104dSAndroid Build Coastguard Worker   /* Put all the directory strings in an array.  */
1048*7304104dSAndroid Build Coastguard Worker   files->ndirs = ndirlist;
1049*7304104dSAndroid Build Coastguard Worker   for (unsigned int i = 0; i < ndirlist; ++i)
1050*7304104dSAndroid Build Coastguard Worker     dirs[i] = dirarray[i].dir;
1051*7304104dSAndroid Build Coastguard Worker   dirs[ndirlist] = NULL;
1052*7304104dSAndroid Build Coastguard Worker 
1053*7304104dSAndroid Build Coastguard Worker   /* Pass the file data structure to the caller.  */
1054*7304104dSAndroid Build Coastguard Worker   if (filesp != NULL)
1055*7304104dSAndroid Build Coastguard Worker     *filesp = files;
1056*7304104dSAndroid Build Coastguard Worker 
1057*7304104dSAndroid Build Coastguard Worker   size_t buf_size = (sizeof (Dwarf_Lines)
1058*7304104dSAndroid Build Coastguard Worker 		     + (sizeof (Dwarf_Line) * state.nlinelist));
1059*7304104dSAndroid Build Coastguard Worker   void *buf = libdw_alloc (dbg, Dwarf_Lines, buf_size, 1);
1060*7304104dSAndroid Build Coastguard Worker 
1061*7304104dSAndroid Build Coastguard Worker   /* First use the buffer for the pointers, and sort the entries.
1062*7304104dSAndroid Build Coastguard Worker      We'll write the pointers in the end of the buffer, and then
1063*7304104dSAndroid Build Coastguard Worker      copy into the buffer from the beginning so the overlap works.  */
1064*7304104dSAndroid Build Coastguard Worker   assert (sizeof (Dwarf_Line) >= sizeof (struct linelist *));
1065*7304104dSAndroid Build Coastguard Worker   struct linelist **sortlines = (buf + buf_size
1066*7304104dSAndroid Build Coastguard Worker 				 - sizeof (struct linelist **) * state.nlinelist);
1067*7304104dSAndroid Build Coastguard Worker 
1068*7304104dSAndroid Build Coastguard Worker   /* The list is in LIFO order and usually they come in clumps with
1069*7304104dSAndroid Build Coastguard Worker      ascending addresses.  So fill from the back to probably start with
1070*7304104dSAndroid Build Coastguard Worker      runs already in order before we sort.  */
1071*7304104dSAndroid Build Coastguard Worker   struct linelist *lineslist = state.linelist;
1072*7304104dSAndroid Build Coastguard Worker   for (size_t i = state.nlinelist; i-- > 0; )
1073*7304104dSAndroid Build Coastguard Worker     {
1074*7304104dSAndroid Build Coastguard Worker       sortlines[i] = lineslist;
1075*7304104dSAndroid Build Coastguard Worker       lineslist = lineslist->next;
1076*7304104dSAndroid Build Coastguard Worker     }
1077*7304104dSAndroid Build Coastguard Worker   assert (lineslist == NULL);
1078*7304104dSAndroid Build Coastguard Worker 
1079*7304104dSAndroid Build Coastguard Worker   /* Sort by ascending address.  */
1080*7304104dSAndroid Build Coastguard Worker   qsort (sortlines, state.nlinelist, sizeof sortlines[0], &compare_lines);
1081*7304104dSAndroid Build Coastguard Worker 
1082*7304104dSAndroid Build Coastguard Worker   /* Now that they are sorted, put them in the final array.
1083*7304104dSAndroid Build Coastguard Worker      The buffers overlap, so we've clobbered the early elements
1084*7304104dSAndroid Build Coastguard Worker      of SORTLINES by the time we're reading the later ones.  */
1085*7304104dSAndroid Build Coastguard Worker   Dwarf_Lines *lines = buf;
1086*7304104dSAndroid Build Coastguard Worker   lines->nlines = state.nlinelist;
1087*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < state.nlinelist; ++i)
1088*7304104dSAndroid Build Coastguard Worker     {
1089*7304104dSAndroid Build Coastguard Worker       lines->info[i] = sortlines[i]->line;
1090*7304104dSAndroid Build Coastguard Worker       lines->info[i].files = files;
1091*7304104dSAndroid Build Coastguard Worker     }
1092*7304104dSAndroid Build Coastguard Worker 
1093*7304104dSAndroid Build Coastguard Worker   /* Make sure the highest address for the CU is marked as end_sequence.
1094*7304104dSAndroid Build Coastguard Worker      This is required by the DWARF spec, but some compilers forget and
1095*7304104dSAndroid Build Coastguard Worker      dwfl_module_getsrc depends on it.  */
1096*7304104dSAndroid Build Coastguard Worker   if (state.nlinelist > 0)
1097*7304104dSAndroid Build Coastguard Worker     lines->info[state.nlinelist - 1].end_sequence = 1;
1098*7304104dSAndroid Build Coastguard Worker 
1099*7304104dSAndroid Build Coastguard Worker   /* Pass the line structure back to the caller.  */
1100*7304104dSAndroid Build Coastguard Worker   if (linesp != NULL)
1101*7304104dSAndroid Build Coastguard Worker     *linesp = lines;
1102*7304104dSAndroid Build Coastguard Worker 
1103*7304104dSAndroid Build Coastguard Worker   /* Success.  */
1104*7304104dSAndroid Build Coastguard Worker   res = 0;
1105*7304104dSAndroid Build Coastguard Worker 
1106*7304104dSAndroid Build Coastguard Worker  out:
1107*7304104dSAndroid Build Coastguard Worker   /* Free malloced line records, if any.  */
1108*7304104dSAndroid Build Coastguard Worker   for (size_t i = MAX_STACK_LINES; i < state.nlinelist; i++)
1109*7304104dSAndroid Build Coastguard Worker     {
1110*7304104dSAndroid Build Coastguard Worker       struct linelist *ll = state.linelist->next;
1111*7304104dSAndroid Build Coastguard Worker       free (state.linelist);
1112*7304104dSAndroid Build Coastguard Worker       state.linelist = ll;
1113*7304104dSAndroid Build Coastguard Worker     }
1114*7304104dSAndroid Build Coastguard Worker   if (dirarray != dirstack)
1115*7304104dSAndroid Build Coastguard Worker     free (dirarray);
1116*7304104dSAndroid Build Coastguard Worker   for (size_t i = MAX_STACK_FILES; i < nfilelist; i++)
1117*7304104dSAndroid Build Coastguard Worker     {
1118*7304104dSAndroid Build Coastguard Worker       struct filelist *fl = filelist->next;
1119*7304104dSAndroid Build Coastguard Worker       free (filelist);
1120*7304104dSAndroid Build Coastguard Worker       filelist = fl;
1121*7304104dSAndroid Build Coastguard Worker     }
1122*7304104dSAndroid Build Coastguard Worker 
1123*7304104dSAndroid Build Coastguard Worker   return res;
1124*7304104dSAndroid Build Coastguard Worker }
1125*7304104dSAndroid Build Coastguard Worker 
1126*7304104dSAndroid Build Coastguard Worker static int
files_lines_compare(const void * p1,const void * p2)1127*7304104dSAndroid Build Coastguard Worker files_lines_compare (const void *p1, const void *p2)
1128*7304104dSAndroid Build Coastguard Worker {
1129*7304104dSAndroid Build Coastguard Worker   const struct files_lines_s *t1 = p1;
1130*7304104dSAndroid Build Coastguard Worker   const struct files_lines_s *t2 = p2;
1131*7304104dSAndroid Build Coastguard Worker 
1132*7304104dSAndroid Build Coastguard Worker   if (t1->debug_line_offset < t2->debug_line_offset)
1133*7304104dSAndroid Build Coastguard Worker     return -1;
1134*7304104dSAndroid Build Coastguard Worker   if (t1->debug_line_offset > t2->debug_line_offset)
1135*7304104dSAndroid Build Coastguard Worker     return 1;
1136*7304104dSAndroid Build Coastguard Worker 
1137*7304104dSAndroid Build Coastguard Worker   return 0;
1138*7304104dSAndroid Build Coastguard Worker }
1139*7304104dSAndroid Build Coastguard Worker 
1140*7304104dSAndroid Build Coastguard Worker int
1141*7304104dSAndroid Build Coastguard Worker internal_function
__libdw_getsrclines(Dwarf * dbg,Dwarf_Off debug_line_offset,const char * comp_dir,unsigned address_size,Dwarf_Lines ** linesp,Dwarf_Files ** filesp)1142*7304104dSAndroid Build Coastguard Worker __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
1143*7304104dSAndroid Build Coastguard Worker 		     const char *comp_dir, unsigned address_size,
1144*7304104dSAndroid Build Coastguard Worker 		     Dwarf_Lines **linesp, Dwarf_Files **filesp)
1145*7304104dSAndroid Build Coastguard Worker {
1146*7304104dSAndroid Build Coastguard Worker   struct files_lines_s fake = { .debug_line_offset = debug_line_offset };
1147*7304104dSAndroid Build Coastguard Worker   struct files_lines_s **found = tfind (&fake, &dbg->files_lines,
1148*7304104dSAndroid Build Coastguard Worker 					files_lines_compare);
1149*7304104dSAndroid Build Coastguard Worker   if (found == NULL)
1150*7304104dSAndroid Build Coastguard Worker     {
1151*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = __libdw_checked_get_data (dbg, IDX_debug_line);
1152*7304104dSAndroid Build Coastguard Worker       if (data == NULL
1153*7304104dSAndroid Build Coastguard Worker 	  || __libdw_offset_in_section (dbg, IDX_debug_line,
1154*7304104dSAndroid Build Coastguard Worker 					debug_line_offset, 1) != 0)
1155*7304104dSAndroid Build Coastguard Worker 	return -1;
1156*7304104dSAndroid Build Coastguard Worker 
1157*7304104dSAndroid Build Coastguard Worker       const unsigned char *linep = data->d_buf + debug_line_offset;
1158*7304104dSAndroid Build Coastguard Worker       const unsigned char *lineendp = data->d_buf + data->d_size;
1159*7304104dSAndroid Build Coastguard Worker 
1160*7304104dSAndroid Build Coastguard Worker       struct files_lines_s *node = libdw_alloc (dbg, struct files_lines_s,
1161*7304104dSAndroid Build Coastguard Worker 						sizeof *node, 1);
1162*7304104dSAndroid Build Coastguard Worker 
1163*7304104dSAndroid Build Coastguard Worker       if (read_srclines (dbg, linep, lineendp, comp_dir, address_size,
1164*7304104dSAndroid Build Coastguard Worker 			 &node->lines, &node->files) != 0)
1165*7304104dSAndroid Build Coastguard Worker 	return -1;
1166*7304104dSAndroid Build Coastguard Worker 
1167*7304104dSAndroid Build Coastguard Worker       node->debug_line_offset = debug_line_offset;
1168*7304104dSAndroid Build Coastguard Worker 
1169*7304104dSAndroid Build Coastguard Worker       found = tsearch (node, &dbg->files_lines, files_lines_compare);
1170*7304104dSAndroid Build Coastguard Worker       if (found == NULL)
1171*7304104dSAndroid Build Coastguard Worker 	{
1172*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_NOMEM);
1173*7304104dSAndroid Build Coastguard Worker 	  return -1;
1174*7304104dSAndroid Build Coastguard Worker 	}
1175*7304104dSAndroid Build Coastguard Worker     }
1176*7304104dSAndroid Build Coastguard Worker 
1177*7304104dSAndroid Build Coastguard Worker   if (linesp != NULL)
1178*7304104dSAndroid Build Coastguard Worker     *linesp = (*found)->lines;
1179*7304104dSAndroid Build Coastguard Worker 
1180*7304104dSAndroid Build Coastguard Worker   if (filesp != NULL)
1181*7304104dSAndroid Build Coastguard Worker     *filesp = (*found)->files;
1182*7304104dSAndroid Build Coastguard Worker 
1183*7304104dSAndroid Build Coastguard Worker   return 0;
1184*7304104dSAndroid Build Coastguard Worker }
1185*7304104dSAndroid Build Coastguard Worker 
1186*7304104dSAndroid Build Coastguard Worker /* Get the compilation directory, if any is set.  */
1187*7304104dSAndroid Build Coastguard Worker const char *
__libdw_getcompdir(Dwarf_Die * cudie)1188*7304104dSAndroid Build Coastguard Worker __libdw_getcompdir (Dwarf_Die *cudie)
1189*7304104dSAndroid Build Coastguard Worker {
1190*7304104dSAndroid Build Coastguard Worker   Dwarf_Attribute compdir_attr_mem;
1191*7304104dSAndroid Build Coastguard Worker   Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
1192*7304104dSAndroid Build Coastguard Worker 						      DW_AT_comp_dir,
1193*7304104dSAndroid Build Coastguard Worker 						      &compdir_attr_mem);
1194*7304104dSAndroid Build Coastguard Worker   return INTUSE(dwarf_formstring) (compdir_attr);
1195*7304104dSAndroid Build Coastguard Worker }
1196*7304104dSAndroid Build Coastguard Worker 
1197*7304104dSAndroid Build Coastguard Worker int
dwarf_getsrclines(Dwarf_Die * cudie,Dwarf_Lines ** lines,size_t * nlines)1198*7304104dSAndroid Build Coastguard Worker dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
1199*7304104dSAndroid Build Coastguard Worker {
1200*7304104dSAndroid Build Coastguard Worker   if (cudie == NULL)
1201*7304104dSAndroid Build Coastguard Worker     return -1;
1202*7304104dSAndroid Build Coastguard Worker   if (! is_cudie (cudie))
1203*7304104dSAndroid Build Coastguard Worker     {
1204*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_NOT_CUDIE);
1205*7304104dSAndroid Build Coastguard Worker       return -1;
1206*7304104dSAndroid Build Coastguard Worker     }
1207*7304104dSAndroid Build Coastguard Worker 
1208*7304104dSAndroid Build Coastguard Worker   /* Get the information if it is not already known.  */
1209*7304104dSAndroid Build Coastguard Worker   struct Dwarf_CU *const cu = cudie->cu;
1210*7304104dSAndroid Build Coastguard Worker   if (cu->lines == NULL)
1211*7304104dSAndroid Build Coastguard Worker     {
1212*7304104dSAndroid Build Coastguard Worker       /* For split units always pick the lines from the skeleton.  */
1213*7304104dSAndroid Build Coastguard Worker       if (cu->unit_type == DW_UT_split_compile
1214*7304104dSAndroid Build Coastguard Worker 	  || cu->unit_type == DW_UT_split_type)
1215*7304104dSAndroid Build Coastguard Worker 	{
1216*7304104dSAndroid Build Coastguard Worker 	  /* We tries, assume we fail...  */
1217*7304104dSAndroid Build Coastguard Worker 	  cu->lines = (void *) -1l;
1218*7304104dSAndroid Build Coastguard Worker 
1219*7304104dSAndroid Build Coastguard Worker 	  Dwarf_CU *skel = __libdw_find_split_unit (cu);
1220*7304104dSAndroid Build Coastguard Worker 	  if (skel != NULL)
1221*7304104dSAndroid Build Coastguard Worker 	    {
1222*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Die skeldie = CUDIE (skel);
1223*7304104dSAndroid Build Coastguard Worker 	      int res = INTUSE(dwarf_getsrclines) (&skeldie, lines, nlines);
1224*7304104dSAndroid Build Coastguard Worker 	      if (res == 0)
1225*7304104dSAndroid Build Coastguard Worker 		{
1226*7304104dSAndroid Build Coastguard Worker 		  cu->lines = skel->lines;
1227*7304104dSAndroid Build Coastguard Worker 		  *lines = cu->lines;
1228*7304104dSAndroid Build Coastguard Worker 		  *nlines = cu->lines->nlines;
1229*7304104dSAndroid Build Coastguard Worker 		}
1230*7304104dSAndroid Build Coastguard Worker 	      return res;
1231*7304104dSAndroid Build Coastguard Worker 	    }
1232*7304104dSAndroid Build Coastguard Worker 
1233*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
1234*7304104dSAndroid Build Coastguard Worker 	  return -1;
1235*7304104dSAndroid Build Coastguard Worker 	}
1236*7304104dSAndroid Build Coastguard Worker 
1237*7304104dSAndroid Build Coastguard Worker       /* Failsafe mode: no data found.  */
1238*7304104dSAndroid Build Coastguard Worker       cu->lines = (void *) -1l;
1239*7304104dSAndroid Build Coastguard Worker       cu->files = (void *) -1l;
1240*7304104dSAndroid Build Coastguard Worker 
1241*7304104dSAndroid Build Coastguard Worker       /* The die must have a statement list associated.  */
1242*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute stmt_list_mem;
1243*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
1244*7304104dSAndroid Build Coastguard Worker 						       &stmt_list_mem);
1245*7304104dSAndroid Build Coastguard Worker 
1246*7304104dSAndroid Build Coastguard Worker       /* Get the offset into the .debug_line section.  NB: this call
1247*7304104dSAndroid Build Coastguard Worker 	 also checks whether the previous dwarf_attr call failed.  */
1248*7304104dSAndroid Build Coastguard Worker       Dwarf_Off debug_line_offset;
1249*7304104dSAndroid Build Coastguard Worker       if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
1250*7304104dSAndroid Build Coastguard Worker 			   NULL, &debug_line_offset) == NULL)
1251*7304104dSAndroid Build Coastguard Worker 	return -1;
1252*7304104dSAndroid Build Coastguard Worker 
1253*7304104dSAndroid Build Coastguard Worker       if (__libdw_getsrclines (cu->dbg, debug_line_offset,
1254*7304104dSAndroid Build Coastguard Worker 			       __libdw_getcompdir (cudie),
1255*7304104dSAndroid Build Coastguard Worker 			       cu->address_size, &cu->lines, &cu->files) < 0)
1256*7304104dSAndroid Build Coastguard Worker 	return -1;
1257*7304104dSAndroid Build Coastguard Worker     }
1258*7304104dSAndroid Build Coastguard Worker   else if (cu->lines == (void *) -1l)
1259*7304104dSAndroid Build Coastguard Worker     return -1;
1260*7304104dSAndroid Build Coastguard Worker 
1261*7304104dSAndroid Build Coastguard Worker   *lines = cu->lines;
1262*7304104dSAndroid Build Coastguard Worker   *nlines = cu->lines->nlines;
1263*7304104dSAndroid Build Coastguard Worker 
1264*7304104dSAndroid Build Coastguard Worker   // XXX Eventually: unlocking here.
1265*7304104dSAndroid Build Coastguard Worker 
1266*7304104dSAndroid Build Coastguard Worker   return 0;
1267*7304104dSAndroid Build Coastguard Worker }
1268*7304104dSAndroid Build Coastguard Worker INTDEF(dwarf_getsrclines)
1269