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