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