Branch data Line data Source code
1 : : /* Return line number information of CU.
2 : : Copyright (C) 2004-2010 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2004.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include <assert.h>
35 : : #include <stdlib.h>
36 : : #include <string.h>
37 : : #include "dwarf.h"
38 : : #include "libdwP.h"
39 : :
40 : :
41 : : struct filelist
42 : : {
43 : : Dwarf_Fileinfo info;
44 : : struct filelist *next;
45 : : };
46 : :
47 : : struct linelist
48 : : {
49 : : Dwarf_Line line;
50 : : struct linelist *next;
51 : : };
52 : :
53 : :
54 : : /* Compare by Dwarf_Line.addr, given pointers into an array of pointers. */
55 : : static int
56 : 4842182 : compare_lines (const void *a, const void *b)
57 : : {
58 : 4842182 : Dwarf_Line *const *p1 = a;
59 : 4842182 : Dwarf_Line *const *p2 = b;
60 : :
61 [ + + ]: 4842182 : if ((*p1)->addr == (*p2)->addr)
62 : : /* An end_sequence marker precedes a normal record at the same address. */
63 : 9457 : return (*p2)->end_sequence - (*p1)->end_sequence;
64 : :
65 : 4842182 : return (*p1)->addr - (*p2)->addr;
66 : : }
67 : :
68 : : int
69 : 14112 : dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
70 : : {
71 [ + - ][ + - ]: 14112 : if (unlikely (cudie == NULL
72 : : || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
73 : : return -1;
74 : :
75 : 14112 : int res = -1;
76 : :
77 : : /* Get the information if it is not already known. */
78 : 14112 : struct Dwarf_CU *const cu = cudie->cu;
79 [ + + ]: 14112 : if (cu->lines == NULL)
80 : : {
81 : : /* Failsafe mode: no data found. */
82 : 14092 : cu->lines = (void *) -1l;
83 : 14092 : cu->files = (void *) -1l;
84 : :
85 : : /* The die must have a statement list associated. */
86 : : Dwarf_Attribute stmt_list_mem;
87 : 14092 : Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
88 : : &stmt_list_mem);
89 : :
90 : : /* Get the offset into the .debug_line section. NB: this call
91 : : also checks whether the previous dwarf_attr call failed. */
92 : : const unsigned char *lineendp;
93 : 14092 : const unsigned char *linep
94 : 14092 : = __libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
95 : : (unsigned char **) &lineendp, NULL);
96 [ + - ]: 14092 : if (linep == NULL)
97 : : goto out;
98 : :
99 : : /* Get the compilation directory. */
100 : : Dwarf_Attribute compdir_attr_mem;
101 : 14092 : Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
102 : : DW_AT_comp_dir,
103 : : &compdir_attr_mem);
104 : 14092 : const char *comp_dir = INTUSE(dwarf_formstring) (compdir_attr);
105 : :
106 [ - + ]: 14092 : if (unlikely (linep + 4 > lineendp))
107 : : {
108 : : invalid_data:
109 : 0 : __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
110 : : goto out;
111 : : }
112 : :
113 : 14092 : Dwarf *dbg = cu->dbg;
114 [ + + ][ - + ]: 14092 : Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
115 : 14092 : unsigned int length = 4;
116 [ - + ]: 14092 : if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
117 : : {
118 [ # # ]: 0 : if (unlikely (linep + 8 > lineendp))
119 : : goto invalid_data;
120 [ # # ][ # # ]: 0 : unit_length = read_8ubyte_unaligned_inc (dbg, linep);
121 : 0 : length = 8;
122 : : }
123 : :
124 : : /* Check whether we have enough room in the section. */
125 [ - + ]: 14092 : if (unit_length < 2 + length + 5 * 1
126 [ - + ]: 14092 : || unlikely (linep + unit_length > lineendp))
127 : : goto invalid_data;
128 : 14092 : lineendp = linep + unit_length;
129 : :
130 : : /* The next element of the header is the version identifier. */
131 [ + + ][ - + ]: 14092 : uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
132 [ + - ][ - + ]: 14092 : if (unlikely (version < 2) || unlikely (version > 4))
133 : : {
134 : 0 : __libdw_seterrno (DWARF_E_VERSION);
135 : : goto out;
136 : : }
137 : :
138 : : /* Next comes the header length. */
139 : : Dwarf_Word header_length;
140 [ + - ]: 14092 : if (length == 4)
141 [ + + ][ - + ]: 14092 : header_length = read_4ubyte_unaligned_inc (dbg, linep);
142 : : else
143 [ # # ][ # # ]: 0 : header_length = read_8ubyte_unaligned_inc (dbg, linep);
144 : 14092 : const unsigned char *header_start = linep;
145 : :
146 : : /* Next the minimum instruction length. */
147 : 14092 : uint_fast8_t minimum_instr_len = *linep++;
148 : :
149 : : /* Next the maximum operations per instruction, in version 4 format. */
150 : 14092 : uint_fast8_t max_ops_per_instr = 1;
151 [ - + ]: 14092 : if (version >= 4)
152 : : {
153 [ # # ]: 0 : if (unlikely (lineendp - linep < 5))
154 : : goto invalid_data;
155 : 0 : max_ops_per_instr = *linep++;
156 [ # # ]: 0 : if (unlikely (max_ops_per_instr == 0))
157 : : goto invalid_data;
158 : : }
159 : :
160 : : /* Then the flag determining the default value of the is_stmt
161 : : register. */
162 : 14092 : uint_fast8_t default_is_stmt = *linep++;
163 : :
164 : : /* Now the line base. */
165 : 14092 : int_fast8_t line_base = (int8_t) *linep++;
166 : :
167 : : /* And the line range. */
168 : 14092 : uint_fast8_t line_range = *linep++;
169 : :
170 : : /* The opcode base. */
171 : 14092 : uint_fast8_t opcode_base = *linep++;
172 : :
173 : : /* Remember array with the standard opcode length (-1 to account for
174 : : the opcode with value zero not being mentioned). */
175 : 14092 : const uint8_t *standard_opcode_lengths = linep - 1;
176 [ - + ]: 14092 : if (unlikely (lineendp - linep < opcode_base - 1))
177 : : goto invalid_data;
178 : 14092 : linep += opcode_base - 1;
179 : :
180 : : /* First comes the list of directories. Add the compilation
181 : : directory first since the index zero is used for it. */
182 : : struct dirlist
183 : : {
184 : : const char *dir;
185 : : size_t len;
186 : : struct dirlist *next;
187 : 28184 : } comp_dir_elem =
188 : : {
189 : : .dir = comp_dir,
190 [ + + ]: 14092 : .len = comp_dir ? strlen (comp_dir) : 0,
191 : : .next = NULL
192 : : };
193 : 14092 : struct dirlist *dirlist = &comp_dir_elem;
194 : 14092 : unsigned int ndirlist = 1;
195 : :
196 : : // XXX Directly construct array to conserve memory?
197 [ + + ]: 101699 : while (*linep != 0)
198 : : {
199 : 87607 : struct dirlist *new_dir =
200 : : (struct dirlist *) alloca (sizeof (*new_dir));
201 : :
202 : 87607 : new_dir->dir = (char *) linep;
203 : 87607 : uint8_t *endp = memchr (linep, '\0', lineendp - linep);
204 [ - + ]: 87607 : if (endp == NULL)
205 : : goto invalid_data;
206 : 87607 : new_dir->len = endp - linep;
207 : 87607 : new_dir->next = dirlist;
208 : 87607 : dirlist = new_dir;
209 : 87607 : ++ndirlist;
210 : 87607 : linep = endp + 1;
211 : : }
212 : : /* Skip the final NUL byte. */
213 : 14092 : ++linep;
214 : :
215 : : /* Rearrange the list in array form. */
216 : 14092 : struct dirlist **dirarray
217 : 14092 : = (struct dirlist **) alloca (ndirlist * sizeof (*dirarray));
218 [ + + ]: 115791 : for (unsigned int n = ndirlist; n-- > 0; dirlist = dirlist->next)
219 : 101699 : dirarray[n] = dirlist;
220 : :
221 : : /* Now read the files. */
222 : 14092 : struct filelist null_file =
223 : : {
224 : : .info =
225 : : {
226 : : .name = "???",
227 : : .mtime = 0,
228 : : .length = 0
229 : : },
230 : : .next = NULL
231 : : };
232 : 14092 : struct filelist *filelist = &null_file;
233 : 14092 : unsigned int nfilelist = 1;
234 : :
235 [ - + ]: 14092 : if (unlikely (linep >= lineendp))
236 : : goto invalid_data;
237 [ + + ]: 216095 : while (*linep != 0)
238 : : {
239 : 202003 : struct filelist *new_file =
240 : : (struct filelist *) alloca (sizeof (*new_file));
241 : :
242 : : /* First comes the file name. */
243 : 202003 : char *fname = (char *) linep;
244 : 202003 : uint8_t *endp = memchr (fname, '\0', lineendp - linep);
245 [ - + ]: 202003 : if (endp == NULL)
246 : : goto invalid_data;
247 : 202003 : size_t fnamelen = endp - (uint8_t *) fname;
248 : 202003 : linep = endp + 1;
249 : :
250 : : /* Then the index. */
251 : : Dwarf_Word diridx;
252 [ - + ]: 202003 : get_uleb128 (diridx, linep);
253 [ - + ]: 202003 : if (unlikely (diridx >= ndirlist))
254 : : {
255 : 0 : __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
256 : : goto out;
257 : : }
258 : :
259 [ + + ]: 202003 : if (*fname == '/')
260 : : /* It's an absolute path. */
261 : 226 : new_file->info.name = fname;
262 : : else
263 : : {
264 [ + + ]: 201777 : new_file->info.name = libdw_alloc (dbg, char, 1,
265 : : dirarray[diridx]->len + 1
266 : : + fnamelen + 1);
267 : 201777 : char *cp = new_file->info.name;
268 : :
269 [ + + ]: 201777 : if (dirarray[diridx]->dir != NULL)
270 : : {
271 : : /* This value could be NULL in case the DW_AT_comp_dir
272 : : was not present. We cannot do much in this case.
273 : : The easiest thing is to convert the path in an
274 : : absolute path. */
275 : 199365 : cp = stpcpy (cp, dirarray[diridx]->dir);
276 : : }
277 : 201777 : *cp++ = '/';
278 : 201777 : strcpy (cp, fname);
279 [ - + ]: 201777 : assert (strlen (new_file->info.name)
280 : : < dirarray[diridx]->len + 1 + fnamelen + 1);
281 : : }
282 : :
283 : : /* Next comes the modification time. */
284 [ - + ]: 202003 : get_uleb128 (new_file->info.mtime, linep);
285 : :
286 : : /* Finally the length of the file. */
287 [ - + ]: 202003 : get_uleb128 (new_file->info.length, linep);
288 : :
289 : 202003 : new_file->next = filelist;
290 : 202003 : filelist = new_file;
291 : 202003 : ++nfilelist;
292 : : }
293 : : /* Skip the final NUL byte. */
294 : 14092 : ++linep;
295 : :
296 : : /* Consistency check. */
297 [ - + ]: 14092 : if (unlikely (linep != header_start + header_length))
298 : : {
299 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
300 : : goto out;
301 : : }
302 : :
303 : : /* We are about to process the statement program. Initialize the
304 : : state machine registers (see 6.2.2 in the v2.1 specification). */
305 : 14092 : Dwarf_Word addr = 0;
306 : 14092 : unsigned int op_index = 0;
307 : 14092 : unsigned int file = 1;
308 : 14092 : int line = 1;
309 : 14092 : unsigned int column = 0;
310 : 14092 : uint_fast8_t is_stmt = default_is_stmt;
311 : 14092 : bool basic_block = false;
312 : 14092 : bool prologue_end = false;
313 : 14092 : bool epilogue_begin = false;
314 : 14092 : unsigned int isa = 0;
315 : 14092 : unsigned int discriminator = 0;
316 : :
317 : : /* Apply the "operation advance" from a special opcode
318 : : or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
319 : : inline void advance_pc (unsigned int op_advance)
320 : : {
321 : 2953372 : addr += minimum_instr_len * ((op_index + op_advance)
322 : 1476686 : / max_ops_per_instr);
323 : 362105 : op_index = (op_index + op_advance) % max_ops_per_instr;
324 : : }
325 : :
326 : : /* Process the instructions. */
327 : 14092 : struct linelist *linelist = NULL;
328 : 14092 : unsigned int nlinelist = 0;
329 : :
330 : : /* Adds a new line to the matrix.
331 : : We cannot simply define a function because we want to use alloca. */
332 : : #define NEW_LINE(end_seq) \
333 : : do { \
334 : : if (unlikely (add_new_line (alloca (sizeof (struct linelist)), \
335 : : end_seq))) \
336 : : goto invalid_data; \
337 : : } while (0)
338 : :
339 : 1219355 : inline bool add_new_line (struct linelist *new_line, bool end_sequence)
340 : : {
341 : : /* Set the line information. For some fields we use bitfields,
342 : : so we would lose information if the encoded values are too large.
343 : : Check just for paranoia, and call the data "invalid" if it
344 : : violates our assumptions on reasonable limits for the values. */
345 : : #define SET(field) \
346 : : do { \
347 : : new_line->line.field = field; \
348 : : if (unlikely (new_line->line.field != field)) \
349 : : return true; \
350 : : } while (0)
351 : :
352 [ + - ]: 1219355 : SET (addr);
353 [ + - ]: 1219355 : SET (op_index);
354 [ + - ]: 1219355 : SET (file);
355 [ + - ]: 1219355 : SET (line);
356 [ + - ]: 1219355 : SET (column);
357 [ + - ]: 1219355 : SET (is_stmt);
358 [ + - ]: 1219355 : SET (basic_block);
359 [ + - ]: 1219355 : SET (end_sequence);
360 [ + - ]: 1219355 : SET (prologue_end);
361 [ + - ]: 1219355 : SET (epilogue_begin);
362 [ + - ]: 1219355 : SET (isa);
363 [ + - ]: 1219355 : SET (discriminator);
364 : :
365 : : #undef SET
366 : :
367 : 1219355 : new_line->next = linelist;
368 : 1219355 : linelist = new_line;
369 : 1219355 : ++nlinelist;
370 : :
371 : 1219355 : return false;
372 : : }
373 : :
374 [ + + ]: 2240801 : while (linep < lineendp)
375 : : {
376 : : unsigned int opcode;
377 : : unsigned int u128;
378 : : int s128;
379 : :
380 : : /* Read the opcode. */
381 : 2226709 : opcode = *linep++;
382 : :
383 : : /* Is this a special opcode? */
384 [ + + ]: 2226709 : if (likely (opcode >= opcode_base))
385 : : {
386 : : /* Yes. Handling this is quite easy since the opcode value
387 : : is computed with
388 : :
389 : : opcode = (desired line increment - line_base)
390 : : + (line_range * address advance) + opcode_base
391 : : */
392 : 1114581 : int line_increment = (line_base
393 : 1114581 : + (opcode - opcode_base) % line_range);
394 : :
395 : : /* Perform the increments. */
396 : 1114581 : line += line_increment;
397 : 1114581 : advance_pc ((opcode - opcode_base) / line_range);
398 : :
399 : : /* Add a new line with the current state machine values. */
400 [ - + ]: 1114581 : NEW_LINE (0);
401 : :
402 : : /* Reset the flags. */
403 : 1114581 : basic_block = false;
404 : 1114581 : prologue_end = false;
405 : 1114581 : epilogue_begin = false;
406 : 1114581 : discriminator = 0;
407 : : }
408 [ + + ]: 1112128 : else if (opcode == 0)
409 : : {
410 : : /* This an extended opcode. */
411 [ - + ]: 173594 : if (unlikely (lineendp - linep < 2))
412 : : goto invalid_data;
413 : :
414 : : /* The length. */
415 : 173594 : uint_fast8_t len = *linep++;
416 : :
417 [ - + ]: 173594 : if (unlikely ((size_t) (lineendp - linep) < len))
418 : : goto invalid_data;
419 : :
420 : : /* The sub-opcode. */
421 : 173594 : opcode = *linep++;
422 : :
423 [ + + - + : 173594 : switch (opcode)
- ]
424 : : {
425 : : case DW_LNE_end_sequence:
426 : : /* Add a new line with the current state machine values.
427 : : The is the end of the sequence. */
428 [ - + ]: 23878 : NEW_LINE (1);
429 : :
430 : : /* Reset the registers. */
431 : 23878 : addr = 0;
432 : 23878 : op_index = 0;
433 : 23878 : file = 1;
434 : 23878 : line = 1;
435 : 23878 : column = 0;
436 : 23878 : is_stmt = default_is_stmt;
437 : 23878 : basic_block = false;
438 : 23878 : prologue_end = false;
439 : 23878 : epilogue_begin = false;
440 : 23878 : isa = 0;
441 : 23878 : discriminator = 0;
442 : 23878 : break;
443 : :
444 : : case DW_LNE_set_address:
445 : : /* The value is an address. The size is defined as
446 : : apporiate for the target machine. We use the
447 : : address size field from the CU header. */
448 : 24001 : op_index = 0;
449 [ - + ]: 24001 : if (unlikely (lineendp - linep < cu->address_size))
450 : : goto invalid_data;
451 [ + - ]: 24001 : if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
452 : : cu->address_size, &addr))
453 : : goto out;
454 : : break;
455 : :
456 : : case DW_LNE_define_file:
457 : : {
458 : 0 : char *fname = (char *) linep;
459 : 0 : uint8_t *endp = memchr (linep, '\0', lineendp - linep);
460 [ # # ]: 0 : if (endp == NULL)
461 : : goto invalid_data;
462 : 0 : size_t fnamelen = endp - linep;
463 : 0 : linep = endp + 1;
464 : :
465 : : unsigned int diridx;
466 [ # # ]: 0 : get_uleb128 (diridx, linep);
467 : : Dwarf_Word mtime;
468 [ # # ]: 0 : get_uleb128 (mtime, linep);
469 : : Dwarf_Word filelength;
470 [ # # ]: 0 : get_uleb128 (filelength, linep);
471 : :
472 : 0 : struct filelist *new_file =
473 : : (struct filelist *) alloca (sizeof (*new_file));
474 [ # # ]: 0 : if (fname[0] == '/')
475 : 0 : new_file->info.name = fname;
476 : : else
477 : : {
478 : 0 : new_file->info.name =
479 [ # # ]: 0 : libdw_alloc (dbg, char, 1, (dirarray[diridx]->len + 1
480 : : + fnamelen + 1));
481 : 0 : char *cp = new_file->info.name;
482 : :
483 [ # # ]: 0 : if (dirarray[diridx]->dir != NULL)
484 : : /* This value could be NULL in case the
485 : : DW_AT_comp_dir was not present. We
486 : : cannot do much in this case. The easiest
487 : : thing is to convert the path in an
488 : : absolute path. */
489 : 0 : cp = stpcpy (cp, dirarray[diridx]->dir);
490 : 0 : *cp++ = '/';
491 : 0 : strcpy (cp, fname);
492 : : }
493 : :
494 : 0 : new_file->info.mtime = mtime;
495 : 0 : new_file->info.length = filelength;
496 : 0 : new_file->next = filelist;
497 : 0 : filelist = new_file;
498 : 0 : ++nfilelist;
499 : : }
500 : 0 : break;
501 : :
502 : : case DW_LNE_set_discriminator:
503 : : /* Takes one ULEB128 parameter, the discriminator. */
504 [ - + ]: 125715 : if (unlikely (standard_opcode_lengths[opcode] != 1))
505 : : goto invalid_data;
506 : :
507 [ - + ]: 125715 : get_uleb128 (discriminator, linep);
508 : : break;
509 : :
510 : : default:
511 : : /* Unknown, ignore it. */
512 [ # # ]: 0 : if (unlikely ((size_t) (lineendp - (linep - 1)) < len))
513 : : goto invalid_data;
514 : 0 : linep += len - 1;
515 : 0 : break;
516 : : }
517 : : }
518 [ + - ]: 938534 : else if (opcode <= DW_LNS_set_isa)
519 : : {
520 : : /* This is a known standard opcode. */
521 [ + + + + : 938534 : switch (opcode)
- + - + -
- - - - ]
522 : : {
523 : : case DW_LNS_copy:
524 : : /* Takes no argument. */
525 [ - + ]: 80896 : if (unlikely (standard_opcode_lengths[opcode] != 0))
526 : : goto invalid_data;
527 : :
528 : : /* Add a new line with the current state machine values. */
529 [ - + ]: 80896 : NEW_LINE (0);
530 : :
531 : : /* Reset the flags. */
532 : 80896 : basic_block = false;
533 : 80896 : prologue_end = false;
534 : 80896 : epilogue_begin = false;
535 : 80896 : discriminator = 0;
536 : 80896 : break;
537 : :
538 : : case DW_LNS_advance_pc:
539 : : /* Takes one uleb128 parameter which is added to the
540 : : address. */
541 [ - + ]: 124669 : if (unlikely (standard_opcode_lengths[opcode] != 1))
542 : : goto invalid_data;
543 : :
544 [ + + ]: 124669 : get_uleb128 (u128, linep);
545 : : advance_pc (u128);
546 : : break;
547 : :
548 : : case DW_LNS_advance_line:
549 : : /* Takes one sleb128 parameter which is added to the
550 : : line. */
551 [ - + ]: 383274 : if (unlikely (standard_opcode_lengths[opcode] != 1))
552 : : goto invalid_data;
553 : :
554 [ + + ]: 383274 : get_sleb128 (s128, linep);
555 : 383274 : line += s128;
556 : 383274 : break;
557 : :
558 : : case DW_LNS_set_file:
559 : : /* Takes one uleb128 parameter which is stored in file. */
560 [ - + ]: 51333 : if (unlikely (standard_opcode_lengths[opcode] != 1))
561 : : goto invalid_data;
562 : :
563 [ - + ]: 51333 : get_uleb128 (u128, linep);
564 : 51333 : file = u128;
565 : 51333 : break;
566 : :
567 : : case DW_LNS_set_column:
568 : : /* Takes one uleb128 parameter which is stored in column. */
569 [ # # ]: 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
570 : : goto invalid_data;
571 : :
572 [ # # ]: 0 : get_uleb128 (u128, linep);
573 : 0 : column = u128;
574 : 0 : break;
575 : :
576 : : case DW_LNS_negate_stmt:
577 : : /* Takes no argument. */
578 [ - + ]: 60926 : if (unlikely (standard_opcode_lengths[opcode] != 0))
579 : : goto invalid_data;
580 : :
581 : 60926 : is_stmt = 1 - is_stmt;
582 : 60926 : break;
583 : :
584 : : case DW_LNS_set_basic_block:
585 : : /* Takes no argument. */
586 [ # # ]: 0 : if (unlikely (standard_opcode_lengths[opcode] != 0))
587 : : goto invalid_data;
588 : :
589 : 0 : basic_block = true;
590 : 0 : break;
591 : :
592 : : case DW_LNS_const_add_pc:
593 : : /* Takes no argument. */
594 [ - + ]: 237436 : if (unlikely (standard_opcode_lengths[opcode] != 0))
595 : : goto invalid_data;
596 : :
597 : 237436 : advance_pc ((255 - opcode_base) / line_range);
598 : : break;
599 : :
600 : : case DW_LNS_fixed_advance_pc:
601 : : /* Takes one 16 bit parameter which is added to the
602 : : address. */
603 [ # # ]: 0 : if (unlikely (standard_opcode_lengths[opcode] != 1)
604 [ # # ]: 0 : || unlikely (lineendp - linep < 2))
605 : : goto invalid_data;
606 : :
607 [ # # ][ # # ]: 0 : addr += read_2ubyte_unaligned_inc (dbg, linep);
608 : 0 : op_index = 0;
609 : 0 : break;
610 : :
611 : : case DW_LNS_set_prologue_end:
612 : : /* Takes no argument. */
613 [ # # ]: 0 : if (unlikely (standard_opcode_lengths[opcode] != 0))
614 : : goto invalid_data;
615 : :
616 : 0 : prologue_end = true;
617 : 0 : break;
618 : :
619 : : case DW_LNS_set_epilogue_begin:
620 : : /* Takes no argument. */
621 [ # # ]: 0 : if (unlikely (standard_opcode_lengths[opcode] != 0))
622 : : goto invalid_data;
623 : :
624 : 0 : epilogue_begin = true;
625 : 0 : break;
626 : :
627 : : case DW_LNS_set_isa:
628 : : /* Takes one uleb128 parameter which is stored in isa. */
629 [ # # ]: 0 : if (unlikely (standard_opcode_lengths[opcode] != 1))
630 : : goto invalid_data;
631 : :
632 [ # # ]: 0 : get_uleb128 (isa, linep);
633 : : break;
634 : : }
635 : : }
636 : : else
637 : : {
638 : : /* This is a new opcode the generator but not we know about.
639 : : Read the parameters associated with it but then discard
640 : : everything. Read all the parameters for this opcode. */
641 [ # # ]: 0 : for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
642 [ # # ]: 0 : get_uleb128 (u128, linep);
643 : :
644 : : /* Next round, ignore this opcode. */
645 : 2226709 : continue;
646 : : }
647 : : }
648 : :
649 : : /* Put all the files in an array. */
650 [ + + ]: 14092 : Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
651 : : sizeof (Dwarf_Files)
652 : : + nfilelist * sizeof (Dwarf_Fileinfo)
653 : : + (ndirlist + 1) * sizeof (char *),
654 : : 1);
655 : 14092 : const char **dirs = (void *) &files->info[nfilelist];
656 : :
657 : 14092 : files->nfiles = nfilelist;
658 [ + + ]: 230187 : while (nfilelist-- > 0)
659 : : {
660 : 216095 : files->info[nfilelist] = filelist->info;
661 : 216095 : filelist = filelist->next;
662 : : }
663 [ - + ]: 14092 : assert (filelist == NULL);
664 : :
665 : : /* Put all the directory strings in an array. */
666 : 14092 : files->ndirs = ndirlist;
667 [ + + ]: 115791 : for (unsigned int i = 0; i < ndirlist; ++i)
668 : 101699 : dirs[i] = dirarray[i]->dir;
669 : 14092 : dirs[ndirlist] = NULL;
670 : :
671 : : /* Remember the referring CU. */
672 : 14092 : files->cu = cu;
673 : :
674 : : /* Make the file data structure available through the CU. */
675 : 14092 : cu->files = files;
676 : :
677 [ + + ]: 14092 : void *buf = libdw_alloc (dbg, Dwarf_Lines, (sizeof (Dwarf_Lines)
678 : : + (sizeof (Dwarf_Line)
679 : : * nlinelist)), 1);
680 : :
681 : : /* First use the buffer for the pointers, and sort the entries.
682 : : We'll write the pointers in the end of the buffer, and then
683 : : copy into the buffer from the beginning so the overlap works. */
684 : : assert (sizeof (Dwarf_Line) >= sizeof (Dwarf_Line *));
685 : 14092 : Dwarf_Line **sortlines = (buf + sizeof (Dwarf_Lines)
686 : 28184 : + ((sizeof (Dwarf_Line)
687 : 14092 : - sizeof (Dwarf_Line *)) * nlinelist));
688 : :
689 : : /* The list is in LIFO order and usually they come in clumps with
690 : : ascending addresses. So fill from the back to probably start with
691 : : runs already in order before we sort. */
692 : 14092 : unsigned int i = nlinelist;
693 [ + + ]: 1233447 : while (i-- > 0)
694 : : {
695 : 1219355 : sortlines[i] = &linelist->line;
696 : 1219355 : linelist = linelist->next;
697 : : }
698 [ - + ]: 14092 : assert (linelist == NULL);
699 : :
700 : : /* Sort by ascending address. */
701 : 14092 : qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines);
702 : :
703 : : /* Now that they are sorted, put them in the final array.
704 : : The buffers overlap, so we've clobbered the early elements
705 : : of SORTLINES by the time we're reading the later ones. */
706 : 14092 : cu->lines = buf;
707 : 14092 : cu->lines->nlines = nlinelist;
708 [ + + ]: 1233447 : for (i = 0; i < nlinelist; ++i)
709 : : {
710 : 1219355 : cu->lines->info[i] = *sortlines[i];
711 : 1219355 : cu->lines->info[i].files = files;
712 : : }
713 : :
714 : : /* Success. */
715 : 14092 : res = 0;
716 : : }
717 [ + - ]: 20 : else if (cu->lines != (void *) -1l)
718 : : /* We already have the information. */
719 : 20 : res = 0;
720 : :
721 [ + - ]: 14112 : if (likely (res == 0))
722 : : {
723 : 14112 : *lines = cu->lines;
724 : 14112 : *nlines = cu->lines->nlines;
725 : : }
726 : : out:
727 : :
728 : : // XXX Eventually: unlocking here.
729 : :
730 : 14112 : return res;
731 : : }
732 : : INTDEF(dwarf_getsrclines)
|