1 /* $NetBSD: libdwarf_lineno.c,v 1.6 2026/05/17 21:40:49 jkoshy Exp $ */ 2 3 /*- 4 * Copyright (c) 2009,2010,2023 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.6 2026/05/17 21:40:49 jkoshy Exp $"); 32 ELFTC_VCSID("Id: libdwarf_lineno.c 4067 2025-01-03 10:33:44Z jkoshy"); 33 34 static int 35 _dwarf_lineno_make_fullpath(Dwarf_Debug dbg, Dwarf_LineInfo li, 36 Dwarf_LineFile lf, const char *compdir, Dwarf_Error *error) 37 { 38 const char *dirname; 39 int slen; 40 41 /* Make full pathname if need. */ 42 if (*lf->lf_fname != '/') { 43 dirname = compdir; 44 if (lf->lf_dirndx > 0) 45 dirname = li->li_incdirs[lf->lf_dirndx - 1]; 46 if (dirname != NULL) { 47 slen = strlen(dirname) + strlen(lf->lf_fname) + 2; 48 if ((lf->lf_fullpath = malloc(slen)) == NULL) { 49 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 50 return (DW_DLE_MEMORY); 51 } 52 snprintf(lf->lf_fullpath, slen, "%s/%s", dirname, 53 lf->lf_fname); 54 } 55 } 56 57 return (DW_DLE_NONE); 58 } 59 60 static int 61 _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir, 62 Dwarf_Error *error, Dwarf_Debug dbg) 63 { 64 Dwarf_LineFile lf; 65 uint8_t *src; 66 int ret; 67 68 src = *p; 69 70 if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) { 71 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 72 return (DW_DLE_MEMORY); 73 } 74 75 lf->lf_fullpath = NULL; 76 lf->lf_fname = (char *) src; 77 src += strlen(lf->lf_fname) + 1; 78 lf->lf_dirndx = _dwarf_decode_uleb128(&src); 79 if (lf->lf_dirndx > li->li_inclen) { 80 free(lf); 81 DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD); 82 return (DW_DLE_DIR_INDEX_BAD); 83 } 84 85 ret = _dwarf_lineno_make_fullpath(dbg, li, lf, compdir, error); 86 if (ret != DW_DLE_NONE) { 87 free(lf); 88 return (ret); 89 } 90 91 lf->lf_mtime = _dwarf_decode_uleb128(&src); 92 lf->lf_size = _dwarf_decode_uleb128(&src); 93 STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next); 94 li->li_lflen++; 95 96 *p = src; 97 98 return (DW_DLE_NONE); 99 } 100 101 static int 102 _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p, 103 uint8_t *pe, const char *compdir, Dwarf_Error *error) 104 { 105 Dwarf_Debug dbg; 106 Dwarf_Line ln, tln; 107 uint64_t address, file, line, column, opsize; 108 int is_stmt, basic_block, end_sequence; 109 int ret; 110 111 #define RESET_REGISTERS \ 112 do { \ 113 address = 0; \ 114 file = 1; \ 115 line = 1; \ 116 column = 0; \ 117 is_stmt = li->li_defstmt; \ 118 basic_block = 0; \ 119 end_sequence = 0; \ 120 } while(0) 121 122 #define APPEND_ROW \ 123 do { \ 124 ln = malloc(sizeof(struct _Dwarf_Line)); \ 125 if (ln == NULL) { \ 126 ret = DW_DLE_MEMORY; \ 127 DWARF_SET_ERROR(dbg, error, ret); \ 128 goto prog_fail; \ 129 } \ 130 ln->ln_li = li; \ 131 ln->ln_addr = address; \ 132 ln->ln_symndx = 0; \ 133 ln->ln_fileno = file; \ 134 ln->ln_lineno = line; \ 135 ln->ln_column = column; \ 136 ln->ln_bblock = basic_block; \ 137 ln->ln_stmt = is_stmt; \ 138 ln->ln_endseq = end_sequence; \ 139 STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);\ 140 li->li_lnlen++; \ 141 } while(0) 142 143 #define LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange)) 144 #define ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen) 145 146 dbg = cu->cu_dbg; 147 148 /* 149 * Set registers to their default values. 150 */ 151 RESET_REGISTERS; 152 153 /* 154 * Start line number program. 155 */ 156 while (p < pe) { 157 if (*p == 0) { 158 159 /* 160 * Extended Opcodes. 161 */ 162 163 p++; 164 opsize = _dwarf_decode_uleb128(&p); 165 switch (*p) { 166 case DW_LNE_end_sequence: 167 p++; 168 end_sequence = 1; 169 APPEND_ROW; 170 RESET_REGISTERS; 171 break; 172 case DW_LNE_set_address: 173 p++; 174 address = dbg->decode(&p, cu->cu_pointer_size); 175 break; 176 case DW_LNE_define_file: 177 p++; 178 ret = _dwarf_lineno_add_file(li, &p, compdir, 179 error, dbg); 180 if (ret != DW_DLE_NONE) 181 goto prog_fail; 182 break; 183 default: 184 /* Unrecognized extened opcodes. */ 185 p += opsize; 186 } 187 188 } else if (*p > 0 && *p < li->li_opbase) { 189 190 /* 191 * Standard Opcodes. 192 */ 193 194 switch (*p++) { 195 case DW_LNS_copy: 196 APPEND_ROW; 197 basic_block = 0; 198 break; 199 case DW_LNS_advance_pc: 200 address += _dwarf_decode_uleb128(&p) * 201 li->li_minlen; 202 break; 203 case DW_LNS_advance_line: 204 line += _dwarf_decode_sleb128(&p); 205 break; 206 case DW_LNS_set_file: 207 file = _dwarf_decode_uleb128(&p); 208 break; 209 case DW_LNS_set_column: 210 column = _dwarf_decode_uleb128(&p); 211 break; 212 case DW_LNS_negate_stmt: 213 is_stmt = !is_stmt; 214 break; 215 case DW_LNS_set_basic_block: 216 basic_block = 1; 217 break; 218 case DW_LNS_const_add_pc: 219 address += ADDRESS(255); 220 break; 221 case DW_LNS_fixed_advance_pc: 222 address += dbg->decode(&p, 2); 223 break; 224 case DW_LNS_set_prologue_end: 225 break; 226 case DW_LNS_set_epilogue_begin: 227 break; 228 case DW_LNS_set_isa: 229 (void) _dwarf_decode_uleb128(&p); 230 break; 231 default: 232 /* Unrecognized extened opcodes. What to do? */ 233 break; 234 } 235 236 } else { 237 238 /* 239 * Special Opcodes. 240 */ 241 242 line += LINE(*p); 243 address += ADDRESS(*p); 244 APPEND_ROW; 245 basic_block = 0; 246 p++; 247 } 248 } 249 250 return (DW_DLE_NONE); 251 252 prog_fail: 253 254 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 255 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); 256 free(ln); 257 } 258 259 return (ret); 260 261 #undef RESET_REGISTERS 262 #undef APPEND_ROW 263 #undef LINE 264 #undef ADDRESS 265 } 266 267 struct lnct { 268 unsigned type; 269 unsigned form; 270 }; 271 272 273 static int 274 _dwarf_lineno_parse_lnct_desc(Dwarf_Debug dbg, int fmt, struct lnct **lnct, 275 uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 276 { 277 int i; 278 279 if (fmt == 0) { 280 *lnct = NULL; 281 return (DW_DLE_NONE); 282 } 283 284 if ((*lnct = calloc(fmt, sizeof(struct lnct))) == NULL) { 285 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 286 return (DW_DLE_MEMORY); 287 } 288 for (i = 0; i < fmt; i++) { 289 (*lnct)[i].type = _dwarf_read_uleb128(data, offsetp); 290 (*lnct)[i].form = _dwarf_read_uleb128(data, offsetp); 291 } 292 293 return (DW_DLE_NONE); 294 } 295 296 static int 297 _dwarf_lineno_lnct_path(Dwarf_Debug dbg, char **fname, unsigned form, 298 uint8_t *data, uint64_t size, uint64_t *offsetp, int dwarf_size, 299 Dwarf_Error *error) 300 { 301 Dwarf_Unsigned sp; 302 int ret; 303 304 ret = DW_DLE_NONE; 305 306 switch (form) { 307 case DW_FORM_string: 308 *fname = _dwarf_read_string(data, size, offsetp); 309 break; 310 case DW_FORM_strp: 311 sp = dbg->read(data, offsetp, dwarf_size); 312 *fname = _dwarf_strtab_get_table(dbg) + sp; 313 break; 314 case DW_FORM_line_strp: 315 sp = dbg->read(data, offsetp, dwarf_size); 316 *fname = _dwarf_strtab_get_line_table(dbg) + sp; 317 break; 318 case DW_FORM_strp_sup: 319 sp = dbg->read(data, offsetp, dwarf_size); 320 *fname = NULL; /* TODO: support sup string table. */ 321 break; 322 default: 323 ret = DW_DLE_LNCT_DESC_BAD; 324 DWARF_SET_ERROR(dbg, error, ret); 325 break; 326 } 327 328 return (ret); 329 } 330 331 static int 332 _dwarf_lineno_lnct_dirndx(Dwarf_Debug dbg, Dwarf_Unsigned *dirndx, 333 unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 334 { 335 int ret; 336 337 ret = DW_DLE_NONE; 338 339 switch (form) { 340 case DW_FORM_data1: 341 *dirndx = dbg->read(data, offsetp, 1); 342 break; 343 case DW_FORM_data2: 344 *dirndx = dbg->read(data, offsetp, 2); 345 break; 346 case DW_FORM_udata: 347 *dirndx = _dwarf_read_uleb128(data, offsetp); 348 break; 349 default: 350 ret = DW_DLE_LNCT_DESC_BAD; 351 DWARF_SET_ERROR(dbg, error, ret); 352 break; 353 } 354 355 return (ret); 356 } 357 358 static int 359 _dwarf_lineno_lnct_timestamp(Dwarf_Debug dbg, Dwarf_Unsigned *ts, 360 unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 361 { 362 int ret; 363 364 ret = DW_DLE_NONE; 365 366 switch (form) { 367 case DW_FORM_udata: 368 *ts = _dwarf_read_uleb128(data, offsetp); 369 break; 370 case DW_FORM_data4: 371 *ts = dbg->read(data, offsetp, 4); 372 break; 373 case DW_FORM_data8: 374 *ts = dbg->read(data, offsetp, 8); 375 break; 376 case DW_FORM_block: 377 /* TODO: Not supported. */ 378 default: 379 ret = DW_DLE_LNCT_DESC_BAD; 380 DWARF_SET_ERROR(dbg, error, ret); 381 break; 382 } 383 384 return (ret); 385 } 386 387 static int 388 _dwarf_lineno_lnct_size(Dwarf_Debug dbg, Dwarf_Unsigned *sz, unsigned form, 389 uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 390 { 391 int ret; 392 393 ret = DW_DLE_NONE; 394 395 switch (form) { 396 case DW_FORM_udata: 397 *sz = _dwarf_read_uleb128(data, offsetp); 398 break; 399 case DW_FORM_data1: 400 *sz = dbg->read(data, offsetp, 1); 401 break; 402 case DW_FORM_data2: 403 *sz = dbg->read(data, offsetp, 2); 404 break; 405 case DW_FORM_data4: 406 *sz = dbg->read(data, offsetp, 4); 407 break; 408 case DW_FORM_data8: 409 *sz = dbg->read(data, offsetp, 8); 410 break; 411 default: 412 ret = DW_DLE_LNCT_DESC_BAD; 413 DWARF_SET_ERROR(dbg, error, ret); 414 break; 415 } 416 417 return (ret); 418 } 419 420 static int 421 _dwarf_lineno_lnct_md5(Dwarf_Debug dbg, Dwarf_Form_Data16 *md5, 422 unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error) 423 { 424 425 if (form != DW_FORM_data16) { 426 DWARF_SET_ERROR(dbg, error, DW_DLE_LNCT_DESC_BAD); 427 return (DW_DLE_LNCT_DESC_BAD); 428 } 429 430 memcpy(md5->fd_data, data + *offsetp, 16); 431 offsetp += 16; 432 433 return (DW_DLE_NONE); 434 } 435 436 int 437 _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error) 438 { 439 Dwarf_Debug dbg; 440 Dwarf_Section *ds; 441 Dwarf_CU cu; 442 Dwarf_Attribute at; 443 Dwarf_LineInfo li; 444 Dwarf_LineFile lf, tlf; 445 struct lnct *lnct; 446 char *compdir; 447 uint64_t length, hdroff, endoff; 448 uint8_t *p; 449 int dwarf_size, fmt, j, ret; 450 unsigned int i; 451 452 cu = die->die_cu; 453 assert(cu != NULL); 454 455 dbg = cu->cu_dbg; 456 assert(dbg != NULL); 457 458 if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL) 459 return (DW_DLE_NONE); 460 461 /* 462 * Try to find out the dir where the CU was compiled. Later we 463 * will use the dir to create full pathnames, if need. 464 */ 465 compdir = NULL; 466 at = _dwarf_attr_find(die, DW_AT_comp_dir); 467 if (at != NULL) { 468 switch (at->at_form) { 469 case DW_FORM_strp: 470 case DW_FORM_strp_sup: 471 case DW_FORM_line_strp: 472 compdir = at->u[1].s; 473 break; 474 case DW_FORM_string: 475 compdir = at->u[0].s; 476 break; 477 case DW_FORM_strx: 478 case DW_FORM_strx1: 479 case DW_FORM_strx2: 480 case DW_FORM_strx3: 481 case DW_FORM_strx4: 482 if ((ret = _dwarf_read_indexed_str(dbg, cu, 483 at->u[0].u64, &compdir, error)) != DW_DLE_NONE) 484 return (ret); 485 default: 486 break; 487 } 488 } 489 490 length = dbg->read(ds->ds_data, &offset, 4); 491 if (length == 0xffffffff) { 492 dwarf_size = 8; 493 length = dbg->read(ds->ds_data, &offset, 8); 494 } else 495 dwarf_size = 4; 496 497 if (length > ds->ds_size - offset) { 498 DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD); 499 return (DW_DLE_DEBUG_LINE_LENGTH_BAD); 500 } 501 502 if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) { 503 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 504 return (DW_DLE_MEMORY); 505 } 506 507 /* 508 * Read in line number program header. 509 */ 510 li->li_length = length; 511 endoff = offset + length; 512 li->li_version = dbg->read(ds->ds_data, &offset, 2); 513 if (li->li_version == 5) { 514 (void) dbg->read(ds->ds_data, &offset, 1); /* TODO */ 515 (void) dbg->read(ds->ds_data, &offset, 1); /* TODO */ 516 } 517 li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size); 518 hdroff = offset; 519 li->li_minlen = dbg->read(ds->ds_data, &offset, 1); 520 if (li->li_version >= 4) 521 li->li_maxop = dbg->read(ds->ds_data, &offset, 1); 522 li->li_defstmt = dbg->read(ds->ds_data, &offset, 1); 523 li->li_lbase = dbg->read(ds->ds_data, &offset, 1); 524 li->li_lrange = dbg->read(ds->ds_data, &offset, 1); 525 li->li_opbase = dbg->read(ds->ds_data, &offset, 1); 526 STAILQ_INIT(&li->li_lflist); 527 STAILQ_INIT(&li->li_lnlist); 528 529 if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) { 530 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 531 DWARF_SET_ERROR(dbg, error, ret); 532 goto fail_cleanup; 533 } 534 535 if ((li->li_oplen = malloc(li->li_opbase)) == NULL) { 536 ret = DW_DLE_MEMORY; 537 DWARF_SET_ERROR(dbg, error, ret); 538 goto fail_cleanup; 539 } 540 541 /* 542 * Read in std opcode arg length list. Note that the first 543 * element is not used. 544 */ 545 for (i = 1; i < li->li_opbase; i++) 546 li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1); 547 548 /* 549 * Directory and filename parser for DWARF4 and below. 550 */ 551 if (li->li_version <= 4) { 552 553 /* 554 * Check how many strings in the include dir string array. 555 */ 556 length = 0; 557 p = ds->ds_data + offset; 558 while (*p != '\0') { 559 while (*p++ != '\0') 560 ; 561 length++; 562 } 563 li->li_inclen = length; 564 565 /* Sanity check. */ 566 if (p - ds->ds_data > (int) ds->ds_size) { 567 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 568 DWARF_SET_ERROR(dbg, error, ret); 569 goto fail_cleanup; 570 } 571 572 if (length != 0) { 573 if ((li->li_incdirs = malloc(length * sizeof(char *))) == 574 NULL) { 575 ret = DW_DLE_MEMORY; 576 DWARF_SET_ERROR(dbg, error, ret); 577 goto fail_cleanup; 578 } 579 } 580 581 /* Fill in include dir array. */ 582 i = 0; 583 p = ds->ds_data + offset; 584 while (*p != '\0') { 585 li->li_incdirs[i++] = (char *) p; 586 while (*p++ != '\0') 587 ; 588 } 589 590 p++; 591 592 /* 593 * Process file list. 594 */ 595 while (*p != '\0') { 596 ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg); 597 if (ret != DW_DLE_NONE) 598 goto fail_cleanup; 599 if (p - ds->ds_data > (int) ds->ds_size) { 600 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 601 DWARF_SET_ERROR(dbg, error, ret); 602 goto fail_cleanup; 603 } 604 } 605 606 p++; 607 608 /* Sanity check. */ 609 if (p - ds->ds_data - hdroff != li->li_hdrlen) { 610 ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; 611 DWARF_SET_ERROR(dbg, error, ret); 612 goto fail_cleanup; 613 } 614 615 goto lnprog; 616 } 617 618 /* 619 * DWARF5 has completely overhauled the dir/source file information 620 * fields, which are incompatible with DWARF4 or lower. 621 */ 622 623 lnct = NULL; 624 fmt = dbg->read(ds->ds_data, &offset, 1); 625 if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data, 626 &offset, error)) != DW_DLE_NONE) 627 goto fail_cleanup; 628 629 li->li_inclen = dbg->read(ds->ds_data, &offset, 1); 630 if (li->li_inclen == 0) { 631 if (fmt > 0) { 632 free(lnct); 633 ret = DW_DLE_DIR_COUNT_BAD; 634 DWARF_SET_ERROR(dbg, error, ret); 635 goto fail_cleanup; 636 } 637 638 goto file_entries; 639 } 640 641 if (fmt == 0) { 642 ret = DW_DLE_DIR_COUNT_BAD; 643 DWARF_SET_ERROR(dbg, error, ret); 644 goto fail_cleanup; 645 } 646 if ((li->li_incdirs = malloc(length * sizeof(char *))) == NULL) { 647 free(lnct); 648 ret = DW_DLE_MEMORY; 649 DWARF_SET_ERROR(dbg, error, ret); 650 goto fail_cleanup; 651 } 652 for (i = 0; i < li->li_inclen; i++) { 653 for (j = 0; j < fmt; j++) { 654 if (lnct[j].type != DW_LNCT_path) { 655 free(lnct); 656 ret = DW_DLE_LNCT_DESC_BAD; 657 DWARF_SET_ERROR(dbg, error, ret); 658 goto fail_cleanup; 659 } 660 661 ret = _dwarf_lineno_lnct_path(dbg, &li->li_incdirs[i], 662 lnct[j].form, ds->ds_data, ds->ds_size, &offset, 663 dwarf_size, error); 664 if (ret != DW_DLE_NONE) { 665 free(lnct); 666 goto fail_cleanup; 667 } 668 } 669 } 670 if (lnct) 671 free(lnct); 672 673 file_entries: 674 675 lnct = NULL; 676 fmt = dbg->read(ds->ds_data, &offset, 1); 677 if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data, 678 &offset, error)) != DW_DLE_NONE) 679 goto fail_cleanup; 680 681 li->li_lflen = dbg->read(ds->ds_data, &offset, 1); 682 if (li->li_lflen == 0) { 683 if (fmt > 0) { 684 free(lnct); 685 ret = DW_DLE_FILE_COUNT_BAD; 686 DWARF_SET_ERROR(dbg, error, ret); 687 goto fail_cleanup; 688 } 689 690 p = ds->ds_data + offset; 691 goto lnprog; 692 } 693 694 for (i = 0; i < li->li_lflen; i++) { 695 if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) { 696 free(lnct); 697 ret = DW_DLE_MEMORY; 698 DWARF_SET_ERROR(dbg, error, ret); 699 goto fail_cleanup; 700 } 701 for (j = 0; j < fmt; j++) { 702 switch (lnct[j].type) { 703 case DW_LNCT_path: 704 ret = _dwarf_lineno_lnct_path(dbg, 705 &lf->lf_fname, lnct[j].form, ds->ds_data, 706 ds->ds_size, &offset, dwarf_size, error); 707 break; 708 case DW_LNCT_directory_index: 709 ret = _dwarf_lineno_lnct_dirndx(dbg, 710 &lf->lf_dirndx, lnct[j].form, ds->ds_data, 711 &offset, error); 712 break; 713 case DW_LNCT_timestamp: 714 ret = _dwarf_lineno_lnct_timestamp(dbg, 715 &lf->lf_mtime, lnct[j].form, ds->ds_data, 716 &offset, error); 717 break; 718 case DW_LNCT_size: 719 ret = _dwarf_lineno_lnct_size(dbg, 720 &lf->lf_size, lnct[j].form, ds->ds_data, 721 &offset, error); 722 break; 723 case DW_LNCT_MD5: 724 ret = _dwarf_lineno_lnct_md5(dbg, 725 &lf->lf_md5, lnct[j].form, ds->ds_data, 726 &offset, error); 727 break; 728 default: 729 ret = DW_DLE_LNCT_DESC_BAD; 730 DWARF_SET_ERROR(dbg, error, ret); 731 break; 732 } 733 if (ret != DW_DLE_NONE) { 734 free(lf); 735 free(lnct); 736 goto fail_cleanup; 737 } 738 } 739 ret = _dwarf_lineno_make_fullpath(dbg, li, lf, compdir, error); 740 if (ret != DW_DLE_NONE) { 741 free(lf); 742 free(lnct); 743 goto fail_cleanup; 744 } 745 STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next); 746 } 747 if (lnct) 748 free(lnct); 749 750 p = ds->ds_data + offset; 751 752 lnprog: 753 /* 754 * Process line number program. 755 */ 756 ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir, 757 error); 758 if (ret != DW_DLE_NONE) 759 goto fail_cleanup; 760 761 cu->cu_lineinfo = li; 762 763 return (DW_DLE_NONE); 764 765 fail_cleanup: 766 767 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 768 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next); 769 if (lf->lf_fullpath) 770 free(lf->lf_fullpath); 771 free(lf); 772 } 773 774 if (li->li_oplen) 775 free(li->li_oplen); 776 if (li->li_incdirs) 777 free(li->li_incdirs); 778 free(li); 779 780 return (ret); 781 } 782 783 void 784 _dwarf_lineno_cleanup(Dwarf_LineInfo li) 785 { 786 Dwarf_LineFile lf, tlf; 787 Dwarf_Line ln, tln; 788 789 if (li == NULL) 790 return; 791 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 792 STAILQ_REMOVE(&li->li_lflist, lf, 793 _Dwarf_LineFile, lf_next); 794 if (lf->lf_fullpath) 795 free(lf->lf_fullpath); 796 free(lf); 797 } 798 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 799 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, 800 ln_next); 801 free(ln); 802 } 803 if (li->li_oplen) 804 free(li->li_oplen); 805 if (li->li_incdirs) 806 free(li->li_incdirs); 807 if (li->li_lnarray) 808 free(li->li_lnarray); 809 if (li->li_lfnarray) 810 free(li->li_lfnarray); 811 free(li); 812 } 813 814 static int 815 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds, 816 Dwarf_Rel_Section drs, Dwarf_Error * error) 817 { 818 Dwarf_LineInfo li; 819 Dwarf_Line ln; 820 Dwarf_Unsigned address, file, line, spc; 821 Dwarf_Unsigned addr0, maddr; 822 Dwarf_Signed line0, column; 823 int is_stmt, basic_block; 824 int need_copy; 825 int ret; 826 827 #define RESET_REGISTERS \ 828 do { \ 829 address = 0; \ 830 file = 1; \ 831 line = 1; \ 832 column = 0; \ 833 is_stmt = li->li_defstmt; \ 834 basic_block = 0; \ 835 } while(0) 836 837 li = dbg->dbgp_lineinfo; 838 maddr = (255 - li->li_opbase) / li->li_lrange; 839 840 RESET_REGISTERS; 841 842 STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) { 843 if (ln->ln_symndx > 0) { 844 /* 845 * Generate DW_LNE_set_address extended op. 846 */ 847 RCHECK(WRITE_VALUE(0, 1)); 848 RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1)); 849 RCHECK(WRITE_VALUE(DW_LNE_set_address, 1)); 850 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, 851 dwarf_drt_data_reloc, dbg->dbg_pointer_size, 852 ds->ds_size, ln->ln_symndx, ln->ln_addr, 853 NULL, error)); 854 address = ln->ln_addr; 855 continue; 856 } else if (ln->ln_endseq) { 857 addr0 = (ln->ln_addr - address) / li->li_minlen; 858 if (addr0 != 0) { 859 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); 860 RCHECK(WRITE_ULEB128(addr0)); 861 } 862 863 /* 864 * Generate DW_LNE_end_sequence. 865 */ 866 RCHECK(WRITE_VALUE(0, 1)); 867 RCHECK(WRITE_ULEB128(1)); 868 RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1)); 869 RESET_REGISTERS; 870 continue; 871 } 872 873 /* 874 * Generate standard opcodes for file, column, is_stmt or 875 * basic_block changes. 876 */ 877 if (ln->ln_fileno != file) { 878 RCHECK(WRITE_VALUE(DW_LNS_set_file, 1)); 879 RCHECK(WRITE_ULEB128(ln->ln_fileno)); 880 file = ln->ln_fileno; 881 } 882 if (ln->ln_column != column) { 883 RCHECK(WRITE_VALUE(DW_LNS_set_column, 1)); 884 RCHECK(WRITE_ULEB128(ln->ln_column)); 885 column = ln->ln_column; 886 } 887 if (ln->ln_stmt != is_stmt) { 888 RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1)); 889 is_stmt = ln->ln_stmt; 890 } 891 if (ln->ln_bblock && !basic_block) { 892 RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1)); 893 basic_block = 1; 894 } 895 896 /* 897 * Calculate address and line number change. 898 */ 899 addr0 = (ln->ln_addr - address) / li->li_minlen; 900 line0 = ln->ln_lineno - line; 901 902 if (addr0 == 0 && line0 == 0) 903 continue; 904 905 /* 906 * Check if line delta is with the range and if the special 907 * opcode can be used. 908 */ 909 assert(li->li_lbase <= 0); 910 if (line0 >= li->li_lbase && 911 line0 <= li->li_lbase + li->li_lrange - 1) { 912 spc = (line0 - li->li_lbase) + 913 (li->li_lrange * addr0) + li->li_opbase; 914 if (spc <= 255) { 915 RCHECK(WRITE_VALUE(spc, 1)); 916 basic_block = 0; 917 goto next_line; 918 } 919 } 920 921 /* Generate DW_LNS_advance_line for line number change. */ 922 if (line0 != 0) { 923 RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1)); 924 RCHECK(WRITE_SLEB128(line0)); 925 line0 = 0; 926 need_copy = 1; 927 } else 928 need_copy = basic_block; 929 930 if (addr0 != 0) { 931 /* See if it can be handled by DW_LNS_const_add_pc. */ 932 spc = (line0 - li->li_lbase) + 933 (li->li_lrange * (addr0 - maddr)) + li->li_opbase; 934 if (addr0 >= maddr && spc <= 255) { 935 RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1)); 936 RCHECK(WRITE_VALUE(spc, 1)); 937 } else { 938 /* Otherwise we use DW_LNS_advance_pc. */ 939 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); 940 RCHECK(WRITE_ULEB128(addr0)); 941 } 942 } 943 944 if (need_copy) { 945 RCHECK(WRITE_VALUE(DW_LNS_copy, 1)); 946 basic_block = 0; 947 } 948 949 next_line: 950 address = ln->ln_addr; 951 line = ln->ln_lineno; 952 } 953 954 return (DW_DLE_NONE); 955 956 gen_fail: 957 return (ret); 958 959 #undef RESET_REGISTERS 960 } 961 962 static uint8_t 963 _dwarf_get_minlen(Dwarf_P_Debug dbg) 964 { 965 966 assert(dbg != NULL); 967 968 switch (dbg->dbgp_isa) { 969 case DW_ISA_ARM: 970 return (2); 971 case DW_ISA_X86: 972 case DW_ISA_X86_64: 973 return (1); 974 default: 975 return (4); 976 } 977 } 978 979 static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1}; 980 981 int 982 _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 983 { 984 Dwarf_LineInfo li; 985 Dwarf_LineFile lf; 986 Dwarf_P_Section ds; 987 Dwarf_Rel_Section drs; 988 Dwarf_Unsigned offset; 989 int i, ret; 990 991 assert(dbg != NULL && dbg->dbgp_lineinfo != NULL); 992 993 li = dbg->dbgp_lineinfo; 994 if (STAILQ_EMPTY(&li->li_lnlist)) 995 return (DW_DLE_NONE); 996 997 li->li_length = 0; 998 li->li_version = 2; 999 li->li_hdrlen = 0; 1000 li->li_minlen = _dwarf_get_minlen(dbg); 1001 li->li_defstmt = 1; 1002 li->li_lbase = -5; 1003 li->li_lrange = 14; 1004 li->li_opbase = 10; 1005 1006 /* Create .debug_line section. */ 1007 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) != 1008 DW_DLE_NONE) 1009 return (ret); 1010 1011 /* Create relocation section for .debug_line */ 1012 if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) != 1013 DW_DLE_NONE) 1014 goto gen_fail1; 1015 1016 /* Length placeholder. (We only use 32-bit DWARF format) */ 1017 RCHECK(WRITE_VALUE(0, 4)); 1018 1019 /* Write line number dwarf version. (DWARF2) */ 1020 RCHECK(WRITE_VALUE(li->li_version, 2)); 1021 1022 /* Header length placeholder. */ 1023 offset = ds->ds_size; 1024 RCHECK(WRITE_VALUE(li->li_hdrlen, 4)); 1025 1026 /* Write minimum instruction length. */ 1027 RCHECK(WRITE_VALUE(li->li_minlen, 1)); 1028 1029 /* 1030 * Write initial value for is_stmt. XXX Which default value we 1031 * should use? 1032 */ 1033 RCHECK(WRITE_VALUE(li->li_defstmt, 1)); 1034 1035 /* 1036 * Write line_base and line_range. FIXME These value needs to be 1037 * fine tuned. 1038 */ 1039 RCHECK(WRITE_VALUE(li->li_lbase, 1)); 1040 RCHECK(WRITE_VALUE(li->li_lrange, 1)); 1041 1042 /* Write opcode_base. (DWARF2) */ 1043 RCHECK(WRITE_VALUE(li->li_opbase, 1)); 1044 1045 /* Write standard op length array. */ 1046 RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0]))); 1047 1048 /* Write the list of include directories. */ 1049 for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) 1050 RCHECK(WRITE_STRING(li->li_incdirs[i])); 1051 RCHECK(WRITE_VALUE(0, 1)); 1052 1053 /* Write the list of filenames. */ 1054 STAILQ_FOREACH(lf, &li->li_lflist, lf_next) { 1055 RCHECK(WRITE_STRING(lf->lf_fname)); 1056 RCHECK(WRITE_ULEB128(lf->lf_dirndx)); 1057 RCHECK(WRITE_ULEB128(lf->lf_mtime)); 1058 RCHECK(WRITE_ULEB128(lf->lf_size)); 1059 } 1060 RCHECK(WRITE_VALUE(0, 1)); 1061 1062 /* Fill in the header length. */ 1063 li->li_hdrlen = ds->ds_size - offset - 4; 1064 dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4); 1065 1066 /* Generate the line number program. */ 1067 RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error)); 1068 1069 /* Fill in the length of this line info. */ 1070 li->li_length = ds->ds_size - 4; 1071 offset = 0; 1072 dbg->write(ds->ds_data, &offset, li->li_length, 4); 1073 1074 /* Notify the creation of .debug_line ELF section. */ 1075 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 1076 1077 /* Finalize relocation section for .debug_line. */ 1078 RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 1079 1080 return (DW_DLE_NONE); 1081 1082 gen_fail: 1083 _dwarf_reloc_section_free(dbg, &drs); 1084 1085 gen_fail1: 1086 _dwarf_section_free(dbg, &ds); 1087 1088 return (ret); 1089 } 1090 1091 void 1092 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg) 1093 { 1094 Dwarf_LineInfo li; 1095 Dwarf_LineFile lf, tlf; 1096 Dwarf_Line ln, tln; 1097 int i; 1098 1099 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 1100 if (dbg->dbgp_lineinfo == NULL) 1101 return; 1102 1103 li = dbg->dbgp_lineinfo; 1104 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { 1105 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, 1106 lf_next); 1107 if (lf->lf_fname) 1108 free(lf->lf_fname); 1109 free(lf); 1110 } 1111 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { 1112 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); 1113 free(ln); 1114 } 1115 if (li->li_incdirs) { 1116 for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) 1117 free(li->li_incdirs[i]); 1118 free(li->li_incdirs); 1119 } 1120 free(li); 1121 dbg->dbgp_lineinfo = NULL; 1122 } 1123