1 /* 2 3 Copyright (C) 2000,2002,2004,2005,2006 Silicon Graphics, Inc. All Rights Reserved. 4 Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. 5 6 This program is free software; you can redistribute it and/or modify it 7 under the terms of version 2.1 of the GNU Lesser General Public License 8 as published by the Free Software Foundation. 9 10 This program is distributed in the hope that it would be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 14 Further, this software is distributed without any warranty that it is 15 free of the rightful claim of any third person regarding infringement 16 or the like. Any license provided herein, whether implied or 17 otherwise, applies only to this software file. Patent licenses, if 18 any, provided herein do not apply to combinations of this program with 19 other software, or any other product whatsoever. 20 21 You should have received a copy of the GNU Lesser General Public 22 License along with this program; if not, write the Free Software 23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, 24 USA. 25 26 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, 27 Mountain View, CA 94043, or: 28 29 http://www.sgi.com 30 31 For further information regarding this notice, see: 32 33 http://oss.sgi.com/projects/GenInfo/NoticeExplan 34 35 */ 36 /* The address of the Free Software Foundation is 37 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 38 Boston, MA 02110-1301, USA. 39 SGI has moved from the Crittenden Lane address. 40 */ 41 42 43 44 45 #include "config.h" 46 #include "dwarf_incl.h" 47 #include <stdio.h> 48 #include <time.h> 49 #include "dwarf_line.h" 50 51 /* FIXME Need to add prologue_end epilogue_begin isa fields. */ 52 static void 53 print_line_header(void) 54 { 55 printf 56 (" s b e\n" 57 " t l s\n" 58 " m c e\n" 59 " section op col t k q\n" 60 " offset code address file line umn ? ? ?\n"); 61 } 62 63 /* FIXME: print new line values: prologue_end epilogue_begin isa */ 64 static void 65 print_line_detail(char *prefix, 66 int opcode, 67 Dwarf_Unsigned address, 68 unsigned long file, 69 unsigned long line, 70 unsigned long column, 71 int is_stmt, int basic_block, int end_sequence, 72 int prologue_end, int epilogue_begin, int isa) 73 { 74 printf("%-15s %2d 0x%08" DW_PR_DUx " " 75 "%2lu %4lu %2lu %1d %1d %1d\n", 76 prefix, 77 (int) opcode, 78 (Dwarf_Unsigned) address, 79 (unsigned long) file, 80 (unsigned long) line, 81 (unsigned long) column, 82 (int) is_stmt, (int) basic_block, (int) end_sequence); 83 84 } 85 86 87 /* 88 return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR 89 If err_count_out is non-NULL, this is a special 'check' 90 call. 91 */ 92 int 93 _dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error, 94 int * err_count_out, int only_line_header) 95 { 96 /* 97 This pointer is used to scan the portion of the .debug_line 98 section for the current cu. */ 99 Dwarf_Small *line_ptr = 0; 100 Dwarf_Small *orig_line_ptr = 0; 101 102 /* 103 This points to the last byte of the .debug_line portion for the 104 current cu. */ 105 Dwarf_Small *line_ptr_end = 0; 106 107 /* 108 Pointer to a DW_AT_stmt_list attribute in case it exists in the 109 die. */ 110 Dwarf_Attribute stmt_list_attr = 0; 111 112 /* Pointer to DW_AT_comp_dir attribute in die. */ 113 Dwarf_Attribute comp_dir_attr = 0; 114 115 /* Pointer to name of compilation directory. */ 116 Dwarf_Small *comp_dir = NULL; 117 118 /* 119 Offset into .debug_line specified by a DW_AT_stmt_list 120 attribute. */ 121 Dwarf_Unsigned line_offset = 0; 122 123 struct Line_Table_Prefix_s prefix; 124 125 126 /* These are the state machine state variables. */ 127 Dwarf_Addr address = 0; 128 Dwarf_Word file = 1; 129 Dwarf_Word line = 1; 130 Dwarf_Word column = 0; 131 Dwarf_Bool is_stmt = false; 132 Dwarf_Bool basic_block = false; 133 Dwarf_Bool end_sequence = false; 134 Dwarf_Bool prologue_end = false; 135 Dwarf_Bool epilogue_begin = false; 136 Dwarf_Small isa = 0; 137 138 139 Dwarf_Sword i=0; 140 141 /* 142 This is the current opcode read from the statement program. */ 143 Dwarf_Small opcode=0; 144 145 146 /* 147 These variables are used to decode leb128 numbers. Leb128_num 148 holds the decoded number, and leb128_length is its length in 149 bytes. */ 150 Dwarf_Word leb128_num=0; 151 Dwarf_Word leb128_length=0; 152 Dwarf_Sword advance_line=0; 153 Dwarf_Half attrform = 0; 154 /* 155 This is the operand of the latest fixed_advance_pc extended 156 opcode. */ 157 Dwarf_Half fixed_advance_pc=0; 158 159 /* In case there are wierd bytes 'after' the line table 160 * prologue this lets us print something. This is a gcc 161 * compiler bug and we expect the bytes count to be 12. 162 */ 163 Dwarf_Small* bogus_bytes_ptr = 0; 164 Dwarf_Unsigned bogus_bytes_count = 0; 165 166 167 /* The Dwarf_Debug this die belongs to. */ 168 Dwarf_Debug dbg=0; 169 int resattr = DW_DLV_ERROR; 170 int lres = DW_DLV_ERROR; 171 int res = DW_DLV_ERROR; 172 173 /* ***** BEGIN CODE ***** */ 174 175 if (error != NULL) { 176 *error = NULL; 177 } 178 179 CHECK_DIE(die, DW_DLV_ERROR); 180 dbg = die->di_cu_context->cc_dbg; 181 182 res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); 183 if (res != DW_DLV_OK) { 184 return res; 185 } 186 187 resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); 188 if (resattr != DW_DLV_OK) { 189 return resattr; 190 } 191 192 193 /* The list of relevant FORMs is small. 194 DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset 195 */ 196 lres = dwarf_whatform(stmt_list_attr,&attrform,error); 197 if (lres != DW_DLV_OK) { 198 return lres; 199 } 200 if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && 201 attrform != DW_FORM_sec_offset ) { 202 _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); 203 return (DW_DLV_ERROR); 204 } 205 lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); 206 if (lres != DW_DLV_OK) { 207 return lres; 208 } 209 210 if (line_offset >= dbg->de_debug_line.dss_size) { 211 _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); 212 return (DW_DLV_ERROR); 213 } 214 orig_line_ptr = dbg->de_debug_line.dss_data; 215 line_ptr = dbg->de_debug_line.dss_data + line_offset; 216 dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); 217 218 /* 219 If die has DW_AT_comp_dir attribute, get the string that names 220 the compilation directory. */ 221 resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); 222 if (resattr == DW_DLV_ERROR) { 223 return resattr; 224 } 225 if (resattr == DW_DLV_OK) { 226 int cres = DW_DLV_ERROR; 227 char *cdir = 0; 228 229 cres = dwarf_formstring(comp_dir_attr, &cdir, error); 230 if (cres == DW_DLV_ERROR) { 231 return cres; 232 } else if (cres == DW_DLV_OK) { 233 comp_dir = (Dwarf_Small *) cdir; 234 } 235 } 236 if (resattr == DW_DLV_OK) { 237 dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); 238 } 239 240 dwarf_init_line_table_prefix(&prefix); 241 { 242 Dwarf_Small *line_ptr_out = 0; 243 int dres = dwarf_read_line_table_prefix(dbg, 244 line_ptr,dbg->de_debug_line.dss_size - line_offset, 245 &line_ptr_out, 246 &prefix, 247 &bogus_bytes_ptr, 248 &bogus_bytes_count, 249 error, 250 err_count_out); 251 if (dres == DW_DLV_ERROR) { 252 dwarf_free_line_table_prefix(&prefix); 253 return dres; 254 } 255 if (dres == DW_DLV_NO_ENTRY) { 256 dwarf_free_line_table_prefix(&prefix); 257 return dres; 258 } 259 line_ptr_end = prefix.pf_line_ptr_end; 260 line_ptr = line_ptr_out; 261 } 262 if(only_line_header) { 263 /* Just checking for header errors, nothing more here.*/ 264 dwarf_free_line_table_prefix(&prefix); 265 return DW_DLV_OK; 266 } 267 268 269 printf("total line info length %ld bytes, " 270 "line offset 0x%" DW_PR_DUx " %" DW_PR_DSd "\n", 271 (long) prefix.pf_total_length, 272 (Dwarf_Unsigned) line_offset, 273 (Dwarf_Signed) line_offset); 274 printf("line table version %d\n",(int) prefix.pf_version); 275 printf("line table length field length %d prologue length %d\n", 276 (int)prefix.pf_length_field_length, 277 (int)prefix.pf_prologue_length); 278 printf("compilation_directory %s\n", 279 comp_dir ? ((char *) comp_dir) : ""); 280 281 printf(" min instruction length %d\n", 282 (int) prefix.pf_minimum_instruction_length); 283 printf(" default is stmt %d\n", (int) 284 prefix.pf_default_is_stmt); 285 printf(" line base %d\n", (int) 286 prefix.pf_line_base); 287 printf(" line_range %d\n", (int) 288 prefix.pf_line_range); 289 printf(" opcode base %d\n", (int) 290 prefix.pf_opcode_base); 291 printf(" standard opcode count %d\n", (int) 292 prefix.pf_std_op_count); 293 294 for (i = 1; i < prefix.pf_opcode_base; i++) { 295 printf(" opcode[%2d] length %d\n", (int) i, 296 (int) prefix.pf_opcode_length_table[i - 1]); 297 } 298 printf(" include directories count %d\n", (int) 299 prefix.pf_include_directories_count); 300 301 302 for (i = 0; i < prefix.pf_include_directories_count; ++i) { 303 printf(" include dir[%d] %s\n", 304 (int) i, prefix.pf_include_directories[i]); 305 } 306 printf(" files count %d\n", (int) 307 prefix.pf_files_count); 308 309 for (i = 0; i < prefix.pf_files_count; ++i) { 310 struct Line_Table_File_Entry_s *lfile = 311 prefix.pf_line_table_file_entries + i; 312 313 Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time; 314 Dwarf_Unsigned di = lfile->lte_directory_index; 315 Dwarf_Unsigned fl = lfile->lte_length_of_file; 316 317 printf(" file[%d] %s (file-number: %d) \n", 318 (int) i, (char *) lfile->lte_filename, 319 (int)(i+1)); 320 321 printf(" dir index %d\n", (int) di); 322 { 323 time_t tt = (time_t) tlm2; 324 325 printf(" last time 0x%x %s", /* ctime supplies 326 newline */ 327 (unsigned) tlm2, ctime(&tt)); 328 } 329 printf(" file length %ld 0x%lx\n", 330 (long) fl, (unsigned long) fl); 331 332 333 } 334 335 336 { 337 Dwarf_Unsigned offset = 0; 338 if(bogus_bytes_count > 0) { 339 Dwarf_Unsigned wcount = bogus_bytes_count; 340 Dwarf_Unsigned boffset = bogus_bytes_ptr - orig_line_ptr; 341 printf("*** DWARF CHECK: the line table prologue header_length " 342 " is %" DW_PR_DUu " too high, we pretend it is smaller." 343 "Section offset: %" DW_PR_DUu " (0x%" DW_PR_DUx ") ***\n", 344 wcount, boffset,boffset); 345 *err_count_out += 1; 346 } 347 offset = line_ptr - orig_line_ptr; 348 349 printf(" statement prog offset in section: %" DW_PR_DUu " 0x%" DW_PR_DUx "\n", 350 offset, offset); 351 } 352 353 /* Initialize the part of the state machine dependent on the 354 prefix. */ 355 is_stmt = prefix.pf_default_is_stmt; 356 357 358 print_line_header(); 359 /* Start of statement program. */ 360 while (line_ptr < line_ptr_end) { 361 int type = 0; 362 363 printf(" [0x%06" DW_PR_DSx "] ", 364 (Dwarf_Signed) (line_ptr - orig_line_ptr)); 365 opcode = *(Dwarf_Small *) line_ptr; 366 line_ptr++; 367 /* 'type' is the output */ 368 WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, 369 prefix.pf_opcode_length_table, line_ptr, 370 prefix.pf_std_op_count); 371 372 if (type == LOP_DISCARD) { 373 int oc; 374 int opcnt = prefix.pf_opcode_length_table[opcode]; 375 376 printf("*** DWARF CHECK: DISCARD standard opcode %d " 377 "with %d operands: " 378 "not understood.", opcode, opcnt); 379 *err_count_out += 1; 380 for (oc = 0; oc < opcnt; oc++) { 381 /* 382 * Read and discard operands we don't 383 * understand. 384 * Arbitrary choice of unsigned read. 385 * Signed read would work as well. 386 */ 387 Dwarf_Unsigned utmp2; 388 389 DECODE_LEB128_UWORD(line_ptr, utmp2); 390 printf(" %" DW_PR_DUu " (0x%" DW_PR_DUx ")", 391 (Dwarf_Unsigned) utmp2, 392 (Dwarf_Unsigned) utmp2); 393 } 394 395 printf("***\n"); 396 /* do nothing, necessary ops done */ 397 } else if (type == LOP_SPECIAL) { 398 /* This op code is a special op in the object, no matter 399 that it might fall into the standard op range in this 400 compile Thatis, these are special opcodes between 401 special_opcode_base and MAX_LINE_OP_CODE. (including 402 special_opcode_base and MAX_LINE_OP_CODE) */ 403 char special[50]; 404 unsigned origop = opcode; 405 406 opcode = opcode - prefix.pf_opcode_base; 407 address = address + prefix.pf_minimum_instruction_length * 408 (opcode / prefix.pf_line_range); 409 line = 410 line + prefix.pf_line_base + 411 opcode % prefix.pf_line_range; 412 413 sprintf(special, "Specialop %3u", origop); 414 print_line_detail(special, 415 opcode, address, (int) file, line, column, 416 is_stmt, basic_block, end_sequence, 417 prologue_end, epilogue_begin, isa); 418 419 basic_block = false; 420 421 } else if (type == LOP_STANDARD) { 422 switch (opcode) { 423 424 case DW_LNS_copy:{ 425 426 print_line_detail("DW_LNS_copy", 427 opcode, address, file, line, 428 column, is_stmt, basic_block, 429 end_sequence, prologue_end, 430 epilogue_begin, isa); 431 432 basic_block = false; 433 break; 434 } 435 436 case DW_LNS_advance_pc:{ 437 Dwarf_Unsigned utmp2; 438 439 440 DECODE_LEB128_UWORD(line_ptr, utmp2); 441 printf("DW_LNS_advance_pc val %" DW_PR_DSd " 0x%" DW_PR_DUx "\n", 442 (Dwarf_Signed) (Dwarf_Word) utmp2, 443 (Dwarf_Unsigned) (Dwarf_Word) utmp2); 444 leb128_num = (Dwarf_Word) utmp2; 445 address = 446 address + 447 prefix.pf_minimum_instruction_length * 448 leb128_num; 449 break; 450 } 451 452 case DW_LNS_advance_line:{ 453 Dwarf_Signed stmp; 454 455 456 DECODE_LEB128_SWORD(line_ptr, stmp); 457 advance_line = (Dwarf_Sword) stmp; 458 printf("DW_LNS_advance_line val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", 459 (Dwarf_Signed) advance_line, 460 (Dwarf_Signed) advance_line); 461 line = line + advance_line; 462 break; 463 } 464 465 case DW_LNS_set_file:{ 466 Dwarf_Unsigned utmp2; 467 468 469 DECODE_LEB128_UWORD(line_ptr, utmp2); 470 file = (Dwarf_Word) utmp2; 471 printf("DW_LNS_set_file %ld\n", (long) file); 472 break; 473 } 474 475 case DW_LNS_set_column:{ 476 Dwarf_Unsigned utmp2; 477 478 479 DECODE_LEB128_UWORD(line_ptr, utmp2); 480 column = (Dwarf_Word) utmp2; 481 printf("DW_LNS_set_column val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n", 482 (Dwarf_Signed) column, (Dwarf_Signed) column); 483 break; 484 } 485 486 case DW_LNS_negate_stmt:{ 487 is_stmt = !is_stmt; 488 printf("DW_LNS_negate_stmt\n"); 489 break; 490 } 491 492 case DW_LNS_set_basic_block:{ 493 494 printf("DW_LNS_set_basic_block\n"); 495 basic_block = true; 496 break; 497 } 498 499 case DW_LNS_const_add_pc:{ 500 opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; 501 address = 502 address + 503 prefix.pf_minimum_instruction_length * (opcode / 504 prefix. 505 pf_line_range); 506 507 printf("DW_LNS_const_add_pc new address 0x%" DW_PR_DSx "\n", 508 (Dwarf_Signed) address); 509 break; 510 } 511 512 case DW_LNS_fixed_advance_pc:{ 513 514 READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, 515 line_ptr, sizeof(Dwarf_Half)); 516 line_ptr += sizeof(Dwarf_Half); 517 address = address + fixed_advance_pc; 518 printf("DW_LNS_fixed_advance_pc val %" DW_PR_DSd 519 " 0x%" DW_PR_DSx " new address 0x%" DW_PR_DSx "\n", 520 (Dwarf_Signed) fixed_advance_pc, 521 (Dwarf_Signed) fixed_advance_pc, 522 (Dwarf_Signed) address); 523 break; 524 } 525 case DW_LNS_set_prologue_end:{ 526 527 prologue_end = true; 528 printf("DW_LNS_set_prologue_end set true.\n"); 529 break; 530 531 532 } 533 /* New in DWARF3 */ 534 case DW_LNS_set_epilogue_begin:{ 535 epilogue_begin = true; 536 printf("DW_LNS_set_epilogue_begin set true.\n"); 537 break; 538 } 539 540 /* New in DWARF3 */ 541 case DW_LNS_set_isa:{ 542 Dwarf_Unsigned utmp2; 543 544 DECODE_LEB128_UWORD(line_ptr, utmp2); 545 isa = utmp2; 546 printf("DW_LNS_set_isa new value 0x%" DW_PR_DUx ".\n", 547 (Dwarf_Unsigned) utmp2); 548 if (isa != utmp2) { 549 /* The value of the isa did not fit in our 550 local so we record it wrong. declare an 551 error. */ 552 dwarf_free_line_table_prefix(&prefix); 553 554 _dwarf_error(dbg, error, 555 DW_DLE_LINE_NUM_OPERANDS_BAD); 556 return (DW_DLV_ERROR); 557 } 558 break; 559 } 560 } 561 562 563 } else if (type == LOP_EXTENDED) { 564 Dwarf_Unsigned utmp3 = 0; 565 Dwarf_Word instr_length = 0; 566 Dwarf_Small ext_opcode = 0; 567 568 DECODE_LEB128_UWORD(line_ptr, utmp3); 569 instr_length = (Dwarf_Word) utmp3; 570 ext_opcode = *(Dwarf_Small *) line_ptr; 571 line_ptr++; 572 switch (ext_opcode) { 573 574 case DW_LNE_end_sequence:{ 575 end_sequence = true; 576 577 print_line_detail("DW_LNE_end_sequence extended", 578 opcode, address, file, line, 579 column, is_stmt, basic_block, 580 end_sequence, prologue_end, 581 epilogue_begin, isa); 582 583 address = 0; 584 file = 1; 585 line = 1; 586 column = 0; 587 is_stmt = prefix.pf_default_is_stmt; 588 basic_block = false; 589 end_sequence = false; 590 prologue_end = false; 591 epilogue_begin = false; 592 593 594 break; 595 } 596 597 case DW_LNE_set_address:{ 598 { 599 READ_UNALIGNED(dbg, address, Dwarf_Addr, 600 line_ptr, 601 die->di_cu_context->cc_address_size); 602 603 line_ptr += die->di_cu_context->cc_address_size; 604 printf("DW_LNE_set_address address 0x%" DW_PR_DUx "\n", 605 (Dwarf_Unsigned) address); 606 } 607 608 break; 609 } 610 611 case DW_LNE_define_file:{ 612 Dwarf_Unsigned di = 0; 613 Dwarf_Unsigned tlm = 0; 614 Dwarf_Unsigned fl = 0; 615 616 Dwarf_Small *fn = (Dwarf_Small *) line_ptr; 617 line_ptr = line_ptr + strlen((char *) line_ptr) + 1; 618 619 di = _dwarf_decode_u_leb128(line_ptr, 620 &leb128_length); 621 line_ptr = line_ptr + leb128_length; 622 623 tlm = _dwarf_decode_u_leb128(line_ptr, 624 &leb128_length); 625 line_ptr = line_ptr + leb128_length; 626 627 fl = _dwarf_decode_u_leb128(line_ptr, 628 &leb128_length); 629 line_ptr = line_ptr + leb128_length; 630 631 632 printf("DW_LNE_define_file %s \n", fn); 633 printf(" dir index %d\n", (int) di); 634 { 635 time_t tt3 = (time_t) tlm; 636 637 /* ctime supplies newline */ 638 printf(" last time 0x%x %s", 639 (unsigned) tlm, ctime(&tt3)); 640 } 641 printf(" file length %ld 0x%lx\n", 642 (long) fl, (unsigned long) fl); 643 644 break; 645 } 646 647 default:{ 648 /* This is an extended op code we do not know about, 649 other than we know now many bytes it is 650 (and the op code and the bytes of operand). */ 651 652 Dwarf_Unsigned remaining_bytes = instr_length -1; 653 if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) { 654 dwarf_free_line_table_prefix(&prefix); 655 _dwarf_error(dbg, error, 656 DW_DLE_LINE_EXT_OPCODE_BAD); 657 return (DW_DLV_ERROR); 658 } 659 printf("DW_LNE extended op 0x%x ",ext_opcode); 660 printf("Bytecount: " DW_PR_DUu , instr_length); 661 if(remaining_bytes > 0) { 662 printf(" linedata: 0x"); 663 while (remaining_bytes > 0) { 664 printf("%02x",(unsigned char)(*(line_ptr))); 665 line_ptr++; 666 remaining_bytes--; 667 } 668 } 669 printf("\n"); 670 } 671 break; 672 } 673 674 } 675 } 676 677 dwarf_free_line_table_prefix(&prefix); 678 return (DW_DLV_OK); 679 } 680 681 /* 682 This is support for dwarfdump: making it possible 683 for clients wanting line detail info on stdout 684 to get that detail without including internal libdwarf 685 header information. 686 Caller passes in compilation unit DIE. 687 The _dwarf_ version is obsolete (though supported for 688 compatibility). 689 The dwarf_ version is preferred. 690 The functions are intentionally identical: having 691 _dwarf_print_lines call dwarf_print_lines might 692 better emphasize they are intentionally identical, but 693 that seemed slightly silly given how short the functions are. 694 Interface adds error_count (output value) February 2009. 695 */ 696 int 697 dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error,int *error_count) 698 { 699 int only_line_header = 0; 700 int res = _dwarf_internal_printlines(die, error, 701 error_count, 702 only_line_header); 703 if (res != DW_DLV_OK) { 704 return res; 705 } 706 return res; 707 } 708 int 709 _dwarf_print_lines(Dwarf_Die die, Dwarf_Error * error) 710 { 711 int only_line_header = 0; 712 int err_count = 0; 713 int res = _dwarf_internal_printlines(die, error, 714 &err_count, 715 only_line_header); 716 /* No way to get error count back in this interface */ 717 if (res != DW_DLV_OK) { 718 return res; 719 } 720 return res; 721 } 722 723 /* The check is in case we are not printing full line data, 724 this gets some of the issues noted with .debug_line, 725 but not all. Call dwarf_print_lines() to get all issues. 726 Intended for apps like dwarfdump. 727 */ 728 void 729 dwarf_check_lineheader(Dwarf_Die die, int *err_count_out) 730 { 731 Dwarf_Error err; 732 int only_line_header = 1; 733 _dwarf_internal_printlines(die, &err,err_count_out, 734 only_line_header); 735 return; 736 } 737 738