xref: /freebsd/contrib/elftoolchain/libdwarf/libdwarf_lineno.c (revision 7d8f797b725e3efc0a4256554654780df83c456c)
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
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
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
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
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
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
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
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
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