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