2 * Copyright (c) 2009,2010 Kai Wang
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include "_libdwarf.h"
29 ELFTC_VCSID("$Id: libdwarf_lineno.c 3164 2015-02-19 01:20:12Z kaiwang27 $");
32 _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir,
33 Dwarf_Error *error, Dwarf_Debug dbg)
43 if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
44 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
45 return (DW_DLE_MEMORY);
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) {
54 DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD);
55 return (DW_DLE_DIR_INDEX_BAD);
58 /* Make a full pathname if needed. */
59 if (*lf->lf_fname != '/') {
60 filepath = open_memstream(&lf->lf_fullpath, &slen);
61 if (filepath == NULL) {
63 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
64 return (DW_DLE_MEMORY);
67 if (lf->lf_dirndx > 0)
68 incdir = li->li_incdirs[lf->lf_dirndx - 1];
73 * Prepend the compilation directory if the directory table
76 if (incdir == NULL || *incdir != '/')
77 fprintf(filepath, "%s/", compdir);
79 fprintf(filepath, "%s/", incdir);
80 fprintf(filepath, "%s", lf->lf_fname);
81 if (fclose(filepath) != 0) {
83 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
84 return (DW_DLE_MEMORY);
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);
99 _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p,
100 uint8_t *pe, const char *compdir, Dwarf_Error *error)
104 uint64_t address, file, line, column, opsize;
105 int is_stmt, basic_block, end_sequence;
108 #define RESET_REGISTERS \
114 is_stmt = li->li_defstmt; \
121 ln = malloc(sizeof(struct _Dwarf_Line)); \
123 ret = DW_DLE_MEMORY; \
124 DWARF_SET_ERROR(dbg, error, ret); \
128 ln->ln_addr = address; \
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);\
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)
146 * Set registers to their default values.
151 * Start line number program.
161 opsize = _dwarf_decode_uleb128(&p);
163 case DW_LNE_end_sequence:
169 case DW_LNE_set_address:
171 address = dbg->decode(&p, cu->cu_pointer_size);
173 case DW_LNE_define_file:
175 ret = _dwarf_lineno_add_file(li, &p, compdir,
177 if (ret != DW_DLE_NONE)
181 /* Unrecognized extened opcodes. */
185 } else if (*p > 0 && *p < li->li_opbase) {
196 case DW_LNS_advance_pc:
197 address += _dwarf_decode_uleb128(&p) *
200 case DW_LNS_advance_line:
201 line += _dwarf_decode_sleb128(&p);
203 case DW_LNS_set_file:
204 file = _dwarf_decode_uleb128(&p);
206 case DW_LNS_set_column:
207 column = _dwarf_decode_uleb128(&p);
209 case DW_LNS_negate_stmt:
212 case DW_LNS_set_basic_block:
215 case DW_LNS_const_add_pc:
216 address += ADDRESS(255);
218 case DW_LNS_fixed_advance_pc:
219 address += dbg->decode(&p, 2);
221 case DW_LNS_set_prologue_end:
223 case DW_LNS_set_epilogue_begin:
226 (void) _dwarf_decode_uleb128(&p);
229 /* Unrecognized extened opcodes. What to do? */
240 address += ADDRESS(*p);
247 return (DW_DLE_NONE);
251 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
252 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
258 #undef RESET_REGISTERS
265 _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error)
272 Dwarf_LineFile lf, tlf;
274 uint64_t length, hdroff, endoff;
276 int dwarf_size, i, ret;
284 if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL)
285 return (DW_DLE_NONE);
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.
292 at = _dwarf_attr_find(die, DW_AT_comp_dir);
294 switch (at->at_form) {
296 compdir = at->u[1].s;
299 compdir = at->u[0].s;
306 length = dbg->read(ds->ds_data, &offset, 4);
307 if (length == 0xffffffff) {
309 length = dbg->read(ds->ds_data, &offset, 8);
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);
318 if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) {
319 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
320 return (DW_DLE_MEMORY);
324 * Read in line number program header.
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);
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);
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);
347 if ((li->li_oplen = malloc(li->li_opbase)) == NULL) {
349 DWARF_SET_ERROR(dbg, error, ret);
354 * Read in std opcode arg length list. Note that the first
355 * element is not used.
357 for (i = 1; i < li->li_opbase; i++)
358 li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1);
361 * Check how many strings in the include dir string array.
364 p = ds->ds_data + offset;
370 li->li_inclen = length;
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);
380 if ((li->li_incdirs = malloc(length * sizeof(char *))) ==
383 DWARF_SET_ERROR(dbg, error, ret);
388 /* Fill in include dir array. */
390 p = ds->ds_data + offset;
392 li->li_incdirs[i++] = (char *) p;
403 ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg);
404 if (ret != DW_DLE_NONE)
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);
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);
423 * Process line number program.
425 ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir,
427 if (ret != DW_DLE_NONE)
430 cu->cu_lineinfo = li;
432 return (DW_DLE_NONE);
436 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
437 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next);
439 free(lf->lf_fullpath);
446 free(li->li_incdirs);
453 _dwarf_lineno_cleanup(Dwarf_LineInfo li)
455 Dwarf_LineFile lf, tlf;
460 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
461 STAILQ_REMOVE(&li->li_lflist, lf,
462 _Dwarf_LineFile, lf_next);
464 free(lf->lf_fullpath);
467 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
468 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line,
475 free(li->li_incdirs);
477 free(li->li_lnarray);
479 free(li->li_lfnarray);
484 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
485 Dwarf_Rel_Section drs, Dwarf_Error * error)
489 Dwarf_Unsigned address, file, line, spc;
490 Dwarf_Unsigned addr0, maddr;
491 Dwarf_Signed line0, column;
492 int is_stmt, basic_block;
496 #define RESET_REGISTERS \
502 is_stmt = li->li_defstmt; \
506 li = dbg->dbgp_lineinfo;
507 maddr = (255 - li->li_opbase) / li->li_lrange;
511 STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) {
512 if (ln->ln_symndx > 0) {
514 * Generate DW_LNE_set_address extended op.
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,
523 address = ln->ln_addr;
525 } else if (ln->ln_endseq) {
526 addr0 = (ln->ln_addr - address) / li->li_minlen;
528 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
529 RCHECK(WRITE_ULEB128(addr0));
533 * Generate DW_LNE_end_sequence.
535 RCHECK(WRITE_VALUE(0, 1));
536 RCHECK(WRITE_ULEB128(1));
537 RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1));
543 * Generate standard opcodes for file, column, is_stmt or
544 * basic_block changes.
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;
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;
556 if (ln->ln_stmt != is_stmt) {
557 RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1));
558 is_stmt = ln->ln_stmt;
560 if (ln->ln_bblock && !basic_block) {
561 RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1));
566 * Calculate address and line number change.
568 addr0 = (ln->ln_addr - address) / li->li_minlen;
569 line0 = ln->ln_lineno - line;
571 if (addr0 == 0 && line0 == 0)
575 * Check if line delta is with the range and if the special
576 * opcode can be used.
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;
584 RCHECK(WRITE_VALUE(spc, 1));
590 /* Generate DW_LNS_advance_line for line number change. */
592 RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1));
593 RCHECK(WRITE_SLEB128(line0));
597 need_copy = basic_block;
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));
607 /* Otherwise we use DW_LNS_advance_pc. */
608 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
609 RCHECK(WRITE_ULEB128(addr0));
614 RCHECK(WRITE_VALUE(DW_LNS_copy, 1));
619 address = ln->ln_addr;
620 line = ln->ln_lineno;
623 return (DW_DLE_NONE);
628 #undef RESET_REGISTERS
632 _dwarf_get_minlen(Dwarf_P_Debug dbg)
637 switch (dbg->dbgp_isa) {
648 static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
651 _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
656 Dwarf_Rel_Section drs;
657 Dwarf_Unsigned offset;
660 assert(dbg != NULL && dbg->dbgp_lineinfo != NULL);
662 li = dbg->dbgp_lineinfo;
663 if (STAILQ_EMPTY(&li->li_lnlist))
664 return (DW_DLE_NONE);
669 li->li_minlen = _dwarf_get_minlen(dbg);
675 /* Create .debug_line section. */
676 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) !=
680 /* Create relocation section for .debug_line */
681 if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) !=
685 /* Length placeholder. (We only use 32-bit DWARF format) */
686 RCHECK(WRITE_VALUE(0, 4));
688 /* Write line number dwarf version. (DWARF2) */
689 RCHECK(WRITE_VALUE(li->li_version, 2));
691 /* Header length placeholder. */
692 offset = ds->ds_size;
693 RCHECK(WRITE_VALUE(li->li_hdrlen, 4));
695 /* Write minimum instruction length. */
696 RCHECK(WRITE_VALUE(li->li_minlen, 1));
699 * Write initial value for is_stmt. XXX Which default value we
702 RCHECK(WRITE_VALUE(li->li_defstmt, 1));
705 * Write line_base and line_range. FIXME These value needs to be
708 RCHECK(WRITE_VALUE(li->li_lbase, 1));
709 RCHECK(WRITE_VALUE(li->li_lrange, 1));
711 /* Write opcode_base. (DWARF2) */
712 RCHECK(WRITE_VALUE(li->li_opbase, 1));
714 /* Write standard op length array. */
715 RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0])));
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));
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));
729 RCHECK(WRITE_VALUE(0, 1));
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);
735 /* Generate the line number program. */
736 RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error));
738 /* Fill in the length of this line info. */
739 li->li_length = ds->ds_size - 4;
741 dbg->write(ds->ds_data, &offset, li->li_length, 4);
743 /* Notify the creation of .debug_line ELF section. */
744 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
746 /* Finalize relocation section for .debug_line. */
747 RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
749 return (DW_DLE_NONE);
752 _dwarf_reloc_section_free(dbg, &drs);
755 _dwarf_section_free(dbg, &ds);
761 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)
764 Dwarf_LineFile lf, tlf;
768 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
769 if (dbg->dbgp_lineinfo == NULL)
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,
780 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
781 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
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);
790 dbg->dbgp_lineinfo = NULL;