1 /*-
2 * Copyright (c) 2009,2010 Kai Wang
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 */
26
27 #include "_libdwarf.h"
28
29 ELFTC_VCSID("$Id: libdwarf_lineno.c 3164 2015-02-19 01:20:12Z kaiwang27 $");
30
31 static int
_dwarf_lineno_add_file(Dwarf_LineInfo li,uint8_t ** p,const char * compdir,Dwarf_Error * error,Dwarf_Debug dbg)32 _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir,
33 Dwarf_Error *error, Dwarf_Debug dbg)
34 {
35 Dwarf_LineFile lf;
36 FILE *filepath;
37 const char *incdir;
38 uint8_t *src;
39 size_t slen;
40
41 src = *p;
42
43 if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
44 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
45 return (DW_DLE_MEMORY);
46 }
47
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) {
53 free(lf);
54 DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD);
55 return (DW_DLE_DIR_INDEX_BAD);
56 }
57
58 /* Make a full pathname if needed. */
59 if (*lf->lf_fname != '/') {
60 filepath = open_memstream(&lf->lf_fullpath, &slen);
61 if (filepath == NULL) {
62 free(lf);
63 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
64 return (DW_DLE_MEMORY);
65 }
66
67 if (lf->lf_dirndx > 0)
68 incdir = li->li_incdirs[lf->lf_dirndx - 1];
69 else
70 incdir = NULL;
71
72 /*
73 * Prepend the compilation directory if the directory table
74 * entry is relative.
75 */
76 if (incdir == NULL || *incdir != '/')
77 fprintf(filepath, "%s/", compdir);
78 if (incdir != NULL)
79 fprintf(filepath, "%s/", incdir);
80 fprintf(filepath, "%s", lf->lf_fname);
81 if (fclose(filepath) != 0) {
82 free(lf);
83 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
84 return (DW_DLE_MEMORY);
85 }
86 }
87
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);
91 li->li_lflen++;
92
93 *p = src;
94
95 return (DW_DLE_NONE);
96 }
97
98 static int
_dwarf_lineno_run_program(Dwarf_CU cu,Dwarf_LineInfo li,uint8_t * p,uint8_t * pe,const char * compdir,Dwarf_Error * error)99 _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p,
100 uint8_t *pe, const char *compdir, Dwarf_Error *error)
101 {
102 Dwarf_Debug dbg;
103 Dwarf_Line ln, tln;
104 uint64_t address, file, line, column, opsize;
105 int is_stmt, basic_block, end_sequence;
106 int ret;
107
108 #define RESET_REGISTERS \
109 do { \
110 address = 0; \
111 file = 1; \
112 line = 1; \
113 column = 0; \
114 is_stmt = li->li_defstmt; \
115 basic_block = 0; \
116 end_sequence = 0; \
117 } while(0)
118
119 #define APPEND_ROW \
120 do { \
121 ln = malloc(sizeof(struct _Dwarf_Line)); \
122 if (ln == NULL) { \
123 ret = DW_DLE_MEMORY; \
124 DWARF_SET_ERROR(dbg, error, ret); \
125 goto prog_fail; \
126 } \
127 ln->ln_li = li; \
128 ln->ln_addr = address; \
129 ln->ln_symndx = 0; \
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);\
137 li->li_lnlen++; \
138 } while(0)
139
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)
142
143 dbg = cu->cu_dbg;
144
145 /*
146 * Set registers to their default values.
147 */
148 RESET_REGISTERS;
149
150 /*
151 * Start line number program.
152 */
153 while (p < pe) {
154 if (*p == 0) {
155
156 /*
157 * Extended Opcodes.
158 */
159
160 p++;
161 opsize = _dwarf_decode_uleb128(&p);
162 switch (*p) {
163 case DW_LNE_end_sequence:
164 p++;
165 end_sequence = 1;
166 APPEND_ROW;
167 RESET_REGISTERS;
168 break;
169 case DW_LNE_set_address:
170 p++;
171 address = dbg->decode(&p, cu->cu_pointer_size);
172 break;
173 case DW_LNE_define_file:
174 p++;
175 ret = _dwarf_lineno_add_file(li, &p, compdir,
176 error, dbg);
177 if (ret != DW_DLE_NONE)
178 goto prog_fail;
179 break;
180 default:
181 /* Unrecognized extened opcodes. */
182 p += opsize;
183 }
184
185 } else if (*p > 0 && *p < li->li_opbase) {
186
187 /*
188 * Standard Opcodes.
189 */
190
191 switch (*p++) {
192 case DW_LNS_copy:
193 APPEND_ROW;
194 basic_block = 0;
195 break;
196 case DW_LNS_advance_pc:
197 address += _dwarf_decode_uleb128(&p) *
198 li->li_minlen;
199 break;
200 case DW_LNS_advance_line:
201 line += _dwarf_decode_sleb128(&p);
202 break;
203 case DW_LNS_set_file:
204 file = _dwarf_decode_uleb128(&p);
205 break;
206 case DW_LNS_set_column:
207 column = _dwarf_decode_uleb128(&p);
208 break;
209 case DW_LNS_negate_stmt:
210 is_stmt = !is_stmt;
211 break;
212 case DW_LNS_set_basic_block:
213 basic_block = 1;
214 break;
215 case DW_LNS_const_add_pc:
216 address += ADDRESS(255);
217 break;
218 case DW_LNS_fixed_advance_pc:
219 address += dbg->decode(&p, 2);
220 break;
221 case DW_LNS_set_prologue_end:
222 break;
223 case DW_LNS_set_epilogue_begin:
224 break;
225 case DW_LNS_set_isa:
226 (void) _dwarf_decode_uleb128(&p);
227 break;
228 default:
229 /* Unrecognized extened opcodes. What to do? */
230 break;
231 }
232
233 } else {
234
235 /*
236 * Special Opcodes.
237 */
238
239 line += LINE(*p);
240 address += ADDRESS(*p);
241 APPEND_ROW;
242 basic_block = 0;
243 p++;
244 }
245 }
246
247 return (DW_DLE_NONE);
248
249 prog_fail:
250
251 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
252 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
253 free(ln);
254 }
255
256 return (ret);
257
258 #undef RESET_REGISTERS
259 #undef APPEND_ROW
260 #undef LINE
261 #undef ADDRESS
262 }
263
264 int
_dwarf_lineno_init(Dwarf_Die die,uint64_t offset,Dwarf_Error * error)265 _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error)
266 {
267 Dwarf_Debug dbg;
268 Dwarf_Section *ds;
269 Dwarf_CU cu;
270 Dwarf_Attribute at;
271 Dwarf_LineInfo li;
272 Dwarf_LineFile lf, tlf;
273 const char *compdir;
274 uint64_t length, hdroff, endoff;
275 uint8_t *p;
276 int dwarf_size, i, ret;
277
278 cu = die->die_cu;
279 assert(cu != NULL);
280
281 dbg = cu->cu_dbg;
282 assert(dbg != NULL);
283
284 if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL)
285 return (DW_DLE_NONE);
286
287 /*
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.
290 */
291 compdir = NULL;
292 at = _dwarf_attr_find(die, DW_AT_comp_dir);
293 if (at != NULL) {
294 switch (at->at_form) {
295 case DW_FORM_strp:
296 compdir = at->u[1].s;
297 break;
298 case DW_FORM_string:
299 compdir = at->u[0].s;
300 break;
301 default:
302 break;
303 }
304 }
305
306 length = dbg->read(ds->ds_data, &offset, 4);
307 if (length == 0xffffffff) {
308 dwarf_size = 8;
309 length = dbg->read(ds->ds_data, &offset, 8);
310 } else
311 dwarf_size = 4;
312
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);
316 }
317
318 if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) {
319 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
320 return (DW_DLE_MEMORY);
321 }
322
323 /*
324 * Read in line number program header.
325 */
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);
330 hdroff = offset;
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);
340
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);
344 goto fail_cleanup;
345 }
346
347 if ((li->li_oplen = malloc(li->li_opbase)) == NULL) {
348 ret = DW_DLE_MEMORY;
349 DWARF_SET_ERROR(dbg, error, ret);
350 goto fail_cleanup;
351 }
352
353 /*
354 * Read in std opcode arg length list. Note that the first
355 * element is not used.
356 */
357 for (i = 1; i < li->li_opbase; i++)
358 li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1);
359
360 /*
361 * Check how many strings in the include dir string array.
362 */
363 length = 0;
364 p = ds->ds_data + offset;
365 while (*p != '\0') {
366 while (*p++ != '\0')
367 ;
368 length++;
369 }
370 li->li_inclen = length;
371
372 /* Sanity check. */
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);
376 goto fail_cleanup;
377 }
378
379 if (length != 0) {
380 if ((li->li_incdirs = malloc(length * sizeof(char *))) ==
381 NULL) {
382 ret = DW_DLE_MEMORY;
383 DWARF_SET_ERROR(dbg, error, ret);
384 goto fail_cleanup;
385 }
386 }
387
388 /* Fill in include dir array. */
389 i = 0;
390 p = ds->ds_data + offset;
391 while (*p != '\0') {
392 li->li_incdirs[i++] = (char *) p;
393 while (*p++ != '\0')
394 ;
395 }
396
397 p++;
398
399 /*
400 * Process file list.
401 */
402 while (*p != '\0') {
403 ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg);
404 if (ret != DW_DLE_NONE)
405 goto fail_cleanup;
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);
409 goto fail_cleanup;
410 }
411 }
412
413 p++;
414
415 /* Sanity check. */
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);
419 goto fail_cleanup;
420 }
421
422 /*
423 * Process line number program.
424 */
425 ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir,
426 error);
427 if (ret != DW_DLE_NONE)
428 goto fail_cleanup;
429
430 cu->cu_lineinfo = li;
431
432 return (DW_DLE_NONE);
433
434 fail_cleanup:
435
436 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
437 STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next);
438 if (lf->lf_fullpath)
439 free(lf->lf_fullpath);
440 free(lf);
441 }
442
443 if (li->li_oplen)
444 free(li->li_oplen);
445 if (li->li_incdirs)
446 free(li->li_incdirs);
447 free(li);
448
449 return (ret);
450 }
451
452 void
_dwarf_lineno_cleanup(Dwarf_LineInfo li)453 _dwarf_lineno_cleanup(Dwarf_LineInfo li)
454 {
455 Dwarf_LineFile lf, tlf;
456 Dwarf_Line ln, tln;
457
458 if (li == NULL)
459 return;
460 STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
461 STAILQ_REMOVE(&li->li_lflist, lf,
462 _Dwarf_LineFile, lf_next);
463 if (lf->lf_fullpath)
464 free(lf->lf_fullpath);
465 free(lf);
466 }
467 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
468 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line,
469 ln_next);
470 free(ln);
471 }
472 if (li->li_oplen)
473 free(li->li_oplen);
474 if (li->li_incdirs)
475 free(li->li_incdirs);
476 if (li->li_lnarray)
477 free(li->li_lnarray);
478 if (li->li_lfnarray)
479 free(li->li_lfnarray);
480 free(li);
481 }
482
483 static int
_dwarf_lineno_gen_program(Dwarf_P_Debug dbg,Dwarf_P_Section ds,Dwarf_Rel_Section drs,Dwarf_Error * error)484 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
485 Dwarf_Rel_Section drs, Dwarf_Error * error)
486 {
487 Dwarf_LineInfo li;
488 Dwarf_Line ln;
489 Dwarf_Unsigned address, file, line, spc;
490 Dwarf_Unsigned addr0, maddr;
491 Dwarf_Signed line0, column;
492 int is_stmt, basic_block;
493 int need_copy;
494 int ret;
495
496 #define RESET_REGISTERS \
497 do { \
498 address = 0; \
499 file = 1; \
500 line = 1; \
501 column = 0; \
502 is_stmt = li->li_defstmt; \
503 basic_block = 0; \
504 } while(0)
505
506 li = dbg->dbgp_lineinfo;
507 maddr = (255 - li->li_opbase) / li->li_lrange;
508
509 RESET_REGISTERS;
510
511 STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) {
512 if (ln->ln_symndx > 0) {
513 /*
514 * Generate DW_LNE_set_address extended op.
515 */
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,
522 NULL, error));
523 address = ln->ln_addr;
524 continue;
525 } else if (ln->ln_endseq) {
526 addr0 = (ln->ln_addr - address) / li->li_minlen;
527 if (addr0 != 0) {
528 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
529 RCHECK(WRITE_ULEB128(addr0));
530 }
531
532 /*
533 * Generate DW_LNE_end_sequence.
534 */
535 RCHECK(WRITE_VALUE(0, 1));
536 RCHECK(WRITE_ULEB128(1));
537 RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1));
538 RESET_REGISTERS;
539 continue;
540 }
541
542 /*
543 * Generate standard opcodes for file, column, is_stmt or
544 * basic_block changes.
545 */
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;
550 }
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;
555 }
556 if (ln->ln_stmt != is_stmt) {
557 RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1));
558 is_stmt = ln->ln_stmt;
559 }
560 if (ln->ln_bblock && !basic_block) {
561 RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1));
562 basic_block = 1;
563 }
564
565 /*
566 * Calculate address and line number change.
567 */
568 addr0 = (ln->ln_addr - address) / li->li_minlen;
569 line0 = ln->ln_lineno - line;
570
571 if (addr0 == 0 && line0 == 0)
572 continue;
573
574 /*
575 * Check if line delta is with the range and if the special
576 * opcode can be used.
577 */
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;
583 if (spc <= 255) {
584 RCHECK(WRITE_VALUE(spc, 1));
585 basic_block = 0;
586 goto next_line;
587 }
588 }
589
590 /* Generate DW_LNS_advance_line for line number change. */
591 if (line0 != 0) {
592 RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1));
593 RCHECK(WRITE_SLEB128(line0));
594 line0 = 0;
595 need_copy = 1;
596 } else
597 need_copy = basic_block;
598
599 if (addr0 != 0) {
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));
606 } else {
607 /* Otherwise we use DW_LNS_advance_pc. */
608 RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
609 RCHECK(WRITE_ULEB128(addr0));
610 }
611 }
612
613 if (need_copy) {
614 RCHECK(WRITE_VALUE(DW_LNS_copy, 1));
615 basic_block = 0;
616 }
617
618 next_line:
619 address = ln->ln_addr;
620 line = ln->ln_lineno;
621 }
622
623 return (DW_DLE_NONE);
624
625 gen_fail:
626 return (ret);
627
628 #undef RESET_REGISTERS
629 }
630
631 static uint8_t
_dwarf_get_minlen(Dwarf_P_Debug dbg)632 _dwarf_get_minlen(Dwarf_P_Debug dbg)
633 {
634
635 assert(dbg != NULL);
636
637 switch (dbg->dbgp_isa) {
638 case DW_ISA_ARM:
639 return (2);
640 case DW_ISA_X86:
641 case DW_ISA_X86_64:
642 return (1);
643 default:
644 return (4);
645 }
646 }
647
648 static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
649
650 int
_dwarf_lineno_gen(Dwarf_P_Debug dbg,Dwarf_Error * error)651 _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
652 {
653 Dwarf_LineInfo li;
654 Dwarf_LineFile lf;
655 Dwarf_P_Section ds;
656 Dwarf_Rel_Section drs;
657 Dwarf_Unsigned offset;
658 int i, ret;
659
660 assert(dbg != NULL && dbg->dbgp_lineinfo != NULL);
661
662 li = dbg->dbgp_lineinfo;
663 if (STAILQ_EMPTY(&li->li_lnlist))
664 return (DW_DLE_NONE);
665
666 li->li_length = 0;
667 li->li_version = 2;
668 li->li_hdrlen = 0;
669 li->li_minlen = _dwarf_get_minlen(dbg);
670 li->li_defstmt = 1;
671 li->li_lbase = -5;
672 li->li_lrange = 14;
673 li->li_opbase = 10;
674
675 /* Create .debug_line section. */
676 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) !=
677 DW_DLE_NONE)
678 return (ret);
679
680 /* Create relocation section for .debug_line */
681 if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) !=
682 DW_DLE_NONE)
683 goto gen_fail1;
684
685 /* Length placeholder. (We only use 32-bit DWARF format) */
686 RCHECK(WRITE_VALUE(0, 4));
687
688 /* Write line number dwarf version. (DWARF2) */
689 RCHECK(WRITE_VALUE(li->li_version, 2));
690
691 /* Header length placeholder. */
692 offset = ds->ds_size;
693 RCHECK(WRITE_VALUE(li->li_hdrlen, 4));
694
695 /* Write minimum instruction length. */
696 RCHECK(WRITE_VALUE(li->li_minlen, 1));
697
698 /*
699 * Write initial value for is_stmt. XXX Which default value we
700 * should use?
701 */
702 RCHECK(WRITE_VALUE(li->li_defstmt, 1));
703
704 /*
705 * Write line_base and line_range. FIXME These value needs to be
706 * fine tuned.
707 */
708 RCHECK(WRITE_VALUE(li->li_lbase, 1));
709 RCHECK(WRITE_VALUE(li->li_lrange, 1));
710
711 /* Write opcode_base. (DWARF2) */
712 RCHECK(WRITE_VALUE(li->li_opbase, 1));
713
714 /* Write standard op length array. */
715 RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0])));
716
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));
721
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));
728 }
729 RCHECK(WRITE_VALUE(0, 1));
730
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);
734
735 /* Generate the line number program. */
736 RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error));
737
738 /* Fill in the length of this line info. */
739 li->li_length = ds->ds_size - 4;
740 offset = 0;
741 dbg->write(ds->ds_data, &offset, li->li_length, 4);
742
743 /* Notify the creation of .debug_line ELF section. */
744 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
745
746 /* Finalize relocation section for .debug_line. */
747 RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
748
749 return (DW_DLE_NONE);
750
751 gen_fail:
752 _dwarf_reloc_section_free(dbg, &drs);
753
754 gen_fail1:
755 _dwarf_section_free(dbg, &ds);
756
757 return (ret);
758 }
759
760 void
_dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)761 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)
762 {
763 Dwarf_LineInfo li;
764 Dwarf_LineFile lf, tlf;
765 Dwarf_Line ln, tln;
766 int i;
767
768 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
769 if (dbg->dbgp_lineinfo == NULL)
770 return;
771
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,
775 lf_next);
776 if (lf->lf_fname)
777 free(lf->lf_fname);
778 free(lf);
779 }
780 STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
781 STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
782 free(ln);
783 }
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);
788 }
789 free(li);
790 dbg->dbgp_lineinfo = NULL;
791 }
792