1 /*- 2 * Copyright (c) 2009,2010 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include "_libdwarf.h" 28 29 ELFTC_VCSID("$Id: libdwarf_lineno.c 3164 2015-02-19 01:20:12Z kaiwang27 $"); 30 31 static int 32 _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir, 33 Dwarf_Error *error, Dwarf_Debug dbg) 34 { 35 Dwarf_LineFile lf; 36 FILE *filepath; 37 const char *incdir; 38 uint8_t *src; 39 size_t slen; 40 41 src = *p; 42 43 if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) { 44 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 45 return (DW_DLE_MEMORY); 46 } 47 48 lf->lf_fullpath = NULL; 49 lf->lf_fname = (char *) src; 50 src += strlen(lf->lf_fname) + 1; 51 lf->lf_dirndx = _dwarf_decode_uleb128(&src); 52 if (lf->lf_dirndx > li->li_inclen) { 53 free(lf); 54 DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD); 55 return (DW_DLE_DIR_INDEX_BAD); 56 } 57 58 /* Make a full pathname if needed. */ 59 if (*lf->lf_fname != '/') { 60 filepath = open_memstream(&lf->lf_fullpath, &slen); 61 if (filepath == NULL) { 62 free(lf); 63 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 64 return (DW_DLE_MEMORY); 65 } 66 67 if (lf->lf_dirndx > 0) 68 incdir = li->li_incdirs[lf->lf_dirndx - 1]; 69 else 70 incdir = NULL; 71 72 /* 73 * Prepend the compilation directory if the directory table 74 * entry is relative. 75 */ 76 if (incdir == NULL || *incdir != '/') 77 fprintf(filepath, "%s/", compdir); 78 if (incdir != NULL) 79 fprintf(filepath, "%s/", incdir); 80 fprintf(filepath, "%s", lf->lf_fname); 81 if (fclose(filepath) != 0) { 82 free(lf); 83 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 84 return (DW_DLE_MEMORY); 85 } 86 } 87 88 lf->lf_mtime = _dwarf_decode_uleb128(&src); 89 lf->lf_size = _dwarf_decode_uleb128(&src); 90 STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next); 91 li->li_lflen++; 92 93 *p = src; 94 95 return (DW_DLE_NONE); 96 } 97 98 static int 99 _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p, 100 uint8_t *pe, const char *compdir, Dwarf_Error *error) 101 { 102 Dwarf_Debug dbg; 103 Dwarf_Line ln, tln; 104 uint64_t address, file, line, column, opsize; 105 int is_stmt, basic_block, end_sequence; 106 int ret; 107 108 #define RESET_REGISTERS \ 109 do { \ 110 address = 0; \ 111 file = 1; \ 112 line = 1; \ 113 column = 0; \ 114 is_stmt = li->li_defstmt; \ 115 basic_block = 0; \ 116 end_sequence = 0; \ 117 } while(0) 118 119 #define APPEND_ROW \ 120 do { \ 121 ln = malloc(sizeof(struct _Dwarf_Line)); \ 122 if (ln == NULL) { \ 123 ret = DW_DLE_MEMORY; \ 124 DWARF_SET_ERROR(dbg, error, ret); \ 125 goto prog_fail; \ 126 } \ 127 ln->ln_li = li; \ 128 ln->ln_addr = address; \ 129 ln->ln_symndx = 0; \ 130 ln->ln_fileno = file; \ 131 ln->ln_lineno = line; \ 132 ln->ln_column = column; \ 133 ln->ln_bblock = basic_block; \ 134 ln->ln_stmt = is_stmt; \ 135 ln->ln_endseq = end_sequence; \ 136 STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);\ 137 li->li_lnlen++; \ 138 } while(0) 139 140 #define LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange)) 141 #define ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen) 142 143 dbg = cu->cu_dbg; 144 145 /* 146 * Set registers to their default values. 147 */ 148 RESET_REGISTERS; 149 150 /* 151 * Start line number program. 152 */ 153 while (p < pe) { 154 if (*p == 0) { 155 156 /* 157 * Extended Opcodes. 158 */ 159 160 p++; 161 opsize = _dwarf_decode_uleb128(&p); 162 switch (*p) { 163 case DW_LNE_end_sequence: 164 p++; 165 end_sequence = 1; 166 APPEND_ROW; 167 RESET_REGISTERS; 168 break; 169 case DW_LNE_set_address: 170 p++; 171 address = dbg->decode(&p, cu->cu_pointer_size); 172 break; 173 case DW_LNE_define_file: 174 p++; 175 ret = _dwarf_lineno_add_file(li, &p, compdir, 176 error, dbg); 177 if (ret != DW_DLE_NONE) 178 goto prog_fail; 179 break; 180 default: 181 /* Unrecognized extened opcodes. */ 182 p += opsize; 183 } 184 185 } else if (*p > 0 && *p < li->li_opbase) { 186 187 /* 188 * Standard Opcodes. 189 */ 190 191 switch (*p++) { 192 case DW_LNS_copy: 193 APPEND_ROW; 194 basic_block = 0; 195 break; 196 case DW_LNS_advance_pc: 197 address += _dwarf_decode_uleb128(&p) * 198 li->li_minlen; 199 break; 200 case DW_LNS_advance_line: 201 line += _dwarf_decode_sleb128(&p); 202 break; 203 case DW_LNS_set_file: 204 file = _dwarf_decode_uleb128(&p); 205 break; 206 case DW_LNS_set_column: 207 column = _dwarf_decode_uleb128(&p); 208 break; 209 case DW_LNS_negate_stmt: 210 is_stmt = !is_stmt; 211 break; 212 case DW_LNS_set_basic_block: 213 basic_block = 1; 214 break; 215 case DW_LNS_const_add_pc: 216 address += ADDRESS(255); 217 break; 218 case DW_LNS_fixed_advance_pc: 219 address += dbg->decode(&p, 2); 220 break; 221 case DW_LNS_set_prologue_end: 222 break; 223 case DW_LNS_set_epilogue_begin: 224 break; 225 case DW_LNS_set_isa: 226 (void) _dwarf_decode_uleb128(&p); 227 break; 228 default: 229 /* Unrecognized extened opcodes. What to do? */ 230 break; 231 } 232 233 } else { 234 235 /* 236 * Special Opcodes. 237 */ 238 239 line += LINE(*p); 240 address += ADDRESS(*p); 241 APPEND_ROW; 242 basic_block = 0; 243 p++; 244 } 245 } 246 247 return (DW_DLE_NONE); 248 249 prog_fail: 250 251 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 252 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); 253 free(ln); 254 } 255 256 return (ret); 257 258 #undef RESET_REGISTERS 259 #undef APPEND_ROW 260 #undef LINE 261 #undef ADDRESS 262 } 263 264 int 265 _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error) 266 { 267 Dwarf_Debug dbg; 268 Dwarf_Section *ds; 269 Dwarf_CU cu; 270 Dwarf_Attribute at; 271 Dwarf_LineInfo li; 272 Dwarf_LineFile lf, tlf; 273 const char *compdir; 274 uint64_t length, hdroff, endoff; 275 uint8_t *p; 276 int dwarf_size, i, ret; 277 278 cu = die->die_cu; 279 assert(cu != NULL); 280 281 dbg = cu->cu_dbg; 282 assert(dbg != NULL); 283 284 if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL) 285 return (DW_DLE_NONE); 286 287 /* 288 * Try to find out the dir where the CU was compiled. Later we 289 * will use the dir to create full pathnames, if need. 290 */ 291 compdir = NULL; 292 at = _dwarf_attr_find(die, DW_AT_comp_dir); 293 if (at != NULL) { 294 switch (at->at_form) { 295 case DW_FORM_strp: 296 compdir = at->u[1].s; 297 break; 298 case DW_FORM_string: 299 compdir = at->u[0].s; 300 break; 301 default: 302 break; 303 } 304 } 305 306 length = dbg->read(ds->ds_data, &offset, 4); 307 if (length == 0xffffffff) { 308 dwarf_size = 8; 309 length = dbg->read(ds->ds_data, &offset, 8); 310 } else 311 dwarf_size = 4; 312 313 if (length > ds->ds_size - offset) { 314 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD); 315 return (DW_DLE_DEBUG_LINE_LENGTH_BAD); 316 } 317 318 if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) { 319 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 320 return (DW_DLE_MEMORY); 321 } 322 323 /* 324 * Read in line number program header. 325 */ 326 li->li_length = length; 327 endoff = offset + length; 328 li->li_version = dbg->read(ds->ds_data, &offset, 2); /* FIXME: verify version */ 329 li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size); 330 hdroff = offset; 331 li->li_minlen = dbg->read(ds->ds_data, &offset, 1); 332 if (li->li_version == 4) 333 li->li_maxop = dbg->read(ds->ds_data, &offset, 1); 334 li->li_defstmt = dbg->read(ds->ds_data, &offset, 1); 335 li->li_lbase = dbg->read(ds->ds_data, &offset, 1); 336 li->li_lrange = dbg->read(ds->ds_data, &offset, 1); 337 li->li_opbase = dbg->read(ds->ds_data, &offset, 1); 338 STAILQ_INIT(&li->li_lflist); 339 STAILQ_INIT(&li->li_lnlist); 340 341 if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) { 342 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 343 DWARF_SET_ERROR(dbg, error, ret); 344 goto fail_cleanup; 345 } 346 347 if ((li->li_oplen = malloc(li->li_opbase)) == NULL) { 348 ret = DW_DLE_MEMORY; 349 DWARF_SET_ERROR(dbg, error, ret); 350 goto fail_cleanup; 351 } 352 353 /* 354 * Read in std opcode arg length list. Note that the first 355 * element is not used. 356 */ 357 for (i = 1; i < li->li_opbase; i++) 358 li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1); 359 360 /* 361 * Check how many strings in the include dir string array. 362 */ 363 length = 0; 364 p = ds->ds_data + offset; 365 while (*p != '\0') { 366 while (*p++ != '\0') 367 ; 368 length++; 369 } 370 li->li_inclen = length; 371 372 /* Sanity check. */ 373 if (p - ds->ds_data > (int) ds->ds_size) { 374 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 375 DWARF_SET_ERROR(dbg, error, ret); 376 goto fail_cleanup; 377 } 378 379 if (length != 0) { 380 if ((li->li_incdirs = malloc(length * sizeof(char *))) == 381 NULL) { 382 ret = DW_DLE_MEMORY; 383 DWARF_SET_ERROR(dbg, error, ret); 384 goto fail_cleanup; 385 } 386 } 387 388 /* Fill in include dir array. */ 389 i = 0; 390 p = ds->ds_data + offset; 391 while (*p != '\0') { 392 li->li_incdirs[i++] = (char *) p; 393 while (*p++ != '\0') 394 ; 395 } 396 397 p++; 398 399 /* 400 * Process file list. 401 */ 402 while (*p != '\0') { 403 ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg); 404 if (ret != DW_DLE_NONE) 405 goto fail_cleanup; 406 if (p - ds->ds_data > (int) ds->ds_size) { 407 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 408 DWARF_SET_ERROR(dbg, error, ret); 409 goto fail_cleanup; 410 } 411 } 412 413 p++; 414 415 /* Sanity check. */ 416 if (p - ds->ds_data - hdroff != li->li_hdrlen) { 417 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 418 DWARF_SET_ERROR(dbg, error, ret); 419 goto fail_cleanup; 420 } 421 422 /* 423 * Process line number program. 424 */ 425 ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir, 426 error); 427 if (ret != DW_DLE_NONE) 428 goto fail_cleanup; 429 430 cu->cu_lineinfo = li; 431 432 return (DW_DLE_NONE); 433 434 fail_cleanup: 435 436 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 437 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next); 438 if (lf->lf_fullpath) 439 free(lf->lf_fullpath); 440 free(lf); 441 } 442 443 if (li->li_oplen) 444 free(li->li_oplen); 445 if (li->li_incdirs) 446 free(li->li_incdirs); 447 free(li); 448 449 return (ret); 450 } 451 452 void 453 _dwarf_lineno_cleanup(Dwarf_LineInfo li) 454 { 455 Dwarf_LineFile lf, tlf; 456 Dwarf_Line ln, tln; 457 458 if (li == NULL) 459 return; 460 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 461 STAILQ_REMOVE(&li->li_lflist, lf, 462 _Dwarf_LineFile, lf_next); 463 if (lf->lf_fullpath) 464 free(lf->lf_fullpath); 465 free(lf); 466 } 467 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 468 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, 469 ln_next); 470 free(ln); 471 } 472 if (li->li_oplen) 473 free(li->li_oplen); 474 if (li->li_incdirs) 475 free(li->li_incdirs); 476 if (li->li_lnarray) 477 free(li->li_lnarray); 478 if (li->li_lfnarray) 479 free(li->li_lfnarray); 480 free(li); 481 } 482 483 static int 484 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds, 485 Dwarf_Rel_Section drs, Dwarf_Error * error) 486 { 487 Dwarf_LineInfo li; 488 Dwarf_Line ln; 489 Dwarf_Unsigned address, file, line, spc; 490 Dwarf_Unsigned addr0, maddr; 491 Dwarf_Signed line0, column; 492 int is_stmt, basic_block; 493 int need_copy; 494 int ret; 495 496 #define RESET_REGISTERS \ 497 do { \ 498 address = 0; \ 499 file = 1; \ 500 line = 1; \ 501 column = 0; \ 502 is_stmt = li->li_defstmt; \ 503 basic_block = 0; \ 504 } while(0) 505 506 li = dbg->dbgp_lineinfo; 507 maddr = (255 - li->li_opbase) / li->li_lrange; 508 509 RESET_REGISTERS; 510 511 STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) { 512 if (ln->ln_symndx > 0) { 513 /* 514 * Generate DW_LNE_set_address extended op. 515 */ 516 RCHECK(WRITE_VALUE(0, 1)); 517 RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1)); 518 RCHECK(WRITE_VALUE(DW_LNE_set_address, 1)); 519 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, 520 dwarf_drt_data_reloc, dbg->dbg_pointer_size, 521 ds->ds_size, ln->ln_symndx, ln->ln_addr, 522 NULL, error)); 523 address = ln->ln_addr; 524 continue; 525 } else if (ln->ln_endseq) { 526 addr0 = (ln->ln_addr - address) / li->li_minlen; 527 if (addr0 != 0) { 528 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); 529 RCHECK(WRITE_ULEB128(addr0)); 530 } 531 532 /* 533 * Generate DW_LNE_end_sequence. 534 */ 535 RCHECK(WRITE_VALUE(0, 1)); 536 RCHECK(WRITE_ULEB128(1)); 537 RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1)); 538 RESET_REGISTERS; 539 continue; 540 } 541 542 /* 543 * Generate standard opcodes for file, column, is_stmt or 544 * basic_block changes. 545 */ 546 if (ln->ln_fileno != file) { 547 RCHECK(WRITE_VALUE(DW_LNS_set_file, 1)); 548 RCHECK(WRITE_ULEB128(ln->ln_fileno)); 549 file = ln->ln_fileno; 550 } 551 if (ln->ln_column != column) { 552 RCHECK(WRITE_VALUE(DW_LNS_set_column, 1)); 553 RCHECK(WRITE_ULEB128(ln->ln_column)); 554 column = ln->ln_column; 555 } 556 if (ln->ln_stmt != is_stmt) { 557 RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1)); 558 is_stmt = ln->ln_stmt; 559 } 560 if (ln->ln_bblock && !basic_block) { 561 RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1)); 562 basic_block = 1; 563 } 564 565 /* 566 * Calculate address and line number change. 567 */ 568 addr0 = (ln->ln_addr - address) / li->li_minlen; 569 line0 = ln->ln_lineno - line; 570 571 if (addr0 == 0 && line0 == 0) 572 continue; 573 574 /* 575 * Check if line delta is with the range and if the special 576 * opcode can be used. 577 */ 578 assert(li->li_lbase <= 0); 579 if (line0 >= li->li_lbase && 580 line0 <= li->li_lbase + li->li_lrange - 1) { 581 spc = (line0 - li->li_lbase) + 582 (li->li_lrange * addr0) + li->li_opbase; 583 if (spc <= 255) { 584 RCHECK(WRITE_VALUE(spc, 1)); 585 basic_block = 0; 586 goto next_line; 587 } 588 } 589 590 /* Generate DW_LNS_advance_line for line number change. */ 591 if (line0 != 0) { 592 RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1)); 593 RCHECK(WRITE_SLEB128(line0)); 594 line0 = 0; 595 need_copy = 1; 596 } else 597 need_copy = basic_block; 598 599 if (addr0 != 0) { 600 /* See if it can be handled by DW_LNS_const_add_pc. */ 601 spc = (line0 - li->li_lbase) + 602 (li->li_lrange * (addr0 - maddr)) + li->li_opbase; 603 if (addr0 >= maddr && spc <= 255) { 604 RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1)); 605 RCHECK(WRITE_VALUE(spc, 1)); 606 } else { 607 /* Otherwise we use DW_LNS_advance_pc. */ 608 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); 609 RCHECK(WRITE_ULEB128(addr0)); 610 } 611 } 612 613 if (need_copy) { 614 RCHECK(WRITE_VALUE(DW_LNS_copy, 1)); 615 basic_block = 0; 616 } 617 618 next_line: 619 address = ln->ln_addr; 620 line = ln->ln_lineno; 621 } 622 623 return (DW_DLE_NONE); 624 625 gen_fail: 626 return (ret); 627 628 #undef RESET_REGISTERS 629 } 630 631 static uint8_t 632 _dwarf_get_minlen(Dwarf_P_Debug dbg) 633 { 634 635 assert(dbg != NULL); 636 637 switch (dbg->dbgp_isa) { 638 case DW_ISA_ARM: 639 return (2); 640 case DW_ISA_X86: 641 case DW_ISA_X86_64: 642 return (1); 643 default: 644 return (4); 645 } 646 } 647 648 static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1}; 649 650 int 651 _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 652 { 653 Dwarf_LineInfo li; 654 Dwarf_LineFile lf; 655 Dwarf_P_Section ds; 656 Dwarf_Rel_Section drs; 657 Dwarf_Unsigned offset; 658 int i, ret; 659 660 assert(dbg != NULL && dbg->dbgp_lineinfo != NULL); 661 662 li = dbg->dbgp_lineinfo; 663 if (STAILQ_EMPTY(&li->li_lnlist)) 664 return (DW_DLE_NONE); 665 666 li->li_length = 0; 667 li->li_version = 2; 668 li->li_hdrlen = 0; 669 li->li_minlen = _dwarf_get_minlen(dbg); 670 li->li_defstmt = 1; 671 li->li_lbase = -5; 672 li->li_lrange = 14; 673 li->li_opbase = 10; 674 675 /* Create .debug_line section. */ 676 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) != 677 DW_DLE_NONE) 678 return (ret); 679 680 /* Create relocation section for .debug_line */ 681 if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) != 682 DW_DLE_NONE) 683 goto gen_fail1; 684 685 /* Length placeholder. (We only use 32-bit DWARF format) */ 686 RCHECK(WRITE_VALUE(0, 4)); 687 688 /* Write line number dwarf version. (DWARF2) */ 689 RCHECK(WRITE_VALUE(li->li_version, 2)); 690 691 /* Header length placeholder. */ 692 offset = ds->ds_size; 693 RCHECK(WRITE_VALUE(li->li_hdrlen, 4)); 694 695 /* Write minimum instruction length. */ 696 RCHECK(WRITE_VALUE(li->li_minlen, 1)); 697 698 /* 699 * Write initial value for is_stmt. XXX Which default value we 700 * should use? 701 */ 702 RCHECK(WRITE_VALUE(li->li_defstmt, 1)); 703 704 /* 705 * Write line_base and line_range. FIXME These value needs to be 706 * fine tuned. 707 */ 708 RCHECK(WRITE_VALUE(li->li_lbase, 1)); 709 RCHECK(WRITE_VALUE(li->li_lrange, 1)); 710 711 /* Write opcode_base. (DWARF2) */ 712 RCHECK(WRITE_VALUE(li->li_opbase, 1)); 713 714 /* Write standard op length array. */ 715 RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0]))); 716 717 /* Write the list of include directories. */ 718 for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) 719 RCHECK(WRITE_STRING(li->li_incdirs[i])); 720 RCHECK(WRITE_VALUE(0, 1)); 721 722 /* Write the list of filenames. */ 723 STAILQ_FOREACH(lf, &li->li_lflist, lf_next) { 724 RCHECK(WRITE_STRING(lf->lf_fname)); 725 RCHECK(WRITE_ULEB128(lf->lf_dirndx)); 726 RCHECK(WRITE_ULEB128(lf->lf_mtime)); 727 RCHECK(WRITE_ULEB128(lf->lf_size)); 728 } 729 RCHECK(WRITE_VALUE(0, 1)); 730 731 /* Fill in the header length. */ 732 li->li_hdrlen = ds->ds_size - offset - 4; 733 dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4); 734 735 /* Generate the line number program. */ 736 RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error)); 737 738 /* Fill in the length of this line info. */ 739 li->li_length = ds->ds_size - 4; 740 offset = 0; 741 dbg->write(ds->ds_data, &offset, li->li_length, 4); 742 743 /* Notify the creation of .debug_line ELF section. */ 744 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 745 746 /* Finalize relocation section for .debug_line. */ 747 RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 748 749 return (DW_DLE_NONE); 750 751 gen_fail: 752 _dwarf_reloc_section_free(dbg, &drs); 753 754 gen_fail1: 755 _dwarf_section_free(dbg, &ds); 756 757 return (ret); 758 } 759 760 void 761 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg) 762 { 763 Dwarf_LineInfo li; 764 Dwarf_LineFile lf, tlf; 765 Dwarf_Line ln, tln; 766 int i; 767 768 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 769 if (dbg->dbgp_lineinfo == NULL) 770 return; 771 772 li = dbg->dbgp_lineinfo; 773 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 774 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, 775 lf_next); 776 if (lf->lf_fname) 777 free(lf->lf_fname); 778 free(lf); 779 } 780 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 781 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); 782 free(ln); 783 } 784 if (li->li_incdirs) { 785 for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) 786 free(li->li_incdirs[i]); 787 free(li->li_incdirs); 788 } 789 free(li); 790 dbg->dbgp_lineinfo = NULL; 791 } 792