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