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