xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/libdwarf_lineno.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
1 /*	$NetBSD: libdwarf_lineno.c,v 1.5 2024/03/03 17:37:32 christos 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.5 2024/03/03 17:37:32 christos Exp $");
32 ELFTC_VCSID("Id: libdwarf_lineno.c 4019 2023-10-22 03:06:17Z kaiwang27");
33 
34 static int
_dwarf_lineno_make_fullpath(Dwarf_Debug dbg,Dwarf_LineInfo li,Dwarf_LineFile lf,const char * compdir,Dwarf_Error * error)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
_dwarf_lineno_add_file(Dwarf_LineInfo li,uint8_t ** p,const char * compdir,Dwarf_Error * error,Dwarf_Debug dbg)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
_dwarf_lineno_run_program(Dwarf_CU cu,Dwarf_LineInfo li,uint8_t * p,uint8_t * pe,const char * compdir,Dwarf_Error * error)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
_dwarf_lineno_parse_lnct_desc(Dwarf_Debug dbg,int fmt,struct lnct ** lnct,uint8_t * data,uint64_t * offsetp,Dwarf_Error * error)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
_dwarf_lineno_lnct_path(Dwarf_Debug dbg,char ** fname,unsigned form,uint8_t * data,uint64_t size,uint64_t * offsetp,int dwarf_size,Dwarf_Error * error)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
_dwarf_lineno_lnct_dirndx(Dwarf_Debug dbg,Dwarf_Unsigned * dirndx,unsigned form,uint8_t * data,uint64_t * offsetp,Dwarf_Error * error)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
_dwarf_lineno_lnct_timestamp(Dwarf_Debug dbg,Dwarf_Unsigned * ts,unsigned form,uint8_t * data,uint64_t * offsetp,Dwarf_Error * error)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
_dwarf_lineno_lnct_size(Dwarf_Debug dbg,Dwarf_Unsigned * sz,unsigned form,uint8_t * data,uint64_t * offsetp,Dwarf_Error * error)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
_dwarf_lineno_lnct_md5(Dwarf_Debug dbg,Dwarf_Form_Data16 * md5,unsigned form,uint8_t * data,uint64_t * offsetp,Dwarf_Error * error)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
_dwarf_lineno_init(Dwarf_Die die,uint64_t offset,Dwarf_Error * error)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 	const char *compdir;
447 	uint64_t length, hdroff, endoff;
448 	uint8_t *p;
449 	int dwarf_size, fmt, i, j, ret;
450 
451 	cu = die->die_cu;
452 	assert(cu != NULL);
453 
454 	dbg = cu->cu_dbg;
455 	assert(dbg != NULL);
456 
457 	if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL)
458 		return (DW_DLE_NONE);
459 
460 	/*
461 	 * Try to find out the dir where the CU was compiled. Later we
462 	 * will use the dir to create full pathnames, if need.
463 	 */
464 	compdir = NULL;
465 	at = _dwarf_attr_find(die, DW_AT_comp_dir);
466 	if (at != NULL) {
467 		switch (at->at_form) {
468 		case DW_FORM_strp:
469 		case DW_FORM_strp_sup:
470 		case DW_FORM_line_strp:
471 			compdir = at->u[1].s;
472 			break;
473 		case DW_FORM_string:
474 			compdir = at->u[0].s;
475 			break;
476 		default:
477 			break;
478 		}
479 	}
480 
481 	length = dbg->read(ds->ds_data, &offset, 4);
482 	if (length == 0xffffffff) {
483 		dwarf_size = 8;
484 		length = dbg->read(ds->ds_data, &offset, 8);
485 	} else
486 		dwarf_size = 4;
487 
488 	if (length > ds->ds_size - offset) {
489 		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
490 		return (DW_DLE_DEBUG_LINE_LENGTH_BAD);
491 	}
492 
493 	if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) {
494 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
495 		return (DW_DLE_MEMORY);
496 	}
497 
498 	/*
499 	 * Read in line number program header.
500 	 */
501 	li->li_length = length;
502 	endoff = offset + length;
503 	li->li_version = dbg->read(ds->ds_data, &offset, 2);
504 	if (li->li_version == 5) {
505 		(void) dbg->read(ds->ds_data, &offset, 1); /* TODO */
506 		(void) dbg->read(ds->ds_data, &offset, 1); /* TODO */
507 	}
508 	li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size);
509 	hdroff = offset;
510 	li->li_minlen = dbg->read(ds->ds_data, &offset, 1);
511 	if (li->li_version >= 4)
512 		li->li_maxop = dbg->read(ds->ds_data, &offset, 1);
513 	li->li_defstmt = dbg->read(ds->ds_data, &offset, 1);
514 	li->li_lbase = dbg->read(ds->ds_data, &offset, 1);
515 	li->li_lrange = dbg->read(ds->ds_data, &offset, 1);
516 	li->li_opbase = dbg->read(ds->ds_data, &offset, 1);
517 	STAILQ_INIT(&li->li_lflist);
518 	STAILQ_INIT(&li->li_lnlist);
519 
520 	if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) {
521 		ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
522 		DWARF_SET_ERROR(dbg, error, ret);
523 		goto fail_cleanup;
524 	}
525 
526 	if ((li->li_oplen = malloc(li->li_opbase)) == NULL) {
527 		ret = DW_DLE_MEMORY;
528 		DWARF_SET_ERROR(dbg, error, ret);
529 		goto fail_cleanup;
530 	}
531 
532 	/*
533 	 * Read in std opcode arg length list. Note that the first
534 	 * element is not used.
535 	 */
536 	for (i = 1; i < li->li_opbase; i++)
537 		li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1);
538 
539 	/*
540 	 * Directory and filename parser for DWARF4 and below.
541 	 */
542 	if (li->li_version <= 4) {
543 
544 		/*
545 		 * Check how many strings in the include dir string array.
546 		 */
547 		length = 0;
548 		p = ds->ds_data + offset;
549 		while (*p != '\0') {
550 			while (*p++ != '\0')
551 				;
552 			length++;
553 		}
554 		li->li_inclen = length;
555 
556 		/* Sanity check. */
557 		if (p - ds->ds_data > (int) ds->ds_size) {
558 			ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
559 			DWARF_SET_ERROR(dbg, error, ret);
560 			goto fail_cleanup;
561 		}
562 
563 		if (length != 0) {
564 			if ((li->li_incdirs = malloc(length * sizeof(char *))) ==
565 			    NULL) {
566 				ret = DW_DLE_MEMORY;
567 				DWARF_SET_ERROR(dbg, error, ret);
568 				goto fail_cleanup;
569 			}
570 		}
571 
572 		/* Fill in include dir array. */
573 		i = 0;
574 		p = ds->ds_data + offset;
575 		while (*p != '\0') {
576 			li->li_incdirs[i++] = (char *) p;
577 			while (*p++ != '\0')
578 				;
579 		}
580 
581 		p++;
582 
583 		/*
584 		 * Process file list.
585 		 */
586 		while (*p != '\0') {
587 			ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg);
588 			if (ret != DW_DLE_NONE)
589 				goto fail_cleanup;
590 			if (p - ds->ds_data > (int) ds->ds_size) {
591 				ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
592 				DWARF_SET_ERROR(dbg, error, ret);
593 				goto fail_cleanup;
594 			}
595 		}
596 
597 		p++;
598 
599 		/* Sanity check. */
600 		if (p - ds->ds_data - hdroff != li->li_hdrlen) {
601 			ret = DW_DLE_DEBUG_LINE_LENGTH_BAD;
602 			DWARF_SET_ERROR(dbg, error, ret);
603 			goto fail_cleanup;
604 		}
605 
606 		goto lnprog;
607 	}
608 
609 	/*
610 	 * DWARF5 has completely overhauled the dir/source file information
611 	 * fields, which are incompatible with DWARF4 or lower.
612 	 */
613 
614 	lnct = NULL;
615 	fmt = dbg->read(ds->ds_data, &offset, 1);
616 	if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data,
617 	    &offset, error)) != DW_DLE_NONE)
618 		goto fail_cleanup;
619 
620 	li->li_inclen = dbg->read(ds->ds_data, &offset, 1);
621 	if (li->li_inclen == 0) {
622 		if (fmt > 0) {
623 			free(lnct);
624 			ret = DW_DLE_DIR_COUNT_BAD;
625 			DWARF_SET_ERROR(dbg, error, ret);
626 			goto fail_cleanup;
627 		}
628 
629 		goto file_entries;
630 	}
631 
632 	if (fmt == 0) {
633 		ret = DW_DLE_DIR_COUNT_BAD;
634 		DWARF_SET_ERROR(dbg, error, ret);
635 		goto fail_cleanup;
636 	}
637 	if ((li->li_incdirs = malloc(length * sizeof(char *))) == NULL) {
638 		free(lnct);
639 		ret = DW_DLE_MEMORY;
640 		DWARF_SET_ERROR(dbg, error, ret);
641 		goto fail_cleanup;
642 	}
643 	for (i = 0; i < li->li_inclen; i++) {
644 		for (j = 0; j < fmt; j++) {
645 			if (lnct[j].type != DW_LNCT_path) {
646 				free(lnct);
647 				ret = DW_DLE_LNCT_DESC_BAD;
648 				DWARF_SET_ERROR(dbg, error, ret);
649 				goto fail_cleanup;
650 			}
651 
652 			ret = _dwarf_lineno_lnct_path(dbg, &li->li_incdirs[i],
653 			    lnct[j].form, ds->ds_data, ds->ds_size, &offset,
654 			    dwarf_size, error);
655 			if (ret != DW_DLE_NONE) {
656 				free(lnct);
657 				goto fail_cleanup;
658 			}
659 		}
660 	}
661 	if (lnct)
662 		free(lnct);
663 
664 file_entries:
665 
666 	lnct = NULL;
667 	fmt = dbg->read(ds->ds_data, &offset, 1);
668 	if ((ret = _dwarf_lineno_parse_lnct_desc(dbg, fmt, &lnct, ds->ds_data,
669 	    &offset, error)) != DW_DLE_NONE)
670 		goto fail_cleanup;
671 
672 	li->li_lflen = dbg->read(ds->ds_data, &offset, 1);
673 	if (li->li_lflen == 0) {
674 		if (fmt > 0) {
675 			free(lnct);
676 			ret = DW_DLE_FILE_COUNT_BAD;
677 			DWARF_SET_ERROR(dbg, error, ret);
678 			goto fail_cleanup;
679 		}
680 
681 		p = ds->ds_data + offset;
682 		goto lnprog;
683 	}
684 
685 	for (i = 0; i < li->li_lflen; i++) {
686 		if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) {
687 			free(lnct);
688 			ret = DW_DLE_MEMORY;
689 			DWARF_SET_ERROR(dbg, error, ret);
690 			goto fail_cleanup;
691 		}
692 		for (j = 0; j < fmt; j++) {
693 			switch (lnct[j].type) {
694 			case DW_LNCT_path:
695 				ret = _dwarf_lineno_lnct_path(dbg,
696 				    &lf->lf_fname, lnct[j].form, ds->ds_data,
697 				    ds->ds_size, &offset, dwarf_size, error);
698 				break;
699 			case DW_LNCT_directory_index:
700 				ret = _dwarf_lineno_lnct_dirndx(dbg,
701 				    &lf->lf_dirndx, lnct[j].form, ds->ds_data,
702 				    &offset, error);
703 				break;
704 			case DW_LNCT_timestamp:
705 				ret = _dwarf_lineno_lnct_timestamp(dbg,
706 				    &lf->lf_mtime, lnct[j].form, ds->ds_data,
707 				    &offset, error);
708 				break;
709 			case DW_LNCT_size:
710 				ret = _dwarf_lineno_lnct_size(dbg,
711 				    &lf->lf_size, lnct[j].form, ds->ds_data,
712 				    &offset, error);
713 				break;
714 			case DW_LNCT_MD5:
715 				ret = _dwarf_lineno_lnct_md5(dbg,
716 				    &lf->lf_md5, lnct[j].form, ds->ds_data,
717 				    &offset, error);
718 				break;
719 			default:
720 				ret = DW_DLE_LNCT_DESC_BAD;
721 				DWARF_SET_ERROR(dbg, error, ret);
722 				break;
723 			}
724 			if (ret != DW_DLE_NONE) {
725 				free(lf);
726 				free(lnct);
727 				goto fail_cleanup;
728 			}
729 		}
730 		ret = _dwarf_lineno_make_fullpath(dbg, li, lf, compdir, error);
731 		if (ret != DW_DLE_NONE) {
732 			free(lf);
733 			free(lnct);
734 			goto fail_cleanup;
735 		}
736 		STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next);
737 	}
738 	if (lnct)
739 		free(lnct);
740 
741 	p = ds->ds_data + offset;
742 
743 lnprog:
744 	/*
745 	 * Process line number program.
746 	 */
747 	ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir,
748 	    error);
749 	if (ret != DW_DLE_NONE)
750 		goto fail_cleanup;
751 
752 	cu->cu_lineinfo = li;
753 
754 	return (DW_DLE_NONE);
755 
756 fail_cleanup:
757 
758 	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
759 		STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next);
760 		if (lf->lf_fullpath)
761 			free(lf->lf_fullpath);
762 		free(lf);
763 	}
764 
765 	if (li->li_oplen)
766 		free(li->li_oplen);
767 	if (li->li_incdirs)
768 		free(li->li_incdirs);
769 	free(li);
770 
771 	return (ret);
772 }
773 
774 void
_dwarf_lineno_cleanup(Dwarf_LineInfo li)775 _dwarf_lineno_cleanup(Dwarf_LineInfo li)
776 {
777 	Dwarf_LineFile lf, tlf;
778 	Dwarf_Line ln, tln;
779 
780 	if (li == NULL)
781 		return;
782 	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
783 		STAILQ_REMOVE(&li->li_lflist, lf,
784 		    _Dwarf_LineFile, lf_next);
785 		if (lf->lf_fullpath)
786 			free(lf->lf_fullpath);
787 		free(lf);
788 	}
789 	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
790 		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line,
791 		    ln_next);
792 		free(ln);
793 	}
794 	if (li->li_oplen)
795 		free(li->li_oplen);
796 	if (li->li_incdirs)
797 		free(li->li_incdirs);
798 	if (li->li_lnarray)
799 		free(li->li_lnarray);
800 	if (li->li_lfnarray)
801 		free(li->li_lfnarray);
802 	free(li);
803 }
804 
805 static int
_dwarf_lineno_gen_program(Dwarf_P_Debug dbg,Dwarf_P_Section ds,Dwarf_Rel_Section drs,Dwarf_Error * error)806 _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
807     Dwarf_Rel_Section drs, Dwarf_Error * error)
808 {
809 	Dwarf_LineInfo li;
810 	Dwarf_Line ln;
811 	Dwarf_Unsigned address, file, line, spc;
812 	Dwarf_Unsigned addr0, maddr;
813 	Dwarf_Signed line0, column;
814 	int is_stmt, basic_block;
815 	int need_copy;
816 	int ret;
817 
818 #define	RESET_REGISTERS						\
819 	do {							\
820 		address	       = 0;				\
821 		file	       = 1;				\
822 		line	       = 1;				\
823 		column	       = 0;				\
824 		is_stmt	       = li->li_defstmt;		\
825 		basic_block    = 0;				\
826 	} while(0)
827 
828 	li = dbg->dbgp_lineinfo;
829 	maddr = (255 - li->li_opbase) / li->li_lrange;
830 
831 	RESET_REGISTERS;
832 
833 	STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) {
834 		if (ln->ln_symndx > 0) {
835 			/*
836 			 * Generate DW_LNE_set_address extended op.
837 			 */
838 			RCHECK(WRITE_VALUE(0, 1));
839 			RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1));
840 			RCHECK(WRITE_VALUE(DW_LNE_set_address, 1));
841 			RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds,
842 			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
843 			    ds->ds_size, ln->ln_symndx, ln->ln_addr,
844 			    NULL, error));
845 			address = ln->ln_addr;
846 			continue;
847 		} else if (ln->ln_endseq) {
848 			addr0 = (ln->ln_addr - address) / li->li_minlen;
849 			if (addr0 != 0) {
850 				RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
851 				RCHECK(WRITE_ULEB128(addr0));
852 			}
853 
854 			/*
855 			 * Generate DW_LNE_end_sequence.
856 			 */
857 			RCHECK(WRITE_VALUE(0, 1));
858 			RCHECK(WRITE_ULEB128(1));
859 			RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1));
860 			RESET_REGISTERS;
861 			continue;
862 		}
863 
864 		/*
865 		 * Generate standard opcodes for file, column, is_stmt or
866 		 * basic_block changes.
867 		 */
868 		if (ln->ln_fileno != file) {
869 			RCHECK(WRITE_VALUE(DW_LNS_set_file, 1));
870 			RCHECK(WRITE_ULEB128(ln->ln_fileno));
871 			file = ln->ln_fileno;
872 		}
873 		if (ln->ln_column != column) {
874 			RCHECK(WRITE_VALUE(DW_LNS_set_column, 1));
875 			RCHECK(WRITE_ULEB128(ln->ln_column));
876 			column = ln->ln_column;
877 		}
878 		if (ln->ln_stmt != is_stmt) {
879 			RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1));
880 			is_stmt = ln->ln_stmt;
881 		}
882 		if (ln->ln_bblock && !basic_block) {
883 			RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1));
884 			basic_block = 1;
885 		}
886 
887 		/*
888 		 * Calculate address and line number change.
889 		 */
890 		addr0 = (ln->ln_addr - address) / li->li_minlen;
891 		line0 = ln->ln_lineno - line;
892 
893 		if (addr0 == 0 && line0 == 0)
894 			continue;
895 
896 		/*
897 		 * Check if line delta is with the range and if the special
898 		 * opcode can be used.
899 		 */
900 		assert(li->li_lbase <= 0);
901 		if (line0 >= li->li_lbase &&
902 		    line0 <= li->li_lbase + li->li_lrange - 1) {
903 			spc = (line0 - li->li_lbase) +
904 			    (li->li_lrange * addr0) + li->li_opbase;
905 			if (spc <= 255) {
906 				RCHECK(WRITE_VALUE(spc, 1));
907 				basic_block = 0;
908 				goto next_line;
909 			}
910 		}
911 
912 		/* Generate DW_LNS_advance_line for line number change. */
913 		if (line0 != 0) {
914 			RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1));
915 			RCHECK(WRITE_SLEB128(line0));
916 			line0 = 0;
917 			need_copy = 1;
918 		} else
919 			need_copy = basic_block;
920 
921 		if (addr0 != 0) {
922 			/* See if it can be handled by DW_LNS_const_add_pc. */
923 			spc = (line0 - li->li_lbase) +
924 			    (li->li_lrange * (addr0 - maddr)) + li->li_opbase;
925 			if (addr0 >= maddr && spc <= 255) {
926 				RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1));
927 				RCHECK(WRITE_VALUE(spc, 1));
928 			} else {
929 				/* Otherwise we use DW_LNS_advance_pc. */
930 				RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1));
931 				RCHECK(WRITE_ULEB128(addr0));
932 			}
933 		}
934 
935 		if (need_copy) {
936 			RCHECK(WRITE_VALUE(DW_LNS_copy, 1));
937 			basic_block = 0;
938 		}
939 
940 	next_line:
941 		address = ln->ln_addr;
942 		line = ln->ln_lineno;
943 	}
944 
945 	return (DW_DLE_NONE);
946 
947 gen_fail:
948 	return (ret);
949 
950 #undef	RESET_REGISTERS
951 }
952 
953 static uint8_t
_dwarf_get_minlen(Dwarf_P_Debug dbg)954 _dwarf_get_minlen(Dwarf_P_Debug dbg)
955 {
956 
957 	assert(dbg != NULL);
958 
959 	switch (dbg->dbgp_isa) {
960 	case DW_ISA_ARM:
961 		return (2);
962 	case DW_ISA_X86:
963 	case DW_ISA_X86_64:
964 		return (1);
965 	default:
966 		return (4);
967 	}
968 }
969 
970 static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1};
971 
972 int
_dwarf_lineno_gen(Dwarf_P_Debug dbg,Dwarf_Error * error)973 _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
974 {
975 	Dwarf_LineInfo li;
976 	Dwarf_LineFile lf;
977 	Dwarf_P_Section ds;
978 	Dwarf_Rel_Section drs;
979 	Dwarf_Unsigned offset;
980 	int i, ret;
981 
982 	assert(dbg != NULL && dbg->dbgp_lineinfo != NULL);
983 
984 	li = dbg->dbgp_lineinfo;
985 	if (STAILQ_EMPTY(&li->li_lnlist))
986 		return (DW_DLE_NONE);
987 
988 	li->li_length = 0;
989 	li->li_version = 2;
990 	li->li_hdrlen = 0;
991 	li->li_minlen = _dwarf_get_minlen(dbg);
992 	li->li_defstmt = 1;
993 	li->li_lbase = -5;
994 	li->li_lrange = 14;
995 	li->li_opbase = 10;
996 
997 	/* Create .debug_line section. */
998 	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) !=
999 	    DW_DLE_NONE)
1000 		return (ret);
1001 
1002 	/* Create relocation section for .debug_line */
1003 	if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) !=
1004 	    DW_DLE_NONE)
1005 		goto gen_fail1;
1006 
1007 	/* Length placeholder. (We only use 32-bit DWARF format) */
1008 	RCHECK(WRITE_VALUE(0, 4));
1009 
1010 	/* Write line number dwarf version. (DWARF2) */
1011 	RCHECK(WRITE_VALUE(li->li_version, 2));
1012 
1013 	/* Header length placeholder. */
1014 	offset = ds->ds_size;
1015 	RCHECK(WRITE_VALUE(li->li_hdrlen, 4));
1016 
1017 	/* Write minimum instruction length. */
1018 	RCHECK(WRITE_VALUE(li->li_minlen, 1));
1019 
1020 	/*
1021 	 * Write initial value for is_stmt. XXX Which default value we
1022 	 * should use?
1023 	 */
1024 	RCHECK(WRITE_VALUE(li->li_defstmt, 1));
1025 
1026 	/*
1027 	 * Write line_base and line_range. FIXME These value needs to be
1028 	 * fine tuned.
1029 	 */
1030 	RCHECK(WRITE_VALUE(li->li_lbase, 1));
1031 	RCHECK(WRITE_VALUE(li->li_lrange, 1));
1032 
1033 	/* Write opcode_base. (DWARF2) */
1034 	RCHECK(WRITE_VALUE(li->li_opbase, 1));
1035 
1036 	/* Write standard op length array. */
1037 	RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0])));
1038 
1039 	/* Write the list of include directories. */
1040 	for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
1041 		RCHECK(WRITE_STRING(li->li_incdirs[i]));
1042 	RCHECK(WRITE_VALUE(0, 1));
1043 
1044 	/* Write the list of filenames. */
1045 	STAILQ_FOREACH(lf, &li->li_lflist, lf_next) {
1046 		RCHECK(WRITE_STRING(lf->lf_fname));
1047 		RCHECK(WRITE_ULEB128(lf->lf_dirndx));
1048 		RCHECK(WRITE_ULEB128(lf->lf_mtime));
1049 		RCHECK(WRITE_ULEB128(lf->lf_size));
1050 	}
1051 	RCHECK(WRITE_VALUE(0, 1));
1052 
1053 	/* Fill in the header length. */
1054 	li->li_hdrlen = ds->ds_size - offset - 4;
1055 	dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4);
1056 
1057 	/* Generate the line number program. */
1058 	RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error));
1059 
1060 	/* Fill in the length of this line info. */
1061 	li->li_length = ds->ds_size - 4;
1062 	offset = 0;
1063 	dbg->write(ds->ds_data, &offset, li->li_length, 4);
1064 
1065 	/* Notify the creation of .debug_line ELF section. */
1066 	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
1067 
1068 	/* Finalize relocation section for .debug_line. */
1069 	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
1070 
1071 	return (DW_DLE_NONE);
1072 
1073 gen_fail:
1074 	_dwarf_reloc_section_free(dbg, &drs);
1075 
1076 gen_fail1:
1077 	_dwarf_section_free(dbg, &ds);
1078 
1079 	return (ret);
1080 }
1081 
1082 void
_dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)1083 _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg)
1084 {
1085 	Dwarf_LineInfo li;
1086 	Dwarf_LineFile lf, tlf;
1087 	Dwarf_Line ln, tln;
1088 	int i;
1089 
1090 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
1091 	if (dbg->dbgp_lineinfo == NULL)
1092 		return;
1093 
1094 	li = dbg->dbgp_lineinfo;
1095 	STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) {
1096 		STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile,
1097 		    lf_next);
1098 		if (lf->lf_fname)
1099 			free(lf->lf_fname);
1100 		free(lf);
1101 	}
1102 	STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) {
1103 		STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next);
1104 		free(ln);
1105 	}
1106 	if (li->li_incdirs) {
1107 		for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++)
1108 			free(li->li_incdirs[i]);
1109 		free(li->li_incdirs);
1110 	}
1111 	free(li);
1112 	dbg->dbgp_lineinfo = NULL;
1113 }
1114