1 /* $NetBSD: libdwarf_lineno.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2009,2010 Kai Wang
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
29 #include "_libdwarf.h"
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 ");
35 _dwarf_lineno_add_file(Dwarf_LineInfo li
, uint8_t **p
, const char *compdir
,
36 Dwarf_Error
*error
, Dwarf_Debug dbg
)
45 if ((lf
= malloc(sizeof(struct _Dwarf_LineFile
))) == NULL
) {
46 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
47 return (DW_DLE_MEMORY
);
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
) {
56 DWARF_SET_ERROR(dbg
, error
, DW_DLE_DIR_INDEX_BAD
);
57 return (DW_DLE_DIR_INDEX_BAD
);
60 /* Make full pathname if need. */
61 if (*lf
->lf_fname
!= '/') {
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
) {
69 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
70 return (DW_DLE_MEMORY
);
72 snprintf(lf
->lf_fullpath
, slen
, "%s/%s", dirname
,
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
);
88 _dwarf_lineno_run_program(Dwarf_CU cu
, Dwarf_LineInfo li
, uint8_t *p
,
89 uint8_t *pe
, const char *compdir
, Dwarf_Error
*error
)
93 uint64_t address
, file
, line
, column
, isa
, opsize
;
94 int is_stmt
, basic_block
, end_sequence
;
95 int prologue_end
, epilogue_begin
;
98 #define RESET_REGISTERS \
104 is_stmt = li->li_defstmt; \
108 epilogue_begin = 0; \
113 ln = malloc(sizeof(struct _Dwarf_Line)); \
115 ret = DW_DLE_MEMORY; \
116 DWARF_SET_ERROR(dbg, error, ret); \
120 ln->ln_addr = address; \
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);\
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)
138 * Set registers to their default values.
143 * Start line number program.
153 opsize
= _dwarf_decode_uleb128(&p
);
155 case DW_LNE_end_sequence
:
161 case DW_LNE_set_address
:
163 address
= dbg
->decode(&p
, cu
->cu_pointer_size
);
165 case DW_LNE_define_file
:
167 ret
= _dwarf_lineno_add_file(li
, &p
, compdir
,
169 if (ret
!= DW_DLE_NONE
)
173 /* Unrecognized extened opcodes. */
177 } else if (*p
> 0 && *p
< li
->li_opbase
) {
190 case DW_LNS_advance_pc
:
191 address
+= _dwarf_decode_uleb128(&p
) *
194 case DW_LNS_advance_line
:
195 line
+= _dwarf_decode_sleb128(&p
);
197 case DW_LNS_set_file
:
198 file
= _dwarf_decode_uleb128(&p
);
200 case DW_LNS_set_column
:
201 column
= _dwarf_decode_uleb128(&p
);
203 case DW_LNS_negate_stmt
:
206 case DW_LNS_set_basic_block
:
209 case DW_LNS_const_add_pc
:
210 address
+= ADDRESS(255);
212 case DW_LNS_fixed_advance_pc
:
213 address
+= dbg
->decode(&p
, 2);
215 case DW_LNS_set_prologue_end
:
218 case DW_LNS_set_epilogue_begin
:
222 isa
= _dwarf_decode_uleb128(&p
);
225 /* Unrecognized extened opcodes. What to do? */
236 address
+= ADDRESS(*p
);
245 return (DW_DLE_NONE
);
249 STAILQ_FOREACH_SAFE(ln
, &li
->li_lnlist
, ln_next
, tln
) {
250 STAILQ_REMOVE(&li
->li_lnlist
, ln
, _Dwarf_Line
, ln_next
);
256 #undef RESET_REGISTERS
263 _dwarf_lineno_init(Dwarf_Die die
, uint64_t offset
, Dwarf_Error
*error
)
270 Dwarf_LineFile lf
, tlf
;
272 uint64_t length
, hdroff
, endoff
;
274 int dwarf_size
, i
, ret
;
282 if ((ds
= _dwarf_find_section(dbg
, ".debug_line")) == NULL
)
283 return (DW_DLE_NONE
);
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.
290 at
= _dwarf_attr_find(die
, DW_AT_comp_dir
);
292 switch (at
->at_form
) {
294 compdir
= at
->u
[1].s
;
297 compdir
= at
->u
[0].s
;
304 length
= dbg
->read(ds
->ds_data
, &offset
, 4);
305 if (length
== 0xffffffff) {
307 length
= dbg
->read(ds
->ds_data
, &offset
, 8);
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
);
316 if ((li
= calloc(1, sizeof(struct _Dwarf_LineInfo
))) == NULL
) {
317 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
318 return (DW_DLE_MEMORY
);
322 * Read in line number program header.
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
);
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
);
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
);
343 if ((li
->li_oplen
= malloc(li
->li_opbase
)) == NULL
) {
345 DWARF_SET_ERROR(dbg
, error
, ret
);
350 * Read in std opcode arg length list. Note that the first
351 * element is not used.
353 for (i
= 1; i
< li
->li_opbase
; i
++)
354 li
->li_oplen
[i
] = dbg
->read(ds
->ds_data
, &offset
, 1);
357 * Check how many strings in the include dir string array.
360 p
= ds
->ds_data
+ offset
;
366 li
->li_inclen
= length
;
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
);
376 if ((li
->li_incdirs
= malloc(length
* sizeof(char *))) ==
379 DWARF_SET_ERROR(dbg
, error
, ret
);
384 /* Fill in include dir array. */
386 p
= ds
->ds_data
+ offset
;
388 li
->li_incdirs
[i
++] = (char *) p
;
399 ret
= _dwarf_lineno_add_file(li
, &p
, compdir
, error
, dbg
);
400 if (ret
!= DW_DLE_NONE
)
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
);
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
);
419 * Process line number program.
421 ret
= _dwarf_lineno_run_program(cu
, li
, p
, ds
->ds_data
+ endoff
, compdir
,
423 if (ret
!= DW_DLE_NONE
)
426 cu
->cu_lineinfo
= li
;
428 return (DW_DLE_NONE
);
432 STAILQ_FOREACH_SAFE(lf
, &li
->li_lflist
, lf_next
, tlf
) {
433 STAILQ_REMOVE(&li
->li_lflist
, lf
, _Dwarf_LineFile
, lf_next
);
435 free(lf
->lf_fullpath
);
442 free(li
->li_incdirs
);
449 _dwarf_lineno_cleanup(Dwarf_LineInfo li
)
451 Dwarf_LineFile lf
, tlf
;
456 STAILQ_FOREACH_SAFE(lf
, &li
->li_lflist
, lf_next
, tlf
) {
457 STAILQ_REMOVE(&li
->li_lflist
, lf
,
458 _Dwarf_LineFile
, lf_next
);
460 free(lf
->lf_fullpath
);
463 STAILQ_FOREACH_SAFE(ln
, &li
->li_lnlist
, ln_next
, tln
) {
464 STAILQ_REMOVE(&li
->li_lnlist
, ln
, _Dwarf_Line
,
471 free(li
->li_incdirs
);
473 free(li
->li_lnarray
);
475 free(li
->li_lfnarray
);
480 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg
, Dwarf_P_Section ds
,
481 Dwarf_Rel_Section drs
, Dwarf_Error
* error
)
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
;
492 #define RESET_REGISTERS \
498 is_stmt = li->li_defstmt; \
503 li
= dbg
->dbgp_lineinfo
;
504 maddr
= (255 - li
->li_opbase
) / li
->li_lrange
;
508 STAILQ_FOREACH(ln
, &li
->li_lnlist
, ln_next
) {
509 if (ln
->ln_symndx
> 0) {
511 * Generate DW_LNE_set_address extended op.
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
,
520 address
= ln
->ln_addr
;
522 } else if (ln
->ln_endseq
) {
523 addr0
= (ln
->ln_addr
- address
) / li
->li_minlen
;
525 RCHECK(WRITE_VALUE(DW_LNS_advance_pc
, 1));
526 RCHECK(WRITE_ULEB128(addr0
));
530 * Generate DW_LNE_end_sequence.
532 RCHECK(WRITE_VALUE(0, 1));
533 RCHECK(WRITE_ULEB128(1));
534 RCHECK(WRITE_VALUE(DW_LNE_end_sequence
, 1));
540 * Generate standard opcodes for file, column, is_stmt or
541 * basic_block changes.
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
;
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
;
553 if (ln
->ln_stmt
!= is_stmt
) {
554 RCHECK(WRITE_VALUE(DW_LNS_negate_stmt
, 1));
555 is_stmt
= ln
->ln_stmt
;
557 if (ln
->ln_bblock
&& !basic_block
) {
558 RCHECK(WRITE_VALUE(DW_LNS_set_basic_block
, 1));
563 * Calculate address and line number change.
565 addr0
= (ln
->ln_addr
- address
) / li
->li_minlen
;
566 line0
= ln
->ln_lineno
- line
;
568 if (addr0
== 0 && line0
== 0)
572 * Check if line delta is with the range and if the special
573 * opcode can be used.
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
;
581 RCHECK(WRITE_VALUE(spc
, 1));
587 /* Generate DW_LNS_advance_line for line number change. */
589 RCHECK(WRITE_VALUE(DW_LNS_advance_line
, 1));
590 RCHECK(WRITE_SLEB128(line0
));
594 need_copy
= basic_block
;
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));
604 /* Otherwise we use DW_LNS_advance_pc. */
605 RCHECK(WRITE_VALUE(DW_LNS_advance_pc
, 1));
606 RCHECK(WRITE_ULEB128(addr0
));
611 RCHECK(WRITE_VALUE(DW_LNS_copy
, 1));
616 address
= ln
->ln_addr
;
617 line
= ln
->ln_lineno
;
620 return (DW_DLE_NONE
);
625 #undef RESET_REGISTERS
629 _dwarf_get_minlen(Dwarf_P_Debug dbg
)
634 switch (dbg
->dbgp_isa
) {
645 static uint8_t oplen
[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
648 _dwarf_lineno_gen(Dwarf_P_Debug dbg
, Dwarf_Error
*error
)
653 Dwarf_Rel_Section drs
;
654 Dwarf_Unsigned offset
;
657 assert(dbg
!= NULL
&& dbg
->dbgp_lineinfo
!= NULL
);
659 li
= dbg
->dbgp_lineinfo
;
660 if (STAILQ_EMPTY(&li
->li_lnlist
))
661 return (DW_DLE_NONE
);
666 li
->li_minlen
= _dwarf_get_minlen(dbg
);
672 /* Create .debug_line section. */
673 if ((ret
= _dwarf_section_init(dbg
, &ds
, ".debug_line", 0, error
)) !=
677 /* Create relocation section for .debug_line */
678 if ((ret
= _dwarf_reloc_section_init(dbg
, &drs
, ds
, error
)) !=
682 /* Length placeholder. (We only use 32-bit DWARF format) */
683 RCHECK(WRITE_VALUE(0, 4));
685 /* Write line number dwarf version. (DWARF2) */
686 RCHECK(WRITE_VALUE(li
->li_version
, 2));
688 /* Header length placeholder. */
689 offset
= ds
->ds_size
;
690 RCHECK(WRITE_VALUE(li
->li_hdrlen
, 4));
692 /* Write minimum instruction length. */
693 RCHECK(WRITE_VALUE(li
->li_minlen
, 1));
696 * Write initial value for is_stmt. XXX Which default value we
699 RCHECK(WRITE_VALUE(li
->li_defstmt
, 1));
702 * Write line_base and line_range. FIXME These value needs to be
705 RCHECK(WRITE_VALUE(li
->li_lbase
, 1));
706 RCHECK(WRITE_VALUE(li
->li_lrange
, 1));
708 /* Write opcode_base. (DWARF2) */
709 RCHECK(WRITE_VALUE(li
->li_opbase
, 1));
711 /* Write standard op length array. */
712 RCHECK(WRITE_BLOCK(oplen
, sizeof(oplen
) / sizeof(oplen
[0])));
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));
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
));
726 RCHECK(WRITE_VALUE(0, 1));
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);
732 /* Generate the line number program. */
733 RCHECK(_dwarf_lineno_gen_program(dbg
, ds
, drs
, error
));
735 /* Fill in the length of this line info. */
736 li
->li_length
= ds
->ds_size
- 4;
738 dbg
->write(ds
->ds_data
, &offset
, li
->li_length
, 4);
740 /* Notify the creation of .debug_line ELF section. */
741 RCHECK(_dwarf_section_callback(dbg
, ds
, SHT_PROGBITS
, 0, 0, 0, error
));
743 /* Finalize relocation section for .debug_line. */
744 RCHECK(_dwarf_reloc_section_finalize(dbg
, drs
, error
));
746 return (DW_DLE_NONE
);
749 _dwarf_reloc_section_free(dbg
, &drs
);
752 _dwarf_section_free(dbg
, &ds
);
758 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg
)
761 Dwarf_LineFile lf
, tlf
;
765 assert(dbg
!= NULL
&& dbg
->dbg_mode
== DW_DLC_WRITE
);
766 if (dbg
->dbgp_lineinfo
== NULL
)
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
,
777 STAILQ_FOREACH_SAFE(ln
, &li
->li_lnlist
, ln_next
, tln
) {
778 STAILQ_REMOVE(&li
->li_lnlist
, ln
, _Dwarf_Line
, ln_next
);
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
);
787 dbg
->dbgp_lineinfo
= NULL
;