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