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
29ELFTC_VCSID("$Id: libdwarf_lineno.c 3164 2015-02-19 01:20:12Z kaiwang27 $");
30
31static 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	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
98static int
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
249prog_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
264int
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
434fail_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
452void
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
483static int
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
625gen_fail:
626	return (ret);
627
628#undef	RESET_REGISTERS
629}
630
631static uint8_t
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
648static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
649
650int
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
751gen_fail:
752	_dwarf_reloc_section_free(dbg, &drs);
753
754gen_fail1:
755	_dwarf_section_free(dbg, &ds);
756
757	return (ret);
758}
759
760void
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