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