Remove building with NOCRYPTO option
[minix3.git] / external / bsd / elftoolchain / dist / libdwarf / libdwarf_lineno.c
blobb6397b826a7c02bdc1da6cc6e21f2e746663b417
1 /* $NetBSD: libdwarf_lineno.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
3 /*-
4 * Copyright (c) 2009,2010 Kai Wang
5 * All rights reserved.
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.
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.
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 ");
34 static int
35 _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir,
36 Dwarf_Error *error, Dwarf_Debug dbg)
38 Dwarf_LineFile lf;
39 const char *dirname;
40 uint8_t *src;
41 int slen;
43 src = *p;
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) {
55 free(lf);
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 != '/') {
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);
72 snprintf(lf->lf_fullpath, slen, "%s/%s", dirname,
73 lf->lf_fname);
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++;
82 *p = src;
84 return (DW_DLE_NONE);
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)
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;
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)
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; \
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)
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)
135 dbg = cu->cu_dbg;
138 * Set registers to their default values.
140 RESET_REGISTERS;
143 * Start line number program.
145 while (p < pe) {
146 if (*p == 0) {
149 * Extended Opcodes.
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;
177 } else if (*p > 0 && *p < li->li_opbase) {
180 * Standard Opcodes.
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;
229 } else {
232 * Special Opcodes.
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++;
245 return (DW_DLE_NONE);
247 prog_fail:
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);
254 return (ret);
256 #undef RESET_REGISTERS
257 #undef APPEND_ROW
258 #undef LINE
259 #undef ADDRESS
263 _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error)
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;
276 cu = die->die_cu;
277 assert(cu != NULL);
279 dbg = cu->cu_dbg;
280 assert(dbg != NULL);
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.
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;
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;
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);
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);
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;
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;
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.
359 length = 0;
360 p = ds->ds_data + offset;
361 while (*p != '\0') {
362 while (*p++ != '\0')
364 length++;
366 li->li_inclen = length;
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;
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;
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')
393 p++;
396 * Process file list.
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;
409 p++;
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;
419 * Process line number program.
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;
426 cu->cu_lineinfo = li;
428 return (DW_DLE_NONE);
430 fail_cleanup:
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);
439 if (li->li_oplen)
440 free(li->li_oplen);
441 if (li->li_incdirs)
442 free(li->li_incdirs);
443 free(li);
445 return (ret);
448 void
449 _dwarf_lineno_cleanup(Dwarf_LineInfo li)
451 Dwarf_LineFile lf, tlf;
452 Dwarf_Line ln, tln;
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);
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);
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);
479 static int
480 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
481 Dwarf_Rel_Section drs, Dwarf_Error * error)
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;
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)
503 li = dbg->dbgp_lineinfo;
504 maddr = (255 - li->li_opbase) / li->li_lrange;
506 RESET_REGISTERS;
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,
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));
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));
535 RESET_REGISTERS;
536 continue;
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));
559 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)
569 continue;
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;
580 if (spc <= 255) {
581 RCHECK(WRITE_VALUE(spc, 1));
582 basic_block = 0;
583 goto next_line;
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;
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));
610 if (need_copy) {
611 RCHECK(WRITE_VALUE(DW_LNS_copy, 1));
612 basic_block = 0;
615 next_line:
616 address = ln->ln_addr;
617 line = ln->ln_lineno;
620 return (DW_DLE_NONE);
622 gen_fail:
623 return (ret);
625 #undef RESET_REGISTERS
628 static uint8_t
629 _dwarf_get_minlen(Dwarf_P_Debug dbg)
632 assert(dbg != NULL);
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);
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)
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;
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);
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;
672 /* Create .debug_line section. */
673 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) !=
674 DW_DLE_NONE)
675 return (ret);
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;
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
697 * should use?
699 RCHECK(WRITE_VALUE(li->li_defstmt, 1));
702 * Write line_base and line_range. FIXME These value needs to be
703 * fine tuned.
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;
737 offset = 0;
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);
748 gen_fail:
749 _dwarf_reloc_section_free(dbg, &drs);
751 gen_fail1:
752 _dwarf_section_free(dbg, &ds);
754 return (ret);
757 void
758 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)
760 Dwarf_LineInfo li;
761 Dwarf_LineFile lf, tlf;
762 Dwarf_Line ln, tln;
763 int i;
765 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
766 if (dbg->dbgp_lineinfo == NULL)
767 return;
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);
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);
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);
786 free(li);
787 dbg->dbgp_lineinfo = NULL;