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