Home | History | Annotate | Line # | Download | only in libdwarf
      1 /*	$NetBSD: libdwarf_lineno.c,v 1.6 2026/05/17 21:40:49 jkoshy Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009,2010,2023 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.6 2026/05/17 21:40:49 jkoshy Exp $");
     32 ELFTC_VCSID("Id: libdwarf_lineno.c 4067 2025-01-03 10:33:44Z jkoshy");
     33 
     34 static int
     35 _dwarf_lineno_make_fullpath(Dwarf_Debug dbg, Dwarf_LineInfo li,
     36     Dwarf_LineFile lf, const char *compdir, Dwarf_Error *error)
     37 {
     38 	const char *dirname;
     39 	int slen;
     40 
     41 	/* Make full pathname if need. */
     42 	if (*lf->lf_fname != '/') {
     43 		dirname = compdir;
     44 		if (lf->lf_dirndx > 0)
     45 			dirname = li->li_incdirs[lf->lf_dirndx - 1];
     46 		if (dirname != NULL) {
     47 			slen = strlen(dirname) + strlen(lf->lf_fname) + 2;
     48 			if ((lf->lf_fullpath = malloc(slen)) == NULL) {
     49 				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
     50 				return (DW_DLE_MEMORY);
     51 			}
     52 			snprintf(lf->lf_fullpath, slen, "%s/%s", dirname,
     53 			    lf->lf_fname);
     54 		}
     55 	}
     56 
     57 	return (DW_DLE_NONE);
     58 }
     59 
     60 static int
     61 _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir,
     62     Dwarf_Error *error, Dwarf_Debug dbg)
     63 {
     64 	Dwarf_LineFile lf;
     65 	uint8_t *src;
     66 	int ret;
     67 
     68 	src = *p;
     69 
     70 	if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
     71 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
     72 		return (DW_DLE_MEMORY);
     73 	}
     74 
     75 	lf->lf_fullpath = NULL;
     76 	lf->lf_fname = (char *) src;
     77 	src += strlen(lf->lf_fname) + 1;
     78 	lf->lf_dirndx = _dwarf_decode_uleb128(&src);
     79 	if (lf->lf_dirndx > li->li_inclen) {
     80 		free(lf);
     81 		DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD);
     82 		return (DW_DLE_DIR_INDEX_BAD);
     83 	}
     84 
     85 	ret = _dwarf_lineno_make_fullpath(dbg, li, lf, compdir, error);
     86 	if (ret != DW_DLE_NONE) {
     87 		free(lf);
     88 		return (ret);
     89 	}
     90 
     91 	lf->lf_mtime = _dwarf_decode_uleb128(&src);
     92 	lf->lf_size = _dwarf_decode_uleb128(&src);
     93 	STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next);
     94 	li->li_lflen++;
     95 
     96 	*p = src;
     97 
     98 	return (DW_DLE_NONE);
     99 }
    100 
    101 static int
    102 _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p,
    103     uint8_t *pe, const char *compdir, Dwarf_Error *error)
    104 {
    105 	Dwarf_Debug dbg;
    106 	Dwarf_Line ln, tln;
    107 	uint64_t address, file, line, column, opsize;
    108 	int is_stmt, basic_block, end_sequence;
    109 	int ret;
    110 
    111 #define	RESET_REGISTERS						\
    112 	do {							\
    113 		address	       = 0;				\
    114 		file	       = 1;				\
    115 		line	       = 1;				\
    116 		column	       = 0;				\
    117 		is_stmt	       = li->li_defstmt;		\
    118 		basic_block    = 0;				\
    119 		end_sequence   = 0;				\
    120 	} while(0)
    121 
    122 #define	APPEND_ROW						\
    123 	do {							\
    124 		ln = malloc(sizeof(struct _Dwarf_Line));	\
    125 		if (ln == NULL) {				\
    126 			ret = DW_DLE_MEMORY;			\
    127 			DWARF_SET_ERROR(dbg, error, ret);	\
    128 			goto prog_fail;				\
    129 		}						\
    130 		ln->ln_li     = li;				\
    131 		ln->ln_addr   = address;			\
    132 		ln->ln_symndx = 0;				\
    133 		ln->ln_fileno = file;				\
    134 		ln->ln_lineno = line;				\
    135 		ln->ln_column = column;				\
    136 		ln->ln_bblock = basic_block;			\
    137 		ln->ln_stmt   = is_stmt;			\
    138 		ln->ln_endseq = end_sequence;			\
    139 		STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);\
    140 		li->li_lnlen++;					\
    141 	} while(0)
    142 
    143 #define	LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange))
    144 #define	ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen)
    145 
    146 	dbg = cu->cu_dbg;
    147 
    148 	/*
    149 	 * Set registers to their default values.
    150 	 */
    151 	RESET_REGISTERS;
    152 
    153 	/*
    154 	 * Start line number program.
    155 	 */
    156 	while (p < pe) {
    157 		if (*p == 0) {
    158 
    159 			/*
    160 			 * Extended Opcodes.
    161 			 */
    162 
    163 			p++;
    164 			opsize = _dwarf_decode_uleb128(&p);
    165 			switch (*p) {
    166 			case DW_LNE_end_sequence:
    167 				p++;
    168 				end_sequence = 1;
    169 				APPEND_ROW;
    170 				RESET_REGISTERS;
    171 				break;
    172 			case DW_LNE_set_address:
    173 				p++;
    174 				address = dbg->decode(&p, cu->cu_pointer_size);
    175 				break;
    176 			case DW_LNE_define_file:
    177 				p++;
    178 				ret = _dwarf_lineno_add_file(li, &p, compdir,
    179 				    error, dbg);
    180 				if (ret != DW_DLE_NONE)
    181 					goto prog_fail;
    182 				break;
    183 			default:
    184 				/* Unrecognized extened opcodes. */
    185 				p += opsize;
    186 			}
    187 
    188 		} else if (*p > 0 && *p < li->li_opbase) {
    189 
    190 			/*
    191 			 * Standard Opcodes.
    192 			 */
    193 
    194 			switch (*p++) {
    195 			case DW_LNS_copy:
    196 				APPEND_ROW;
    197 				basic_block = 0;
    198 				break;
    199 			case DW_LNS_advance_pc:
    200 				address += _dwarf_decode_uleb128(&p) *
    201 				    li->li_minlen;
    202 				break;
    203 			case DW_LNS_advance_line:
    204 				line += _dwarf_decode_sleb128(&p);
    205 				break;
    206 			case DW_LNS_set_file:
    207 				file = _dwarf_decode_uleb128(&p);
    208 				break;
    209 			case DW_LNS_set_column:
    210 				column = _dwarf_decode_uleb128(&p);
    211 				break;
    212 			case DW_LNS_negate_stmt:
    213 				is_stmt = !is_stmt;
    214 				break;
    215 			case DW_LNS_set_basic_block:
    216 				basic_block = 1;
    217 				break;
    218 			case DW_LNS_const_add_pc:
    219 				address += ADDRESS(255);
    220 				break;
    221 			case DW_LNS_fixed_advance_pc:
    222 				address += dbg->decode(&p, 2);
    223 				break;
    224 			case DW_LNS_set_prologue_end:
    225 				break;
    226 			case DW_LNS_set_epilogue_begin:
    227 				break;
    228 			case DW_LNS_set_isa:
    229 				(void) _dwarf_decode_uleb128(&p);
    230 				break;
    231 			default:
    232 				/* Unrecognized extened opcodes. What to do? */
    233 				break;
    234 			}
    235 
    236 		} else {
    237 
    238 			/*
    239 			 * Special Opcodes.
    240 			 */
    241 
    242 			line += LINE(*p);
    243 			address += ADDRESS(*p);
    244 			APPEND_ROW;
    245 			basic_block = 0;
    246 			p++;
    247 		}
    248 	}
    249 
    250 	return (DW_DLE_NONE);
    251 
    252 prog_fail:
    253 
    254 	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
    255 		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
    256 		free(ln);
    257 	}
    258 
    259 	return (ret);
    260 
    261 #undef	RESET_REGISTERS
    262 #undef	APPEND_ROW
    263 #undef	LINE
    264 #undef	ADDRESS
    265 }
    266 
    267 struct lnct {
    268 	unsigned type;
    269 	unsigned form;
    270 };
    271 
    272 
    273 static int
    274 _dwarf_lineno_parse_lnct_desc(Dwarf_Debug dbg, int fmt, struct lnct **lnct,
    275     uint8_t *data, uint64_t *offsetp, Dwarf_Error *error)
    276 {
    277 	int i;
    278 
    279 	if (fmt == 0) {
    280 		*lnct = NULL;
    281 		return (DW_DLE_NONE);
    282 	}
    283 
    284 	if ((*lnct = calloc(fmt, sizeof(struct lnct))) == NULL) {
    285 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    286 		return (DW_DLE_MEMORY);
    287 	}
    288 	for (i = 0; i < fmt; i++) {
    289 		(*lnct)[i].type = _dwarf_read_uleb128(data, offsetp);
    290 		(*lnct)[i].form = _dwarf_read_uleb128(data, offsetp);
    291 	}
    292 
    293 	return (DW_DLE_NONE);
    294 }
    295 
    296 static int
    297 _dwarf_lineno_lnct_path(Dwarf_Debug dbg, char **fname, unsigned form,
    298     uint8_t *data, uint64_t size, uint64_t *offsetp, int dwarf_size,
    299     Dwarf_Error *error)
    300 {
    301 	Dwarf_Unsigned sp;
    302 	int ret;
    303 
    304 	ret = DW_DLE_NONE;
    305 
    306 	switch (form) {
    307 	case DW_FORM_string:
    308 		*fname = _dwarf_read_string(data, size, offsetp);
    309 		break;
    310 	case DW_FORM_strp:
    311 		sp = dbg->read(data, offsetp, dwarf_size);
    312 		*fname = _dwarf_strtab_get_table(dbg) + sp;
    313 		break;
    314 	case DW_FORM_line_strp:
    315 		sp = dbg->read(data, offsetp, dwarf_size);
    316 		*fname = _dwarf_strtab_get_line_table(dbg) + sp;
    317 		break;
    318 	case DW_FORM_strp_sup:
    319 		sp = dbg->read(data, offsetp, dwarf_size);
    320 		*fname = NULL;	/* TODO: support sup string table. */
    321 		break;
    322 	default:
    323 		ret = DW_DLE_LNCT_DESC_BAD;
    324 		DWARF_SET_ERROR(dbg, error, ret);
    325 		break;
    326 	}
    327 
    328 	return (ret);
    329 }
    330 
    331 static int
    332 _dwarf_lineno_lnct_dirndx(Dwarf_Debug dbg, Dwarf_Unsigned *dirndx,
    333     unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error)
    334 {
    335 	int ret;
    336 
    337 	ret = DW_DLE_NONE;
    338 
    339 	switch (form) {
    340 	case DW_FORM_data1:
    341 		*dirndx = dbg->read(data, offsetp, 1);
    342 		break;
    343 	case DW_FORM_data2:
    344 		*dirndx = dbg->read(data, offsetp, 2);
    345 		break;
    346 	case DW_FORM_udata:
    347 		*dirndx = _dwarf_read_uleb128(data, offsetp);
    348 		break;
    349 	default:
    350 		ret = DW_DLE_LNCT_DESC_BAD;
    351 		DWARF_SET_ERROR(dbg, error, ret);
    352 		break;
    353 	}
    354 
    355 	return (ret);
    356 }
    357 
    358 static int
    359 _dwarf_lineno_lnct_timestamp(Dwarf_Debug dbg, Dwarf_Unsigned *ts,
    360     unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error)
    361 {
    362 	int ret;
    363 
    364 	ret = DW_DLE_NONE;
    365 
    366 	switch (form) {
    367 	case DW_FORM_udata:
    368 		*ts = _dwarf_read_uleb128(data, offsetp);
    369 		break;
    370 	case DW_FORM_data4:
    371 		*ts = dbg->read(data, offsetp, 4);
    372 		break;
    373 	case DW_FORM_data8:
    374 		*ts = dbg->read(data, offsetp, 8);
    375 		break;
    376 	case DW_FORM_block:
    377 		/* TODO: Not supported. */
    378 	default:
    379 		ret = DW_DLE_LNCT_DESC_BAD;
    380 		DWARF_SET_ERROR(dbg, error, ret);
    381 		break;
    382 	}
    383 
    384 	return (ret);
    385 }
    386 
    387 static int
    388 _dwarf_lineno_lnct_size(Dwarf_Debug dbg, Dwarf_Unsigned *sz, unsigned form,
    389     uint8_t *data, uint64_t *offsetp, Dwarf_Error *error)
    390 {
    391 	int ret;
    392 
    393 	ret = DW_DLE_NONE;
    394 
    395 	switch (form) {
    396 	case DW_FORM_udata:
    397 		*sz = _dwarf_read_uleb128(data, offsetp);
    398 		break;
    399 	case DW_FORM_data1:
    400 		*sz = dbg->read(data, offsetp, 1);
    401 		break;
    402 	case DW_FORM_data2:
    403 		*sz = dbg->read(data, offsetp, 2);
    404 		break;
    405 	case DW_FORM_data4:
    406 		*sz = dbg->read(data, offsetp, 4);
    407 		break;
    408 	case DW_FORM_data8:
    409 		*sz = dbg->read(data, offsetp, 8);
    410 		break;
    411 	default:
    412 		ret = DW_DLE_LNCT_DESC_BAD;
    413 		DWARF_SET_ERROR(dbg, error, ret);
    414 		break;
    415 	}
    416 
    417 	return (ret);
    418 }
    419 
    420 static int
    421 _dwarf_lineno_lnct_md5(Dwarf_Debug dbg, Dwarf_Form_Data16 *md5,
    422     unsigned form, uint8_t *data, uint64_t *offsetp, Dwarf_Error *error)
    423 {
    424 
    425 	if (form != DW_FORM_data16) {
    426 		DWARF_SET_ERROR(dbg, error, DW_DLE_LNCT_DESC_BAD);
    427 		return (DW_DLE_LNCT_DESC_BAD);
    428 	}
    429 
    430 	memcpy(md5->fd_data, data + *offsetp, 16);
    431 	offsetp += 16;
    432 
    433 	return (DW_DLE_NONE);
    434 }
    435 
    436 int
    437 _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error)
    438 {
    439 	Dwarf_Debug dbg;
    440 	Dwarf_Section *ds;
    441 	Dwarf_CU cu;
    442 	Dwarf_Attribute at;
    443 	Dwarf_LineInfo li;
    444 	Dwarf_LineFile lf, tlf;
    445 	struct lnct *lnct;
    446 	char *compdir;
    447 	uint64_t length, hdroff, endoff;
    448 	uint8_t *p;
    449 	int dwarf_size, fmt, j, ret;
    450 	unsigned int i;
    451 
    452 	cu = die->die_cu;
    453 	assert(cu != NULL);
    454 
    455 	dbg = cu->cu_dbg;
    456 	assert(dbg != NULL);
    457 
    458 	if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL)
    459 		return (DW_DLE_NONE);
    460 
    461 	/*
    462 	 * Try to find out the dir where the CU was compiled. Later we
    463 	 * will use the dir to create full pathnames, if need.
    464 	 */
    465 	compdir = NULL;
    466 	at = _dwarf_attr_find(die, DW_AT_comp_dir);
    467 	if (at != NULL) {
    468 		switch (at->at_form) {
    469 		case DW_FORM_strp:
    470 		case DW_FORM_strp_sup:
    471 		case DW_FORM_line_strp:
    472 			compdir = at->u[1].s;
    473 			break;
    474 		case DW_FORM_string:
    475 			compdir = at->u[0].s;
    476 			break;
    477 		case DW_FORM_strx:
    478 		case DW_FORM_strx1:
    479 		case DW_FORM_strx2:
    480 		case DW_FORM_strx3:
    481 		case DW_FORM_strx4:
    482 			if ((ret = _dwarf_read_indexed_str(dbg, cu,
    483 			    at->u[0].u64, &compdir, error)) != DW_DLE_NONE)
    484 				return (ret);
    485 		default:
    486 			break;
    487 		}
    488 	}
    489 
    490 	length = dbg->read(ds->ds_data, &offset, 4);
    491 	if (length == 0xffffffff) {
    492 		dwarf_size = 8;
    493 		length = dbg->read(ds->ds_data, &offset, 8);
    494 	} else
    495 		dwarf_size = 4;
    496 
    497 	if (length > ds->ds_size - offset) {
    498 		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
    499 		return (DW_DLE_DEBUG_LINE_LENGTH_BAD);
    500 	}
    501 
    502 	if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) {
    503 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
    504 		return (DW_DLE_MEMORY);
    505 	}
    506 
    507 	/*
    508 	 * Read in line number program header.
    509 	 */
    510 	li->li_length = length;
    511 	endoff = offset + length;
    512 	li->li_version = dbg->read(ds->ds_data, &offset, 2);
    513 	if (li->li_version == 5) {
    514 		(void) dbg->read(ds->ds_data, &offset, 1); /* TODO */
    515 		(void) dbg->read(ds->ds_data, &offset, 1); /* TODO */
    516 	}
    517 	li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size);
    518 	hdroff = offset;
    519 	li->li_minlen = dbg->read(ds->ds_data, &offset, 1);
    520 	if (li->li_version >= 4)
    521 		li->li_maxop = dbg->read(ds->ds_data, &offset, 1);
    522 	li->li_defstmt = dbg->read(ds->ds_data, &offset, 1);
    523 	li->li_lbase = dbg->read(ds->ds_data, &offset, 1);
    524 	li->li_lrange = dbg->read(ds->ds_data, &offset, 1);
    525 	li->li_opbase = dbg->read(ds->ds_data, &offset, 1);
    526 	STAILQ_INIT(&li->li_lflist);
    527 	STAILQ_INIT(&li->li_lnlist);
    528 
    529 	if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) {
    530 		ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
    531 		DWARF_SET_ERROR(dbg, error, ret);
    532 		goto fail_cleanup;
    533 	}
    534 
    535 	if ((li->li_oplen = malloc(li->li_opbase)) == NULL) {
    536 		ret = DW_DLE_MEMORY;
    537 		DWARF_SET_ERROR(dbg, error, ret);
    538 		goto fail_cleanup;
    539 	}
    540 
    541 	/*
    542 	 * Read in std opcode arg length list. Note that the first
    543 	 * element is not used.
    544 	 */
    545 	for (i = 1; i < li->li_opbase; i++)
    546 		li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1);
    547 
    548 	/*
    549 	 * Directory and filename parser for DWARF4 and below.
    550 	 */
    551 	if (li->li_version <= 4) {
    552 
    553 		/*
    554 		 * Check how many strings in the include dir string array.
    555 		 */
    556 		length = 0;
    557 		p = ds->ds_data + offset;
    558 		while (*p != '\0') {
    559 			while (*p++ != '\0')
    560 				;
    561 			length++;
    562 		}
    563 		li->li_inclen = length;
    564 
    565 		/* Sanity check. */
    566 		if (p - ds->ds_data > (int) ds->ds_size) {
    567 			ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
    568 			DWARF_SET_ERROR(dbg, error, ret);
    569 			goto fail_cleanup;
    570 		}
    571 
    572 		if (length != 0) {
    573 			if ((li->li_incdirs = malloc(length * sizeof(char *))) ==
    574 			    NULL) {
    575 				ret = DW_DLE_MEMORY;
    576 				DWARF_SET_ERROR(dbg, error, ret);
    577 				goto fail_cleanup;
    578 			}
    579 		}
    580 
    581 		/* Fill in include dir array. */
    582 		i = 0;
    583 		p = ds->ds_data + offset;
    584 		while (*p != '\0') {
    585 			li->li_incdirs[i++] = (char *) p;
    586 			while (*p++ != '\0')
    587 				;
    588 		}
    589 
    590 		p++;
    591 
    592 		/*
    593 		 * Process file list.
    594 		 */
    595 		while (*p != '\0') {
    596 			ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg);
    597 			if (ret != DW_DLE_NONE)
    598 				goto fail_cleanup;
    599 			if (p - ds->ds_data > (int) ds->ds_size) {
    600 				ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
    601 				DWARF_SET_ERROR(dbg, error, ret);
    602 				goto fail_cleanup;
    603 			}
    604 		}
    605 
    606 		p++;
    607 
    608 		/* Sanity check. */
    609 		if (p - ds->ds_data - hdroff != li->li_hdrlen) {
    610 			ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
    611 			DWARF_SET_ERROR(dbg, error, ret);
    612 			goto fail_cleanup;
    613 		}
    614 
    615 		goto lnprog;
    616 	}
    617 
    618 	/*
    619 	 * DWARF5 has completely overhauled the dir/source file information
    620 	 * fields, which are incompatible with DWARF4 or lower.
    621 	 */
    622 
    623 	lnct = NULL;
    624 	fmt = dbg->read(ds->ds_data, &offset, 1);
    625 	if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data,
    626 	    &offset, error)) != DW_DLE_NONE)
    627 		goto fail_cleanup;
    628 
    629 	li->li_inclen = dbg->read(ds->ds_data, &offset, 1);
    630 	if (li->li_inclen == 0) {
    631 		if (fmt > 0) {
    632 			free(lnct);
    633 			ret = DW_DLE_DIR_COUNT_BAD;
    634 			DWARF_SET_ERROR(dbg, error, ret);
    635 			goto fail_cleanup;
    636 		}
    637 
    638 		goto file_entries;
    639 	}
    640 
    641 	if (fmt == 0) {
    642 		ret = DW_DLE_DIR_COUNT_BAD;
    643 		DWARF_SET_ERROR(dbg, error, ret);
    644 		goto fail_cleanup;
    645 	}
    646 	if ((li->li_incdirs = malloc(length * sizeof(char *))) == NULL) {
    647 		free(lnct);
    648 		ret = DW_DLE_MEMORY;
    649 		DWARF_SET_ERROR(dbg, error, ret);
    650 		goto fail_cleanup;
    651 	}
    652 	for (i = 0; i < li->li_inclen; i++) {
    653 		for (j = 0; j < fmt; j++) {
    654 			if (lnct[j].type != DW_LNCT_path) {
    655 				free(lnct);
    656 				ret = DW_DLE_LNCT_DESC_BAD;
    657 				DWARF_SET_ERROR(dbg, error, ret);
    658 				goto fail_cleanup;
    659 			}
    660 
    661 			ret = _dwarf_lineno_lnct_path(dbg, &li->li_incdirs[i],
    662 			    lnct[j].form, ds->ds_data, ds->ds_size, &offset,
    663 			    dwarf_size, error);
    664 			if (ret != DW_DLE_NONE) {
    665 				free(lnct);
    666 				goto fail_cleanup;
    667 			}
    668 		}
    669 	}
    670 	if (lnct)
    671 		free(lnct);
    672 
    673 file_entries:
    674 
    675 	lnct = NULL;
    676 	fmt = dbg->read(ds->ds_data, &offset, 1);
    677 	if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data,
    678 	    &offset, error)) != DW_DLE_NONE)
    679 		goto fail_cleanup;
    680 
    681 	li->li_lflen = dbg->read(ds->ds_data, &offset, 1);
    682 	if (li->li_lflen == 0) {
    683 		if (fmt > 0) {
    684 			free(lnct);
    685 			ret = DW_DLE_FILE_COUNT_BAD;
    686 			DWARF_SET_ERROR(dbg, error, ret);
    687 			goto fail_cleanup;
    688 		}
    689 
    690 		p = ds->ds_data + offset;
    691 		goto lnprog;
    692 	}
    693 
    694 	for (i = 0; i < li->li_lflen; i++) {
    695 		if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
    696 			free(lnct);
    697 			ret = DW_DLE_MEMORY;
    698 			DWARF_SET_ERROR(dbg, error, ret);
    699 			goto fail_cleanup;
    700 		}
    701 		for (j = 0; j < fmt; j++) {
    702 			switch (lnct[j].type) {
    703 			case DW_LNCT_path:
    704 				ret = _dwarf_lineno_lnct_path(dbg,
    705 				    &lf->lf_fname, lnct[j].form, ds->ds_data,
    706 				    ds->ds_size, &offset, dwarf_size, error);
    707 				break;
    708 			case DW_LNCT_directory_index:
    709 				ret = _dwarf_lineno_lnct_dirndx(dbg,
    710 				    &lf->lf_dirndx, lnct[j].form, ds->ds_data,
    711 				    &offset, error);
    712 				break;
    713 			case DW_LNCT_timestamp:
    714 				ret = _dwarf_lineno_lnct_timestamp(dbg,
    715 				    &lf->lf_mtime, lnct[j].form, ds->ds_data,
    716 				    &offset, error);
    717 				break;
    718 			case DW_LNCT_size:
    719 				ret = _dwarf_lineno_lnct_size(dbg,
    720 				    &lf->lf_size, lnct[j].form, ds->ds_data,
    721 				    &offset, error);
    722 				break;
    723 			case DW_LNCT_MD5:
    724 				ret = _dwarf_lineno_lnct_md5(dbg,
    725 				    &lf->lf_md5, lnct[j].form, ds->ds_data,
    726 				    &offset, error);
    727 				break;
    728 			default:
    729 				ret = DW_DLE_LNCT_DESC_BAD;
    730 				DWARF_SET_ERROR(dbg, error, ret);
    731 				break;
    732 			}
    733 			if (ret != DW_DLE_NONE) {
    734 				free(lf);
    735 				free(lnct);
    736 				goto fail_cleanup;
    737 			}
    738 		}
    739 		ret = _dwarf_lineno_make_fullpath(dbg, li, lf, compdir, error);
    740 		if (ret != DW_DLE_NONE) {
    741 			free(lf);
    742 			free(lnct);
    743 			goto fail_cleanup;
    744 		}
    745 		STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next);
    746 	}
    747 	if (lnct)
    748 		free(lnct);
    749 
    750 	p = ds->ds_data + offset;
    751 
    752 lnprog:
    753 	/*
    754 	 * Process line number program.
    755 	 */
    756 	ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir,
    757 	    error);
    758 	if (ret != DW_DLE_NONE)
    759 		goto fail_cleanup;
    760 
    761 	cu->cu_lineinfo = li;
    762 
    763 	return (DW_DLE_NONE);
    764 
    765 fail_cleanup:
    766 
    767 	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
    768 		STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next);
    769 		if (lf->lf_fullpath)
    770 			free(lf->lf_fullpath);
    771 		free(lf);
    772 	}
    773 
    774 	if (li->li_oplen)
    775 		free(li->li_oplen);
    776 	if (li->li_incdirs)
    777 		free(li->li_incdirs);
    778 	free(li);
    779 
    780 	return (ret);
    781 }
    782 
    783 void
    784 _dwarf_lineno_cleanup(Dwarf_LineInfo li)
    785 {
    786 	Dwarf_LineFile lf, tlf;
    787 	Dwarf_Line ln, tln;
    788 
    789 	if (li == NULL)
    790 		return;
    791 	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
    792 		STAILQ_REMOVE(&li->li_lflist, lf,
    793 		    _Dwarf_LineFile, lf_next);
    794 		if (lf->lf_fullpath)
    795 			free(lf->lf_fullpath);
    796 		free(lf);
    797 	}
    798 	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
    799 		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line,
    800 		    ln_next);
    801 		free(ln);
    802 	}
    803 	if (li->li_oplen)
    804 		free(li->li_oplen);
    805 	if (li->li_incdirs)
    806 		free(li->li_incdirs);
    807 	if (li->li_lnarray)
    808 		free(li->li_lnarray);
    809 	if (li->li_lfnarray)
    810 		free(li->li_lfnarray);
    811 	free(li);
    812 }
    813 
    814 static int
    815 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
    816     Dwarf_Rel_Section drs, Dwarf_Error * error)
    817 {
    818 	Dwarf_LineInfo li;
    819 	Dwarf_Line ln;
    820 	Dwarf_Unsigned address, file, line, spc;
    821 	Dwarf_Unsigned addr0, maddr;
    822 	Dwarf_Signed line0, column;
    823 	int is_stmt, basic_block;
    824 	int need_copy;
    825 	int ret;
    826 
    827 #define	RESET_REGISTERS						\
    828 	do {							\
    829 		address	       = 0;				\
    830 		file	       = 1;				\
    831 		line	       = 1;				\
    832 		column	       = 0;				\
    833 		is_stmt	       = li->li_defstmt;		\
    834 		basic_block    = 0;				\
    835 	} while(0)
    836 
    837 	li = dbg->dbgp_lineinfo;
    838 	maddr = (255 - li->li_opbase) / li->li_lrange;
    839 
    840 	RESET_REGISTERS;
    841 
    842 	STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) {
    843 		if (ln->ln_symndx > 0) {
    844 			/*
    845 			 * Generate DW_LNE_set_address extended op.
    846 			 */
    847 			RCHECK(WRITE_VALUE(0, 1));
    848 			RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1));
    849 			RCHECK(WRITE_VALUE(DW_LNE_set_address, 1));
    850 			RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds,
    851 			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
    852 			    ds->ds_size, ln->ln_symndx, ln->ln_addr,
    853 			    NULL, error));
    854 			address = ln->ln_addr;
    855 			continue;
    856 		} else if (ln->ln_endseq) {
    857 			addr0 = (ln->ln_addr - address) / li->li_minlen;
    858 			if (addr0 != 0) {
    859 				RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
    860 				RCHECK(WRITE_ULEB128(addr0));
    861 			}
    862 
    863 			/*
    864 			 * Generate DW_LNE_end_sequence.
    865 			 */
    866 			RCHECK(WRITE_VALUE(0, 1));
    867 			RCHECK(WRITE_ULEB128(1));
    868 			RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1));
    869 			RESET_REGISTERS;
    870 			continue;
    871 		}
    872 
    873 		/*
    874 		 * Generate standard opcodes for file, column, is_stmt or
    875 		 * basic_block changes.
    876 		 */
    877 		if (ln->ln_fileno != file) {
    878 			RCHECK(WRITE_VALUE(DW_LNS_set_file, 1));
    879 			RCHECK(WRITE_ULEB128(ln->ln_fileno));
    880 			file = ln->ln_fileno;
    881 		}
    882 		if (ln->ln_column != column) {
    883 			RCHECK(WRITE_VALUE(DW_LNS_set_column, 1));
    884 			RCHECK(WRITE_ULEB128(ln->ln_column));
    885 			column = ln->ln_column;
    886 		}
    887 		if (ln->ln_stmt != is_stmt) {
    888 			RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1));
    889 			is_stmt = ln->ln_stmt;
    890 		}
    891 		if (ln->ln_bblock && !basic_block) {
    892 			RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1));
    893 			basic_block = 1;
    894 		}
    895 
    896 		/*
    897 		 * Calculate address and line number change.
    898 		 */
    899 		addr0 = (ln->ln_addr - address) / li->li_minlen;
    900 		line0 = ln->ln_lineno - line;
    901 
    902 		if (addr0 == 0 && line0 == 0)
    903 			continue;
    904 
    905 		/*
    906 		 * Check if line delta is with the range and if the special
    907 		 * opcode can be used.
    908 		 */
    909 		assert(li->li_lbase <= 0);
    910 		if (line0 >= li->li_lbase &&
    911 		    line0 <= li->li_lbase + li->li_lrange - 1) {
    912 			spc = (line0 - li->li_lbase) +
    913 			    (li->li_lrange * addr0) + li->li_opbase;
    914 			if (spc <= 255) {
    915 				RCHECK(WRITE_VALUE(spc, 1));
    916 				basic_block = 0;
    917 				goto next_line;
    918 			}
    919 		}
    920 
    921 		/* Generate DW_LNS_advance_line for line number change. */
    922 		if (line0 != 0) {
    923 			RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1));
    924 			RCHECK(WRITE_SLEB128(line0));
    925 			line0 = 0;
    926 			need_copy = 1;
    927 		} else
    928 			need_copy = basic_block;
    929 
    930 		if (addr0 != 0) {
    931 			/* See if it can be handled by DW_LNS_const_add_pc. */
    932 			spc = (line0 - li->li_lbase) +
    933 			    (li->li_lrange * (addr0 - maddr)) + li->li_opbase;
    934 			if (addr0 >= maddr && spc <= 255) {
    935 				RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1));
    936 				RCHECK(WRITE_VALUE(spc, 1));
    937 			} else {
    938 				/* Otherwise we use DW_LNS_advance_pc. */
    939 				RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
    940 				RCHECK(WRITE_ULEB128(addr0));
    941 			}
    942 		}
    943 
    944 		if (need_copy) {
    945 			RCHECK(WRITE_VALUE(DW_LNS_copy, 1));
    946 			basic_block = 0;
    947 		}
    948 
    949 	next_line:
    950 		address = ln->ln_addr;
    951 		line = ln->ln_lineno;
    952 	}
    953 
    954 	return (DW_DLE_NONE);
    955 
    956 gen_fail:
    957 	return (ret);
    958 
    959 #undef	RESET_REGISTERS
    960 }
    961 
    962 static uint8_t
    963 _dwarf_get_minlen(Dwarf_P_Debug dbg)
    964 {
    965 
    966 	assert(dbg != NULL);
    967 
    968 	switch (dbg->dbgp_isa) {
    969 	case DW_ISA_ARM:
    970 		return (2);
    971 	case DW_ISA_X86:
    972 	case DW_ISA_X86_64:
    973 		return (1);
    974 	default:
    975 		return (4);
    976 	}
    977 }
    978 
    979 static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
    980 
    981 int
    982 _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
    983 {
    984 	Dwarf_LineInfo li;
    985 	Dwarf_LineFile lf;
    986 	Dwarf_P_Section ds;
    987 	Dwarf_Rel_Section drs;
    988 	Dwarf_Unsigned offset;
    989 	int i, ret;
    990 
    991 	assert(dbg != NULL && dbg->dbgp_lineinfo != NULL);
    992 
    993 	li = dbg->dbgp_lineinfo;
    994 	if (STAILQ_EMPTY(&li->li_lnlist))
    995 		return (DW_DLE_NONE);
    996 
    997 	li->li_length = 0;
    998 	li->li_version = 2;
    999 	li->li_hdrlen = 0;
   1000 	li->li_minlen = _dwarf_get_minlen(dbg);
   1001 	li->li_defstmt = 1;
   1002 	li->li_lbase = -5;
   1003 	li->li_lrange = 14;
   1004 	li->li_opbase = 10;
   1005 
   1006 	/* Create .debug_line section. */
   1007 	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) !=
   1008 	    DW_DLE_NONE)
   1009 		return (ret);
   1010 
   1011 	/* Create relocation section for .debug_line */
   1012 	if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) !=
   1013 	    DW_DLE_NONE)
   1014 		goto gen_fail1;
   1015 
   1016 	/* Length placeholder. (We only use 32-bit DWARF format) */
   1017 	RCHECK(WRITE_VALUE(0, 4));
   1018 
   1019 	/* Write line number dwarf version. (DWARF2) */
   1020 	RCHECK(WRITE_VALUE(li->li_version, 2));
   1021 
   1022 	/* Header length placeholder. */
   1023 	offset = ds->ds_size;
   1024 	RCHECK(WRITE_VALUE(li->li_hdrlen, 4));
   1025 
   1026 	/* Write minimum instruction length. */
   1027 	RCHECK(WRITE_VALUE(li->li_minlen, 1));
   1028 
   1029 	/*
   1030 	 * Write initial value for is_stmt. XXX Which default value we
   1031 	 * should use?
   1032 	 */
   1033 	RCHECK(WRITE_VALUE(li->li_defstmt, 1));
   1034 
   1035 	/*
   1036 	 * Write line_base and line_range. FIXME These value needs to be
   1037 	 * fine tuned.
   1038 	 */
   1039 	RCHECK(WRITE_VALUE(li->li_lbase, 1));
   1040 	RCHECK(WRITE_VALUE(li->li_lrange, 1));
   1041 
   1042 	/* Write opcode_base. (DWARF2) */
   1043 	RCHECK(WRITE_VALUE(li->li_opbase, 1));
   1044 
   1045 	/* Write standard op length array. */
   1046 	RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0])));
   1047 
   1048 	/* Write the list of include directories. */
   1049 	for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
   1050 		RCHECK(WRITE_STRING(li->li_incdirs[i]));
   1051 	RCHECK(WRITE_VALUE(0, 1));
   1052 
   1053 	/* Write the list of filenames. */
   1054 	STAILQ_FOREACH(lf, &li->li_lflist, lf_next) {
   1055 		RCHECK(WRITE_STRING(lf->lf_fname));
   1056 		RCHECK(WRITE_ULEB128(lf->lf_dirndx));
   1057 		RCHECK(WRITE_ULEB128(lf->lf_mtime));
   1058 		RCHECK(WRITE_ULEB128(lf->lf_size));
   1059 	}
   1060 	RCHECK(WRITE_VALUE(0, 1));
   1061 
   1062 	/* Fill in the header length. */
   1063 	li->li_hdrlen = ds->ds_size - offset - 4;
   1064 	dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4);
   1065 
   1066 	/* Generate the line number program. */
   1067 	RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error));
   1068 
   1069 	/* Fill in the length of this line info. */
   1070 	li->li_length = ds->ds_size - 4;
   1071 	offset = 0;
   1072 	dbg->write(ds->ds_data, &offset, li->li_length, 4);
   1073 
   1074 	/* Notify the creation of .debug_line ELF section. */
   1075 	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
   1076 
   1077 	/* Finalize relocation section for .debug_line. */
   1078 	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
   1079 
   1080 	return (DW_DLE_NONE);
   1081 
   1082 gen_fail:
   1083 	_dwarf_reloc_section_free(dbg, &drs);
   1084 
   1085 gen_fail1:
   1086 	_dwarf_section_free(dbg, &ds);
   1087 
   1088 	return (ret);
   1089 }
   1090 
   1091 void
   1092 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)
   1093 {
   1094 	Dwarf_LineInfo li;
   1095 	Dwarf_LineFile lf, tlf;
   1096 	Dwarf_Line ln, tln;
   1097 	int i;
   1098 
   1099 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
   1100 	if (dbg->dbgp_lineinfo == NULL)
   1101 		return;
   1102 
   1103 	li = dbg->dbgp_lineinfo;
   1104 	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
   1105 		STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile,
   1106 		    lf_next);
   1107 		if (lf->lf_fname)
   1108 			free(lf->lf_fname);
   1109 		free(lf);
   1110 	}
   1111 	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
   1112 		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
   1113 		free(ln);
   1114 	}
   1115 	if (li->li_incdirs) {
   1116 		for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
   1117 			free(li->li_incdirs[i]);
   1118 		free(li->li_incdirs);
   1119 	}
   1120 	free(li);
   1121 	dbg->dbgp_lineinfo = NULL;
   1122 }
   1123