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