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