1 /* Return line number information of CU. 2 Copyright (C) 2004-2010, 2013, 2014 Red Hat, Inc. 3 This file is part of elfutils. 4 Written by Ulrich Drepper <drepper (at) 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 <search.h> 38 39 #include "dwarf.h" 40 #include "libdwP.h" 41 42 43 struct filelist 44 { 45 Dwarf_Fileinfo info; 46 struct filelist *next; 47 }; 48 49 struct linelist 50 { 51 Dwarf_Line line; 52 struct linelist *next; 53 size_t sequence; 54 }; 55 56 57 /* Compare by Dwarf_Line.addr, given pointers into an array of pointers. */ 58 static int 59 compare_lines (const void *a, const void *b) 60 { 61 struct linelist *const *p1 = a; 62 struct linelist *const *p2 = b; 63 struct linelist *list1 = *p1; 64 struct linelist *list2 = *p2; 65 Dwarf_Line *line1 = &list1->line; 66 Dwarf_Line *line2 = &list2->line; 67 68 if (line1->addr != line2->addr) 69 return (line1->addr < line2->addr) ? -1 : 1; 70 71 /* An end_sequence marker precedes a normal record at the same address. */ 72 if (line1->end_sequence != line2->end_sequence) 73 return line2->end_sequence - line1->end_sequence; 74 75 /* Otherwise, the linelist sequence maintains a stable sort. */ 76 return (list1->sequence < list2->sequence) ? -1 77 : (list1->sequence > list2->sequence) ? 1 78 : 0; 79 } 80 81 static int 82 read_srclines (Dwarf *dbg, 83 const unsigned char *linep, const unsigned char *lineendp, 84 const char *comp_dir, unsigned address_size, 85 Dwarf_Lines **linesp, Dwarf_Files **filesp) 86 { 87 int res = -1; 88 89 struct linelist *linelist = NULL; 90 size_t nlinelist = 0; 91 92 /* If there are a large number of lines don't blow up the stack. 93 Keep track of the last malloced linelist record and free them 94 through the next pointer at the end. */ 95 #define MAX_STACK_ALLOC 4096 96 struct linelist *malloc_linelist = NULL; 97 98 if (unlikely (linep + 4 > lineendp)) 99 { 100 invalid_data: 101 __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE); 102 goto out; 103 } 104 105 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); 106 unsigned int length = 4; 107 if (unlikely (unit_length == DWARF3_LENGTH_64_BIT)) 108 { 109 if (unlikely (linep + 8 > lineendp)) 110 goto invalid_data; 111 unit_length = read_8ubyte_unaligned_inc (dbg, linep); 112 length = 8; 113 } 114 115 /* Check whether we have enough room in the section. */ 116 if (unlikely (unit_length > (size_t) (lineendp - linep) 117 || unit_length < 2 + length + 5 * 1)) 118 goto invalid_data; 119 lineendp = linep + unit_length; 120 121 /* The next element of the header is the version identifier. */ 122 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); 123 if (unlikely (version < 2) || unlikely (version > 4)) 124 { 125 __libdw_seterrno (DWARF_E_VERSION); 126 goto out; 127 } 128 129 /* Next comes the header length. */ 130 Dwarf_Word header_length; 131 if (length == 4) 132 header_length = read_4ubyte_unaligned_inc (dbg, linep); 133 else 134 header_length = read_8ubyte_unaligned_inc (dbg, linep); 135 const unsigned char *header_start = linep; 136 137 /* Next the minimum instruction length. */ 138 uint_fast8_t minimum_instr_len = *linep++; 139 140 /* Next the maximum operations per instruction, in version 4 format. */ 141 uint_fast8_t max_ops_per_instr = 1; 142 if (version >= 4) 143 { 144 if (unlikely (lineendp - linep < 5)) 145 goto invalid_data; 146 max_ops_per_instr = *linep++; 147 if (unlikely (max_ops_per_instr == 0)) 148 goto invalid_data; 149 } 150 151 /* Then the flag determining the default value of the is_stmt 152 register. */ 153 uint_fast8_t default_is_stmt = *linep++; 154 155 /* Now the line base. */ 156 int_fast8_t line_base = (int8_t) *linep++; 157 158 /* And the line range. */ 159 uint_fast8_t line_range = *linep++; 160 161 /* The opcode base. */ 162 uint_fast8_t opcode_base = *linep++; 163 164 /* Remember array with the standard opcode length (-1 to account for 165 the opcode with value zero not being mentioned). */ 166 const uint8_t *standard_opcode_lengths = linep - 1; 167 if (unlikely (lineendp - linep < opcode_base - 1)) 168 goto invalid_data; 169 linep += opcode_base - 1; 170 171 /* First comes the list of directories. Add the compilation 172 directory first since the index zero is used for it. */ 173 struct dirlist 174 { 175 const char *dir; 176 size_t len; 177 struct dirlist *next; 178 } comp_dir_elem = 179 { 180 .dir = comp_dir, 181 .len = comp_dir ? strlen (comp_dir) : 0, 182 .next = NULL 183 }; 184 struct dirlist *dirlist = &comp_dir_elem; 185 unsigned int ndirlist = 1; 186 187 // XXX Directly construct array to conserve memory? 188 while (*linep != 0) 189 { 190 struct dirlist *new_dir = 191 (struct dirlist *) alloca (sizeof (*new_dir)); 192 193 new_dir->dir = (char *) linep; 194 uint8_t *endp = memchr (linep, '\0', lineendp - linep); 195 if (endp == NULL) 196 goto invalid_data; 197 new_dir->len = endp - linep; 198 new_dir->next = dirlist; 199 dirlist = new_dir; 200 ++ndirlist; 201 linep = endp + 1; 202 } 203 /* Skip the final NUL byte. */ 204 ++linep; 205 206 /* Rearrange the list in array form. */ 207 struct dirlist **dirarray 208 = (struct dirlist **) alloca (ndirlist * sizeof (*dirarray)); 209 for (unsigned int n = ndirlist; n-- > 0; dirlist = dirlist->next) 210 dirarray[n] = dirlist; 211 212 /* Now read the files. */ 213 struct filelist null_file = 214 { 215 .info = 216 { 217 .name = "???", 218 .mtime = 0, 219 .length = 0 220 }, 221 .next = NULL 222 }; 223 struct filelist *filelist = &null_file; 224 unsigned int nfilelist = 1; 225 226 if (unlikely (linep >= lineendp)) 227 goto invalid_data; 228 while (*linep != 0) 229 { 230 struct filelist *new_file = 231 (struct filelist *) alloca (sizeof (*new_file)); 232 233 /* First comes the file name. */ 234 char *fname = (char *) linep; 235 uint8_t *endp = memchr (fname, '\0', lineendp - linep); 236 if (endp == NULL) 237 goto invalid_data; 238 size_t fnamelen = endp - (uint8_t *) fname; 239 linep = endp + 1; 240 241 /* Then the index. */ 242 Dwarf_Word diridx; 243 if (unlikely (linep >= lineendp)) 244 goto invalid_data; 245 get_uleb128 (diridx, linep, lineendp); 246 if (unlikely (diridx >= ndirlist)) 247 { 248 __libdw_seterrno (DWARF_E_INVALID_DIR_IDX); 249 goto out; 250 } 251 252 if (*fname == '/') 253 /* It's an absolute path. */ 254 new_file->info.name = fname; 255 else 256 { 257 new_file->info.name = libdw_alloc (dbg, char, 1, 258 dirarray[diridx]->len + 1 259 + fnamelen + 1); 260 char *cp = new_file->info.name; 261 262 if (dirarray[diridx]->dir != NULL) 263 { 264 /* This value could be NULL in case the DW_AT_comp_dir 265 was not present. We cannot do much in this case. 266 The easiest thing is to convert the path in an 267 absolute path. */ 268 cp = stpcpy (cp, dirarray[diridx]->dir); 269 } 270 *cp++ = '/'; 271 strcpy (cp, fname); 272 assert (strlen (new_file->info.name) 273 < dirarray[diridx]->len + 1 + fnamelen + 1); 274 } 275 276 /* Next comes the modification time. */ 277 if (unlikely (linep >= lineendp)) 278 goto invalid_data; 279 get_uleb128 (new_file->info.mtime, linep, lineendp); 280 281 /* Finally the length of the file. */ 282 if (unlikely (linep >= lineendp)) 283 goto invalid_data; 284 get_uleb128 (new_file->info.length, linep, lineendp); 285 286 new_file->next = filelist; 287 filelist = new_file; 288 ++nfilelist; 289 } 290 /* Skip the final NUL byte. */ 291 ++linep; 292 293 /* Consistency check. */ 294 if (unlikely (linep != header_start + header_length)) 295 { 296 __libdw_seterrno (DWARF_E_INVALID_DWARF); 297 goto out; 298 } 299 300 /* We are about to process the statement program. Initialize the 301 state machine registers (see 6.2.2 in the v2.1 specification). */ 302 Dwarf_Word addr = 0; 303 unsigned int op_index = 0; 304 unsigned int file = 1; 305 int line = 1; 306 unsigned int column = 0; 307 uint_fast8_t is_stmt = default_is_stmt; 308 bool basic_block = false; 309 bool prologue_end = false; 310 bool epilogue_begin = false; 311 unsigned int isa = 0; 312 unsigned int discriminator = 0; 313 314 /* Apply the "operation advance" from a special opcode or 315 DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */ 316 inline void advance_pc (unsigned int op_advance) 317 { 318 addr += minimum_instr_len * ((op_index + op_advance) 319 / max_ops_per_instr); 320 op_index = (op_index + op_advance) % max_ops_per_instr; 321 } 322 323 /* Process the instructions. */ 324 325 /* Adds a new line to the matrix. 326 We cannot simply define a function because we want to use alloca. */ 327 #define NEW_LINE(end_seq) \ 328 do { \ 329 struct linelist *ll = (nlinelist < MAX_STACK_ALLOC \ 330 ? alloca (sizeof (struct linelist)) \ 331 : malloc (sizeof (struct linelist))); \ 332 if (nlinelist >= MAX_STACK_ALLOC) \ 333 malloc_linelist = ll; \ 334 if (unlikely (add_new_line (ll, end_seq))) \ 335 goto invalid_data; \ 336 } while (0) 337 338 inline bool add_new_line (struct linelist *new_line, bool end_sequence) 339 { 340 new_line->next = linelist; 341 new_line->sequence = nlinelist; 342 linelist = new_line; 343 ++nlinelist; 344 345 /* Set the line information. For some fields we use bitfields, 346 so we would lose information if the encoded values are too large. 347 Check just for paranoia, and call the data "invalid" if it 348 violates our assumptions on reasonable limits for the values. */ 349 #define SET(field) \ 350 do { \ 351 new_line->line.field = field; \ 352 if (unlikely (new_line->line.field != field)) \ 353 return true; \ 354 } while (0) 355 356 SET (addr); 357 SET (op_index); 358 SET (file); 359 SET (line); 360 SET (column); 361 SET (is_stmt); 362 SET (basic_block); 363 SET (end_sequence); 364 SET (prologue_end); 365 SET (epilogue_begin); 366 SET (isa); 367 SET (discriminator); 368 369 #undef SET 370 371 return false; 372 } 373 374 while (linep < lineendp) 375 { 376 unsigned int opcode; 377 unsigned int u128; 378 int s128; 379 380 /* Read the opcode. */ 381 opcode = *linep++; 382 383 /* Is this a special opcode? */ 384 if (likely (opcode >= opcode_base)) 385 { 386 if (unlikely (line_range == 0)) 387 goto invalid_data; 388 389 /* Yes. Handling this is quite easy since the opcode value 390 is computed with 391 392 opcode = (desired line increment - line_base) 393 + (line_range * address advance) + opcode_base 394 */ 395 int line_increment = (line_base 396 + (opcode - opcode_base) % line_range); 397 398 /* Perform the increments. */ 399 line += line_increment; 400 advance_pc ((opcode - opcode_base) / line_range); 401 402 /* Add a new line with the current state machine values. */ 403 NEW_LINE (0); 404 405 /* Reset the flags. */ 406 basic_block = false; 407 prologue_end = false; 408 epilogue_begin = false; 409 discriminator = 0; 410 } 411 else if (opcode == 0) 412 { 413 /* This an extended opcode. */ 414 if (unlikely (lineendp - linep < 2)) 415 goto invalid_data; 416 417 /* The length. */ 418 uint_fast8_t len = *linep++; 419 420 if (unlikely ((size_t) (lineendp - linep) < len)) 421 goto invalid_data; 422 423 /* The sub-opcode. */ 424 opcode = *linep++; 425 426 switch (opcode) 427 { 428 case DW_LNE_end_sequence: 429 /* Add a new line with the current state machine values. 430 The is the end of the sequence. */ 431 NEW_LINE (1); 432 433 /* Reset the registers. */ 434 addr = 0; 435 op_index = 0; 436 file = 1; 437 line = 1; 438 column = 0; 439 is_stmt = default_is_stmt; 440 basic_block = false; 441 prologue_end = false; 442 epilogue_begin = false; 443 isa = 0; 444 discriminator = 0; 445 break; 446 447 case DW_LNE_set_address: 448 /* The value is an address. The size is defined as 449 apporiate for the target machine. We use the 450 address size field from the CU header. */ 451 op_index = 0; 452 if (unlikely (lineendp - linep < (uint8_t) address_size)) 453 goto invalid_data; 454 if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep, 455 address_size, &addr)) 456 goto out; 457 break; 458 459 case DW_LNE_define_file: 460 { 461 char *fname = (char *) linep; 462 uint8_t *endp = memchr (linep, '\0', lineendp - linep); 463 if (endp == NULL) 464 goto invalid_data; 465 size_t fnamelen = endp - linep; 466 linep = endp + 1; 467 468 unsigned int diridx; 469 if (unlikely (linep >= lineendp)) 470 goto invalid_data; 471 get_uleb128 (diridx, linep, lineendp); 472 if (unlikely (diridx >= ndirlist)) 473 { 474 __libdw_seterrno (DWARF_E_INVALID_DIR_IDX); 475 goto invalid_data; 476 } 477 Dwarf_Word mtime; 478 if (unlikely (linep >= lineendp)) 479 goto invalid_data; 480 get_uleb128 (mtime, linep, lineendp); 481 Dwarf_Word filelength; 482 if (unlikely (linep >= lineendp)) 483 goto invalid_data; 484 get_uleb128 (filelength, linep, lineendp); 485 486 struct filelist *new_file = 487 (struct filelist *) alloca (sizeof (*new_file)); 488 if (fname[0] == '/') 489 new_file->info.name = fname; 490 else 491 { 492 new_file->info.name = 493 libdw_alloc (dbg, char, 1, (dirarray[diridx]->len + 1 494 + fnamelen + 1)); 495 char *cp = new_file->info.name; 496 497 if (dirarray[diridx]->dir != NULL) 498 /* This value could be NULL in case the 499 DW_AT_comp_dir was not present. We 500 cannot do much in this case. The easiest 501 thing is to convert the path in an 502 absolute path. */ 503 cp = stpcpy (cp, dirarray[diridx]->dir); 504 *cp++ = '/'; 505 strcpy (cp, fname); 506 } 507 508 new_file->info.mtime = mtime; 509 new_file->info.length = filelength; 510 new_file->next = filelist; 511 filelist = new_file; 512 ++nfilelist; 513 } 514 break; 515 516 case DW_LNE_set_discriminator: 517 /* Takes one ULEB128 parameter, the discriminator. */ 518 if (unlikely (standard_opcode_lengths[opcode] != 1)) 519 goto invalid_data; 520 521 if (unlikely (linep >= lineendp)) 522 goto invalid_data; 523 get_uleb128 (discriminator, linep, lineendp); 524 break; 525 526 default: 527 /* Unknown, ignore it. */ 528 if (unlikely ((size_t) (lineendp - (linep - 1)) < len)) 529 goto invalid_data; 530 linep += len - 1; 531 break; 532 } 533 } 534 else if (opcode <= DW_LNS_set_isa) 535 { 536 /* This is a known standard opcode. */ 537 switch (opcode) 538 { 539 case DW_LNS_copy: 540 /* Takes no argument. */ 541 if (unlikely (standard_opcode_lengths[opcode] != 0)) 542 goto invalid_data; 543 544 /* Add a new line with the current state machine values. */ 545 NEW_LINE (0); 546 547 /* Reset the flags. */ 548 basic_block = false; 549 prologue_end = false; 550 epilogue_begin = false; 551 discriminator = 0; 552 break; 553 554 case DW_LNS_advance_pc: 555 /* Takes one uleb128 parameter which is added to the 556 address. */ 557 if (unlikely (standard_opcode_lengths[opcode] != 1)) 558 goto invalid_data; 559 560 if (unlikely (linep >= lineendp)) 561 goto invalid_data; 562 get_uleb128 (u128, linep, lineendp); 563 advance_pc (u128); 564 break; 565 566 case DW_LNS_advance_line: 567 /* Takes one sleb128 parameter which is added to the 568 line. */ 569 if (unlikely (standard_opcode_lengths[opcode] != 1)) 570 goto invalid_data; 571 572 if (unlikely (linep >= lineendp)) 573 goto invalid_data; 574 get_sleb128 (s128, linep, lineendp); 575 line += s128; 576 break; 577 578 case DW_LNS_set_file: 579 /* Takes one uleb128 parameter which is stored in file. */ 580 if (unlikely (standard_opcode_lengths[opcode] != 1)) 581 goto invalid_data; 582 583 if (unlikely (linep >= lineendp)) 584 goto invalid_data; 585 get_uleb128 (u128, linep, lineendp); 586 file = u128; 587 break; 588 589 case DW_LNS_set_column: 590 /* Takes one uleb128 parameter which is stored in column. */ 591 if (unlikely (standard_opcode_lengths[opcode] != 1)) 592 goto invalid_data; 593 594 if (unlikely (linep >= lineendp)) 595 goto invalid_data; 596 get_uleb128 (u128, linep, lineendp); 597 column = u128; 598 break; 599 600 case DW_LNS_negate_stmt: 601 /* Takes no argument. */ 602 if (unlikely (standard_opcode_lengths[opcode] != 0)) 603 goto invalid_data; 604 605 is_stmt = 1 - is_stmt; 606 break; 607 608 case DW_LNS_set_basic_block: 609 /* Takes no argument. */ 610 if (unlikely (standard_opcode_lengths[opcode] != 0)) 611 goto invalid_data; 612 613 basic_block = true; 614 break; 615 616 case DW_LNS_const_add_pc: 617 /* Takes no argument. */ 618 if (unlikely (standard_opcode_lengths[opcode] != 0)) 619 goto invalid_data; 620 621 if (unlikely (line_range == 0)) 622 goto invalid_data; 623 624 advance_pc ((255 - opcode_base) / line_range); 625 break; 626 627 case DW_LNS_fixed_advance_pc: 628 /* Takes one 16 bit parameter which is added to the 629 address. */ 630 if (unlikely (standard_opcode_lengths[opcode] != 1) 631 || unlikely (lineendp - linep < 2)) 632 goto invalid_data; 633 634 addr += read_2ubyte_unaligned_inc (dbg, linep); 635 op_index = 0; 636 break; 637 638 case DW_LNS_set_prologue_end: 639 /* Takes no argument. */ 640 if (unlikely (standard_opcode_lengths[opcode] != 0)) 641 goto invalid_data; 642 643 prologue_end = true; 644 break; 645 646 case DW_LNS_set_epilogue_begin: 647 /* Takes no argument. */ 648 if (unlikely (standard_opcode_lengths[opcode] != 0)) 649 goto invalid_data; 650 651 epilogue_begin = true; 652 break; 653 654 case DW_LNS_set_isa: 655 /* Takes one uleb128 parameter which is stored in isa. */ 656 if (unlikely (standard_opcode_lengths[opcode] != 1)) 657 goto invalid_data; 658 659 if (unlikely (linep >= lineendp)) 660 goto invalid_data; 661 get_uleb128 (isa, linep, lineendp); 662 break; 663 } 664 } 665 else 666 { 667 /* This is a new opcode the generator but not we know about. 668 Read the parameters associated with it but then discard 669 everything. Read all the parameters for this opcode. */ 670 for (int n = standard_opcode_lengths[opcode]; n > 0; --n) 671 { 672 if (unlikely (linep >= lineendp)) 673 goto invalid_data; 674 get_uleb128 (u128, linep, lineendp); 675 } 676 677 /* Next round, ignore this opcode. */ 678 continue; 679 } 680 } 681 682 /* Put all the files in an array. */ 683 Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files, 684 sizeof (Dwarf_Files) 685 + nfilelist * sizeof (Dwarf_Fileinfo) 686 + (ndirlist + 1) * sizeof (char *), 687 1); 688 const char **dirs = (void *) &files->info[nfilelist]; 689 690 files->nfiles = nfilelist; 691 while (nfilelist-- > 0) 692 { 693 files->info[nfilelist] = filelist->info; 694 filelist = filelist->next; 695 } 696 assert (filelist == NULL); 697 698 /* Put all the directory strings in an array. */ 699 files->ndirs = ndirlist; 700 for (unsigned int i = 0; i < ndirlist; ++i) 701 dirs[i] = dirarray[i]->dir; 702 dirs[ndirlist] = NULL; 703 704 /* Pass the file data structure to the caller. */ 705 if (filesp != NULL) 706 *filesp = files; 707 708 size_t buf_size = (sizeof (Dwarf_Lines) + (sizeof (Dwarf_Line) * nlinelist)); 709 void *buf = libdw_alloc (dbg, Dwarf_Lines, buf_size, 1); 710 711 /* First use the buffer for the pointers, and sort the entries. 712 We'll write the pointers in the end of the buffer, and then 713 copy into the buffer from the beginning so the overlap works. */ 714 assert (sizeof (Dwarf_Line) >= sizeof (struct linelist *)); 715 struct linelist **sortlines = (buf + buf_size 716 - sizeof (struct linelist **) * nlinelist); 717 718 /* The list is in LIFO order and usually they come in clumps with 719 ascending addresses. So fill from the back to probably start with 720 runs already in order before we sort. */ 721 for (size_t i = nlinelist; i-- > 0; ) 722 { 723 sortlines[i] = linelist; 724 linelist = linelist->next; 725 } 726 assert (linelist == NULL); 727 728 /* Sort by ascending address. */ 729 qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines); 730 731 /* Now that they are sorted, put them in the final array. 732 The buffers overlap, so we've clobbered the early elements 733 of SORTLINES by the time we're reading the later ones. */ 734 Dwarf_Lines *lines = buf; 735 lines->nlines = nlinelist; 736 for (size_t i = 0; i < nlinelist; ++i) 737 { 738 lines->info[i] = sortlines[i]->line; 739 lines->info[i].files = files; 740 } 741 742 /* Make sure the highest address for the CU is marked as end_sequence. 743 This is required by the DWARF spec, but some compilers forget and 744 dwfl_module_getsrc depends on it. */ 745 if (nlinelist > 0) 746 lines->info[nlinelist - 1].end_sequence = 1; 747 748 /* Pass the line structure back to the caller. */ 749 if (linesp != NULL) 750 *linesp = lines; 751 752 /* Success. */ 753 res = 0; 754 755 out: 756 /* Free malloced line records, if any. */ 757 for (size_t i = MAX_STACK_ALLOC; i < nlinelist; i++) 758 { 759 struct linelist *ll = malloc_linelist->next; 760 free (malloc_linelist); 761 malloc_linelist = ll; 762 } 763 764 return res; 765 } 766 767 static int 768 files_lines_compare (const void *p1, const void *p2) 769 { 770 const struct files_lines_s *t1 = p1; 771 const struct files_lines_s *t2 = p2; 772 773 if (t1->debug_line_offset < t2->debug_line_offset) 774 return -1; 775 if (t1->debug_line_offset > t2->debug_line_offset) 776 return 1; 777 778 return 0; 779 } 780 781 int 782 internal_function 783 __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset, 784 const char *comp_dir, unsigned address_size, 785 Dwarf_Lines **linesp, Dwarf_Files **filesp) 786 { 787 struct files_lines_s fake = { .debug_line_offset = debug_line_offset }; 788 struct files_lines_s **found = tfind (&fake, &dbg->files_lines, 789 files_lines_compare); 790 if (found == NULL) 791 { 792 Elf_Data *data = __libdw_checked_get_data (dbg, IDX_debug_line); 793 if (data == NULL 794 || __libdw_offset_in_section (dbg, IDX_debug_line, 795 debug_line_offset, 1) != 0) 796 return -1; 797 798 const unsigned char *linep = data->d_buf + debug_line_offset; 799 const unsigned char *lineendp = data->d_buf + data->d_size; 800 801 struct files_lines_s *node = libdw_alloc (dbg, struct files_lines_s, 802 sizeof *node, 1); 803 804 if (read_srclines (dbg, linep, lineendp, comp_dir, address_size, 805 &node->lines, &node->files) != 0) 806 return -1; 807 808 node->debug_line_offset = debug_line_offset; 809 810 found = tsearch (node, &dbg->files_lines, files_lines_compare); 811 if (found == NULL) 812 { 813 __libdw_seterrno (DWARF_E_NOMEM); 814 return -1; 815 } 816 } 817 818 if (linesp != NULL) 819 *linesp = (*found)->lines; 820 821 if (filesp != NULL) 822 *filesp = (*found)->files; 823 824 return 0; 825 } 826 827 /* Get the compilation directory, if any is set. */ 828 const char * 829 __libdw_getcompdir (Dwarf_Die *cudie) 830 { 831 Dwarf_Attribute compdir_attr_mem; 832 Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie, 833 DW_AT_comp_dir, 834 &compdir_attr_mem); 835 return INTUSE(dwarf_formstring) (compdir_attr); 836 } 837 838 int 839 dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) 840 { 841 if (unlikely (cudie == NULL 842 || (INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit 843 && INTUSE(dwarf_tag) (cudie) != DW_TAG_partial_unit))) 844 return -1; 845 846 /* Get the information if it is not already known. */ 847 struct Dwarf_CU *const cu = cudie->cu; 848 if (cu->lines == NULL) 849 { 850 /* Failsafe mode: no data found. */ 851 cu->lines = (void *) -1l; 852 cu->files = (void *) -1l; 853 854 /* The die must have a statement list associated. */ 855 Dwarf_Attribute stmt_list_mem; 856 Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, 857 &stmt_list_mem); 858 859 /* Get the offset into the .debug_line section. NB: this call 860 also checks whether the previous dwarf_attr call failed. */ 861 Dwarf_Off debug_line_offset; 862 if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE, 863 NULL, &debug_line_offset) == NULL) 864 return -1; 865 866 if (__libdw_getsrclines (cu->dbg, debug_line_offset, 867 __libdw_getcompdir (cudie), 868 cu->address_size, &cu->lines, &cu->files) < 0) 869 return -1; 870 } 871 else if (cu->lines == (void *) -1l) 872 return -1; 873 874 *lines = cu->lines; 875 *nlines = cu->lines->nlines; 876 877 // XXX Eventually: unlocking here. 878 879 return 0; 880 } 881 INTDEF(dwarf_getsrclines) 882