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