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