xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/libdwarf_frame.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /*	$NetBSD: libdwarf_frame.c,v 1.4 2022/05/01 17:20:47 jkoshy Exp $	*/
2 
3 /*-
4  * Copyright (c) 2009-2011,2014 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_frame.c,v 1.4 2022/05/01 17:20:47 jkoshy Exp $");
32 ELFTC_VCSID("Id: libdwarf_frame.c 3106 2014-12-19 16:00:58Z kaiwang27");
33 
34 static int
35 _dwarf_frame_find_cie(Dwarf_FrameSec fs, Dwarf_Unsigned offset,
36     Dwarf_Cie *ret_cie)
37 {
38 	Dwarf_Cie cie;
39 
40 	STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
41 		if (cie->cie_offset == offset)
42 			break;
43 	}
44 
45 	if (cie == NULL)
46 		return (DW_DLE_NO_ENTRY);
47 
48 	if (ret_cie != NULL)
49 		*ret_cie = cie;
50 
51 	return (DW_DLE_NONE);
52 }
53 
54 static int
55 _dwarf_frame_read_lsb_encoded(Dwarf_Debug dbg, Dwarf_Cie cie, uint64_t *val,
56     uint8_t *data, uint64_t *offsetp, uint8_t encode, Dwarf_Addr pc,
57     Dwarf_Error *error)
58 {
59 	uint8_t application;
60 
61 	if (encode == DW_EH_PE_omit)
62 		return (DW_DLE_NONE);
63 
64 	application = encode & 0xf0;
65 	encode &= 0x0f;
66 
67 	switch (encode) {
68 	case DW_EH_PE_absptr:
69 		*val = dbg->read(data, offsetp, cie->cie_addrsize);
70 		break;
71 	case DW_EH_PE_uleb128:
72 		*val = _dwarf_read_uleb128(data, offsetp);
73 		break;
74 	case DW_EH_PE_udata2:
75 		*val = dbg->read(data, offsetp, 2);
76 		break;
77 	case DW_EH_PE_udata4:
78 		*val = dbg->read(data, offsetp, 4);
79 		break;
80 	case DW_EH_PE_udata8:
81 		*val = dbg->read(data, offsetp, 8);
82 		break;
83 	case DW_EH_PE_sleb128:
84 		*val = _dwarf_read_sleb128(data, offsetp);
85 		break;
86 	case DW_EH_PE_sdata2:
87 		*val = (int16_t) dbg->read(data, offsetp, 2);
88 		break;
89 	case DW_EH_PE_sdata4:
90 		*val = (int32_t) dbg->read(data, offsetp, 4);
91 		break;
92 	case DW_EH_PE_sdata8:
93 		*val = dbg->read(data, offsetp, 8);
94 		break;
95 	default:
96 		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
97 		return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
98 	}
99 
100 	if (application == DW_EH_PE_pcrel) {
101 		/*
102 		 * Value is relative to .eh_frame section virtual addr.
103 		 */
104 		switch (encode) {
105 		case DW_EH_PE_uleb128:
106 		case DW_EH_PE_udata2:
107 		case DW_EH_PE_udata4:
108 		case DW_EH_PE_udata8:
109 			*val += pc;
110 			break;
111 		case DW_EH_PE_sleb128:
112 		case DW_EH_PE_sdata2:
113 		case DW_EH_PE_sdata4:
114 		case DW_EH_PE_sdata8:
115 			*val = pc + (int64_t) *val;
116 			break;
117 		default:
118 			/* DW_EH_PE_absptr is absolute value. */
119 			break;
120 		}
121 	}
122 
123 	/* XXX Applications other than DW_EH_PE_pcrel are not handled. */
124 
125 	return (DW_DLE_NONE);
126 }
127 
128 static int
129 _dwarf_frame_parse_lsb_cie_augment(Dwarf_Debug dbg, Dwarf_Cie cie,
130     Dwarf_Error *error)
131 {
132 	uint8_t *aug_p, *augdata_p;
133 	uint64_t val, offset;
134 	uint8_t encode;
135 	int ret;
136 
137 	assert(cie->cie_augment != NULL && *cie->cie_augment == 'z');
138 
139 	/*
140 	 * Here we're only interested in the presence of augment 'R'
141 	 * and associated CIE augment data, which describes the
142 	 * encoding scheme of FDE PC begin and range.
143 	 */
144 	aug_p = &cie->cie_augment[1];
145 	augdata_p = cie->cie_augdata;
146 	while (*aug_p != '\0') {
147 		switch (*aug_p) {
148 		case 'L':
149 			/* Skip one augment in augment data. */
150 			augdata_p++;
151 			break;
152 		case 'P':
153 			/* Skip two augments in augment data. */
154 			encode = *augdata_p++;
155 			offset = 0;
156 			ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
157 			    augdata_p, &offset, encode, 0, error);
158 			if (ret != DW_DLE_NONE)
159 				return (ret);
160 			augdata_p += offset;
161 			break;
162 		case 'R':
163 			cie->cie_fde_encode = *augdata_p++;
164 			break;
165 		default:
166 			DWARF_SET_ERROR(dbg, error,
167 			    DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
168 			return (DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
169 		}
170 		aug_p++;
171 	}
172 
173 	return (DW_DLE_NONE);
174 }
175 
176 static int
177 _dwarf_frame_add_cie(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
178     Dwarf_Unsigned *off, Dwarf_Cie *ret_cie, Dwarf_Error *error)
179 {
180 	Dwarf_Cie cie;
181 	uint64_t length;
182 	int dwarf_size, ret;
183 	char *p;
184 
185 	/* Check if we already added this CIE. */
186 	if (_dwarf_frame_find_cie(fs, *off, &cie) != DW_DLE_NO_ENTRY) {
187 		*off += cie->cie_length + 4;
188 		return (DW_DLE_NONE);
189 	}
190 
191 	if ((cie = calloc(1, sizeof(struct _Dwarf_Cie))) == NULL) {
192 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
193 		return (DW_DLE_MEMORY);
194 	}
195 	STAILQ_INSERT_TAIL(&fs->fs_cielist, cie, cie_next);
196 
197 	cie->cie_dbg = dbg;
198 	cie->cie_index = fs->fs_cielen;
199 	cie->cie_offset = *off;
200 
201 	length = dbg->read(ds->ds_data, off, 4);
202 	if (length == 0xffffffff) {
203 		dwarf_size = 8;
204 		length = dbg->read(ds->ds_data, off, 8);
205 	} else
206 		dwarf_size = 4;
207 
208 	if (length > ds->ds_size - *off) {
209 		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
210 		return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
211 	}
212 
213 	(void) dbg->read(ds->ds_data, off, dwarf_size); /* Skip CIE id. */
214 	cie->cie_length = length;
215 
216 	cie->cie_version = dbg->read(ds->ds_data, off, 1);
217 	if (cie->cie_version != 1 && cie->cie_version != 3 &&
218 	    cie->cie_version != 4) {
219 		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_VERSION_BAD);
220 		return (DW_DLE_FRAME_VERSION_BAD);
221 	}
222 
223 	cie->cie_augment = ds->ds_data + *off;
224 	p = (char *) ds->ds_data;
225 	while (p[(*off)++] != '\0')
226 		;
227 
228 	/* We only recognize normal .dwarf_frame and GNU .eh_frame sections. */
229 	if (*cie->cie_augment != 0 && *cie->cie_augment != 'z') {
230 		*off = cie->cie_offset + ((dwarf_size == 4) ? 4 : 12) +
231 		    cie->cie_length;
232 		return (DW_DLE_NONE);
233 	}
234 
235 	/* Optional EH Data field for .eh_frame section. */
236 	if (strstr((char *)cie->cie_augment, "eh") != NULL)
237 		cie->cie_ehdata = dbg->read(ds->ds_data, off,
238 		    dbg->dbg_pointer_size);
239 
240 	/* DWARF4 added "address_size" and "segment_size". */
241 	if (cie->cie_version == 4) {
242 		cie->cie_addrsize = dbg->read(ds->ds_data, off, 1);
243 		cie->cie_segmentsize = dbg->read(ds->ds_data, off, 1);
244 	} else {
245 		/*
246 		 * Otherwise (DWARF[23]) we just set CIE addrsize to the
247 		 * debug context pointer size.
248 		 */
249 		cie->cie_addrsize = dbg->dbg_pointer_size;
250 	}
251 
252 	cie->cie_caf = _dwarf_read_uleb128(ds->ds_data, off);
253 	cie->cie_daf = _dwarf_read_sleb128(ds->ds_data, off);
254 
255 	/* Return address register. */
256 	if (cie->cie_version == 1)
257 		cie->cie_ra = dbg->read(ds->ds_data, off, 1);
258 	else
259 		cie->cie_ra = _dwarf_read_uleb128(ds->ds_data, off);
260 
261 	/* Optional CIE augmentation data for .eh_frame section. */
262 	if (*cie->cie_augment == 'z') {
263 		cie->cie_auglen = _dwarf_read_uleb128(ds->ds_data, off);
264 		cie->cie_augdata = ds->ds_data + *off;
265 		*off += cie->cie_auglen;
266 		/*
267 		 * XXX Use DW_EH_PE_absptr for default FDE PC start/range,
268 		 * in case _dwarf_frame_parse_lsb_cie_augment fails to
269 		 * find out the real encode.
270 		 */
271 		cie->cie_fde_encode = DW_EH_PE_absptr;
272 		ret = _dwarf_frame_parse_lsb_cie_augment(dbg, cie, error);
273 		if (ret != DW_DLE_NONE)
274 			return (ret);
275 	}
276 
277 	/* CIE Initial instructions. */
278 	cie->cie_initinst = ds->ds_data + *off;
279 	if (dwarf_size == 4)
280 		cie->cie_instlen = cie->cie_offset + 4 + length - *off;
281 	else
282 		cie->cie_instlen = cie->cie_offset + 12 + length - *off;
283 
284 	*off += cie->cie_instlen;
285 
286 #ifdef FRAME_DEBUG
287 	printf("cie:\n");
288 	printf("\tcie_version=%u cie_offset=%ju cie_length=%ju cie_augment=%s"
289 	    " cie_instlen=%ju cie->cie_caf=%ju cie->cie_daf=%jd off=%ju\n",
290 	    cie->cie_version, cie->cie_offset, cie->cie_length,
291 	    (char *)cie->cie_augment, cie->cie_instlen, cie->cie_caf,
292 	    cie->cie_daf, *off);
293 #endif
294 
295 	if (ret_cie != NULL)
296 		*ret_cie = cie;
297 
298 	fs->fs_cielen++;
299 
300 	return (DW_DLE_NONE);
301 }
302 
303 static int
304 _dwarf_frame_add_fde(Dwarf_Debug dbg, Dwarf_FrameSec fs, Dwarf_Section *ds,
305     Dwarf_Unsigned *off, int eh_frame, Dwarf_Error *error)
306 {
307 	Dwarf_Cie cie;
308 	Dwarf_Fde fde;
309 	Dwarf_Unsigned cieoff;
310 	uint64_t length, val;
311 	int dwarf_size, ret;
312 
313 	if ((fde = calloc(1, sizeof(struct _Dwarf_Fde))) == NULL) {
314 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
315 		return (DW_DLE_MEMORY);
316 	}
317 	STAILQ_INSERT_TAIL(&fs->fs_fdelist, fde, fde_next);
318 
319 	fde->fde_dbg = dbg;
320 	fde->fde_fs = fs;
321 	fde->fde_addr = ds->ds_data + *off;
322 	fde->fde_offset = *off;
323 
324 	length = dbg->read(ds->ds_data, off, 4);
325 	if (length == 0xffffffff) {
326 		dwarf_size = 8;
327 		length = dbg->read(ds->ds_data, off, 8);
328 	} else
329 		dwarf_size = 4;
330 
331 	if (length > ds->ds_size - *off) {
332 		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
333 		return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
334 	}
335 
336 	fde->fde_length = length;
337 
338 	if (eh_frame) {
339 		fde->fde_cieoff = dbg->read(ds->ds_data, off, 4);
340 		cieoff = *off - (4 + fde->fde_cieoff);
341 		/* This delta should never be 0. */
342 		if (cieoff == fde->fde_offset) {
343 			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_CIE_FOR_FDE);
344 			return (DW_DLE_NO_CIE_FOR_FDE);
345 		}
346 	} else {
347 		fde->fde_cieoff = dbg->read(ds->ds_data, off, dwarf_size);
348 		cieoff = fde->fde_cieoff;
349 	}
350 
351 	if (_dwarf_frame_find_cie(fs, cieoff, &cie) ==
352 	    DW_DLE_NO_ENTRY) {
353 		ret = _dwarf_frame_add_cie(dbg, fs, ds, &cieoff, &cie,
354 		    error);
355 		if (ret != DW_DLE_NONE)
356 			return (ret);
357 	}
358 	fde->fde_cie = cie;
359 	if (eh_frame) {
360 		/*
361 		 * The FDE PC start/range for .eh_frame is encoded according
362 		 * to the LSB spec's extension to DWARF2.
363 		 */
364 		ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
365 		    ds->ds_data, off, cie->cie_fde_encode, ds->ds_addr + *off,
366 		    error);
367 		if (ret != DW_DLE_NONE)
368 			return (ret);
369 		fde->fde_initloc = val;
370 		/*
371 		 * FDE PC range should not be relative value to anything.
372 		 * So pass 0 for pc value.
373 		 */
374 		ret = _dwarf_frame_read_lsb_encoded(dbg, cie, &val,
375 		    ds->ds_data, off, cie->cie_fde_encode, 0, error);
376 		if (ret != DW_DLE_NONE)
377 			return (ret);
378 		fde->fde_adrange = val;
379 	} else {
380 		fde->fde_initloc = dbg->read(ds->ds_data, off,
381 		    cie->cie_addrsize);
382 		fde->fde_adrange = dbg->read(ds->ds_data, off,
383 		    cie->cie_addrsize);
384 	}
385 
386 	/* Optional FDE augmentation data for .eh_frame section. (ignored) */
387 	if (eh_frame && *cie->cie_augment == 'z') {
388 		fde->fde_auglen = _dwarf_read_uleb128(ds->ds_data, off);
389 		fde->fde_augdata = ds->ds_data + *off;
390 		*off += fde->fde_auglen;
391 	}
392 
393 	fde->fde_inst = ds->ds_data + *off;
394 	if (dwarf_size == 4)
395 		fde->fde_instlen = fde->fde_offset + 4 + length - *off;
396 	else
397 		fde->fde_instlen = fde->fde_offset + 12 + length - *off;
398 
399 	*off += fde->fde_instlen;
400 
401 #ifdef FRAME_DEBUG
402 	printf("fde:");
403 	if (eh_frame)
404 		printf("(eh_frame)");
405 	putchar('\n');
406 	printf("\tfde_offset=%ju fde_length=%ju fde_cieoff=%ju"
407 	    " fde_instlen=%ju off=%ju\n", fde->fde_offset, fde->fde_length,
408 	    fde->fde_cieoff, fde->fde_instlen, *off);
409 #endif
410 
411 	fs->fs_fdelen++;
412 
413 	return (DW_DLE_NONE);
414 }
415 
416 static void
417 _dwarf_frame_section_cleanup(Dwarf_FrameSec fs)
418 {
419 	Dwarf_Cie cie, tcie;
420 	Dwarf_Fde fde, tfde;
421 
422 	STAILQ_FOREACH_SAFE(cie, &fs->fs_cielist, cie_next, tcie) {
423 		STAILQ_REMOVE(&fs->fs_cielist, cie, _Dwarf_Cie, cie_next);
424 		free(cie);
425 	}
426 
427 	STAILQ_FOREACH_SAFE(fde, &fs->fs_fdelist, fde_next, tfde) {
428 		STAILQ_REMOVE(&fs->fs_fdelist, fde, _Dwarf_Fde, fde_next);
429 		free(fde);
430 	}
431 
432 	if (fs->fs_ciearray != NULL)
433 		free(fs->fs_ciearray);
434 	if (fs->fs_fdearray != NULL)
435 		free(fs->fs_fdearray);
436 
437 	free(fs);
438 }
439 
440 static int
441 _dwarf_frame_section_init(Dwarf_Debug dbg, Dwarf_FrameSec *frame_sec,
442     Dwarf_Section *ds, int eh_frame, Dwarf_Error *error)
443 {
444 	Dwarf_FrameSec fs;
445 	Dwarf_Cie cie;
446 	Dwarf_Fde fde;
447 	uint64_t length, offset, cie_id, entry_off;
448 	int dwarf_size, i, ret;
449 
450 	assert(frame_sec != NULL);
451 	assert(*frame_sec == NULL);
452 
453 	if ((fs = calloc(1, sizeof(struct _Dwarf_FrameSec))) == NULL) {
454 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
455 		return (DW_DLE_MEMORY);
456 	}
457 	STAILQ_INIT(&fs->fs_cielist);
458 	STAILQ_INIT(&fs->fs_fdelist);
459 
460 	offset = 0;
461 	while (offset < ds->ds_size) {
462 		entry_off = offset;
463 		length = dbg->read(ds->ds_data, &offset, 4);
464 		if (length == 0xffffffff) {
465 			dwarf_size = 8;
466 			length = dbg->read(ds->ds_data, &offset, 8);
467 		} else
468 			dwarf_size = 4;
469 
470 		if (length > ds->ds_size - offset ||
471 		    (length == 0 && !eh_frame)) {
472 			DWARF_SET_ERROR(dbg, error,
473 			    DW_DLE_DEBUG_FRAME_LENGTH_BAD);
474 			return (DW_DLE_DEBUG_FRAME_LENGTH_BAD);
475 		}
476 
477 		/* Check terminator for .eh_frame */
478 		if (eh_frame && length == 0)
479 			break;
480 
481 		cie_id = dbg->read(ds->ds_data, &offset, dwarf_size);
482 
483 		if (eh_frame) {
484 			/* GNU .eh_frame use CIE id 0. */
485 			if (cie_id == 0)
486 				ret = _dwarf_frame_add_cie(dbg, fs, ds,
487 				    &entry_off, NULL, error);
488 			else
489 				ret = _dwarf_frame_add_fde(dbg, fs, ds,
490 				    &entry_off, 1, error);
491 		} else {
492 			/* .dwarf_frame use CIE id ~0 */
493 			if ((dwarf_size == 4 && cie_id == ~0U) ||
494 			    (dwarf_size == 8 && cie_id == ~0ULL))
495 				ret = _dwarf_frame_add_cie(dbg, fs, ds,
496 				    &entry_off, NULL, error);
497 			else
498 				ret = _dwarf_frame_add_fde(dbg, fs, ds,
499 				    &entry_off, 0, error);
500 		}
501 
502 		if (ret != DW_DLE_NONE)
503 			goto fail_cleanup;
504 
505 		offset = entry_off;
506 	}
507 
508 	/* Create CIE array. */
509 	if (fs->fs_cielen > 0) {
510 		if ((fs->fs_ciearray = malloc(sizeof(Dwarf_Cie) *
511 		    fs->fs_cielen)) == NULL) {
512 			ret = DW_DLE_MEMORY;
513 			DWARF_SET_ERROR(dbg, error, ret);
514 			goto fail_cleanup;
515 		}
516 		i = 0;
517 		STAILQ_FOREACH(cie, &fs->fs_cielist, cie_next) {
518 			fs->fs_ciearray[i++] = cie;
519 		}
520 		assert((Dwarf_Unsigned)i == fs->fs_cielen);
521 	}
522 
523 	/* Create FDE array. */
524 	if (fs->fs_fdelen > 0) {
525 		if ((fs->fs_fdearray = malloc(sizeof(Dwarf_Fde) *
526 		    fs->fs_fdelen)) == NULL) {
527 			ret = DW_DLE_MEMORY;
528 			DWARF_SET_ERROR(dbg, error, ret);
529 			goto fail_cleanup;
530 		}
531 		i = 0;
532 		STAILQ_FOREACH(fde, &fs->fs_fdelist, fde_next) {
533 			fs->fs_fdearray[i++] = fde;
534 		}
535 		assert((Dwarf_Unsigned)i == fs->fs_fdelen);
536 	}
537 
538 	*frame_sec = fs;
539 
540 	return (DW_DLE_NONE);
541 
542 fail_cleanup:
543 
544 	_dwarf_frame_section_cleanup(fs);
545 
546 	return (ret);
547 }
548 
549 static int
550 _dwarf_frame_run_inst(Dwarf_Debug dbg, Dwarf_Regtable3 *rt, uint8_t addr_size,
551     uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf,
552     Dwarf_Addr pc, Dwarf_Addr pc_req, Dwarf_Addr *row_pc, Dwarf_Error *error)
553 {
554 	Dwarf_Regtable3 *init_rt, *saved_rt;
555 	uint8_t *p, *pe;
556 	uint8_t high2, low6;
557 	uint64_t reg, reg2, uoff, soff;
558 	int ret;
559 
560 #define	CFA	rt->rt3_cfa_rule
561 #define	INITCFA	init_rt->rt3_cfa_rule
562 #define	RL	rt->rt3_rules
563 #define	INITRL	init_rt->rt3_rules
564 
565 #define CHECK_TABLE_SIZE(x)						\
566 	do {								\
567 		if ((x) >= rt->rt3_reg_table_size) {			\
568 			DWARF_SET_ERROR(dbg, error,			\
569 			    DW_DLE_DF_REG_NUM_TOO_HIGH);		\
570 			ret = DW_DLE_DF_REG_NUM_TOO_HIGH;		\
571 			goto program_done;				\
572 		}							\
573 	} while(0)
574 
575 #ifdef FRAME_DEBUG
576 	printf("frame_run_inst: (caf=%ju, daf=%jd)\n", caf, daf);
577 #endif
578 
579 	ret = DW_DLE_NONE;
580 	init_rt = saved_rt = NULL;
581 	*row_pc = pc;
582 
583 	/* Save a copy of the table as initial state. */
584 	_dwarf_frame_regtable_copy(dbg, &init_rt, rt, error);
585 
586 	p = insts;
587 	pe = p + len;
588 
589 	while (p < pe) {
590 
591 #ifdef FRAME_DEBUG
592 		printf("p=%p pe=%p pc=%#jx pc_req=%#jx\n", p, pe, pc, pc_req);
593 #endif
594 
595 		if (*p == DW_CFA_nop) {
596 #ifdef FRAME_DEBUG
597 			printf("DW_CFA_nop\n");
598 #endif
599 			p++;
600 			continue;
601 		}
602 
603 		high2 = *p & 0xc0;
604 		low6 = *p & 0x3f;
605 		p++;
606 
607 		if (high2 > 0) {
608 			switch (high2) {
609 			case DW_CFA_advance_loc:
610 				pc += low6 * caf;
611 #ifdef FRAME_DEBUG
612 				printf("DW_CFA_advance_loc(%#jx(%u))\n", pc,
613 				    low6);
614 #endif
615 				if (pc_req < pc)
616 					goto program_done;
617 				break;
618 			case DW_CFA_offset:
619 				*row_pc = pc;
620 				CHECK_TABLE_SIZE(low6);
621 				RL[low6].dw_offset_relevant = 1;
622 				RL[low6].dw_value_type = DW_EXPR_OFFSET;
623 				RL[low6].dw_regnum = dbg->dbg_frame_cfa_value;
624 				RL[low6].dw_offset_or_block_len =
625 				    _dwarf_decode_uleb128(&p) * daf;
626 #ifdef FRAME_DEBUG
627 				printf("DW_CFA_offset(%jd)\n",
628 				    RL[low6].dw_offset_or_block_len);
629 #endif
630 				break;
631 			case DW_CFA_restore:
632 				*row_pc = pc;
633 				CHECK_TABLE_SIZE(low6);
634 				memcpy(&RL[low6], &INITRL[low6],
635 				    sizeof(Dwarf_Regtable_Entry3));
636 #ifdef FRAME_DEBUG
637 				printf("DW_CFA_restore(%u)\n", low6);
638 #endif
639 				break;
640 			default:
641 				DWARF_SET_ERROR(dbg, error,
642 				    DW_DLE_FRAME_INSTR_EXEC_ERROR);
643 				ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
644 				goto program_done;
645 			}
646 
647 			continue;
648 		}
649 
650 		switch (low6) {
651 		case DW_CFA_set_loc:
652 			pc = dbg->decode(&p, addr_size);
653 #ifdef FRAME_DEBUG
654 			printf("DW_CFA_set_loc(pc=%#jx)\n", pc);
655 #endif
656 			if (pc_req < pc)
657 				goto program_done;
658 			break;
659 		case DW_CFA_advance_loc1:
660 			pc += dbg->decode(&p, 1) * caf;
661 #ifdef FRAME_DEBUG
662 			printf("DW_CFA_set_loc1(pc=%#jx)\n", pc);
663 #endif
664 			if (pc_req < pc)
665 				goto program_done;
666 			break;
667 		case DW_CFA_advance_loc2:
668 			pc += dbg->decode(&p, 2) * caf;
669 #ifdef FRAME_DEBUG
670 			printf("DW_CFA_set_loc2(pc=%#jx)\n", pc);
671 #endif
672 			if (pc_req < pc)
673 				goto program_done;
674 			break;
675 		case DW_CFA_advance_loc4:
676 			pc += dbg->decode(&p, 4) * caf;
677 #ifdef FRAME_DEBUG
678 			printf("DW_CFA_set_loc4(pc=%#jx)\n", pc);
679 #endif
680 			if (pc_req < pc)
681 				goto program_done;
682 			break;
683 		case DW_CFA_offset_extended:
684 			*row_pc = pc;
685 			reg = _dwarf_decode_uleb128(&p);
686 			uoff = _dwarf_decode_uleb128(&p);
687 			CHECK_TABLE_SIZE(reg);
688 			RL[reg].dw_offset_relevant = 1;
689 			RL[reg].dw_value_type = DW_EXPR_OFFSET;
690 			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
691 			RL[reg].dw_offset_or_block_len = uoff * daf;
692 #ifdef FRAME_DEBUG
693 			printf("DW_CFA_offset_extended(reg=%ju,uoff=%ju)\n",
694 			    reg, uoff);
695 #endif
696 			break;
697 		case DW_CFA_restore_extended:
698 			*row_pc = pc;
699 			reg = _dwarf_decode_uleb128(&p);
700 			CHECK_TABLE_SIZE(reg);
701 			memcpy(&RL[reg], &INITRL[reg],
702 			    sizeof(Dwarf_Regtable_Entry3));
703 #ifdef FRAME_DEBUG
704 			printf("DW_CFA_restore_extended(%ju)\n", reg);
705 #endif
706 			break;
707 		case DW_CFA_undefined:
708 			*row_pc = pc;
709 			reg = _dwarf_decode_uleb128(&p);
710 			CHECK_TABLE_SIZE(reg);
711 			RL[reg].dw_offset_relevant = 0;
712 			RL[reg].dw_regnum = dbg->dbg_frame_undefined_value;
713 #ifdef FRAME_DEBUG
714 			printf("DW_CFA_undefined(%ju)\n", reg);
715 #endif
716 			break;
717 		case DW_CFA_same_value:
718 			reg = _dwarf_decode_uleb128(&p);
719 			CHECK_TABLE_SIZE(reg);
720 			RL[reg].dw_offset_relevant = 0;
721 			RL[reg].dw_regnum = dbg->dbg_frame_same_value;
722 #ifdef FRAME_DEBUG
723 			printf("DW_CFA_same_value(%ju)\n", reg);
724 #endif
725 			break;
726 		case DW_CFA_register:
727 			*row_pc = pc;
728 			reg = _dwarf_decode_uleb128(&p);
729 			reg2 = _dwarf_decode_uleb128(&p);
730 			CHECK_TABLE_SIZE(reg);
731 			RL[reg].dw_offset_relevant = 0;
732 			RL[reg].dw_regnum = reg2;
733 #ifdef FRAME_DEBUG
734 			printf("DW_CFA_register(reg=%ju,reg2=%ju)\n", reg,
735 			    reg2);
736 #endif
737 			break;
738 		case DW_CFA_remember_state:
739 			_dwarf_frame_regtable_copy(dbg, &saved_rt, rt, error);
740 #ifdef FRAME_DEBUG
741 			printf("DW_CFA_remember_state\n");
742 #endif
743 			break;
744 		case DW_CFA_restore_state:
745 			*row_pc = pc;
746 			_dwarf_frame_regtable_copy(dbg, &rt, saved_rt, error);
747 #ifdef FRAME_DEBUG
748 			printf("DW_CFA_restore_state\n");
749 #endif
750 			break;
751 		case DW_CFA_def_cfa:
752 			*row_pc = pc;
753 			reg = _dwarf_decode_uleb128(&p);
754 			uoff = _dwarf_decode_uleb128(&p);
755 			CFA.dw_offset_relevant = 1;
756 			CFA.dw_value_type = DW_EXPR_OFFSET;
757 			CFA.dw_regnum = reg;
758 			CFA.dw_offset_or_block_len = uoff;
759 #ifdef FRAME_DEBUG
760 			printf("DW_CFA_def_cfa(reg=%ju,uoff=%ju)\n", reg, uoff);
761 #endif
762 			break;
763 		case DW_CFA_def_cfa_register:
764 			*row_pc = pc;
765 			reg = _dwarf_decode_uleb128(&p);
766 			CFA.dw_regnum = reg;
767 			/*
768 			 * Note that DW_CFA_def_cfa_register change the CFA
769 			 * rule register while keep the old offset. So we
770 			 * should not touch the CFA.dw_offset_relevant flag
771 			 * here.
772 			 */
773 #ifdef FRAME_DEBUG
774 			printf("DW_CFA_def_cfa_register(%ju)\n", reg);
775 #endif
776 			break;
777 		case DW_CFA_def_cfa_offset:
778 			*row_pc = pc;
779 			uoff = _dwarf_decode_uleb128(&p);
780 			CFA.dw_offset_relevant = 1;
781 			CFA.dw_value_type = DW_EXPR_OFFSET;
782 			CFA.dw_offset_or_block_len = uoff;
783 #ifdef FRAME_DEBUG
784 			printf("DW_CFA_def_cfa_offset(%ju)\n", uoff);
785 #endif
786 			break;
787 		case DW_CFA_def_cfa_expression:
788 			*row_pc = pc;
789 			CFA.dw_offset_relevant = 0;
790 			CFA.dw_value_type = DW_EXPR_EXPRESSION;
791 			CFA.dw_offset_or_block_len = _dwarf_decode_uleb128(&p);
792 			CFA.dw_block_ptr = p;
793 			p += CFA.dw_offset_or_block_len;
794 #ifdef FRAME_DEBUG
795 			printf("DW_CFA_def_cfa_expression\n");
796 #endif
797 			break;
798 		case DW_CFA_expression:
799 			*row_pc = pc;
800 			reg = _dwarf_decode_uleb128(&p);
801 			CHECK_TABLE_SIZE(reg);
802 			RL[reg].dw_offset_relevant = 0;
803 			RL[reg].dw_value_type = DW_EXPR_EXPRESSION;
804 			RL[reg].dw_offset_or_block_len =
805 			    _dwarf_decode_uleb128(&p);
806 			RL[reg].dw_block_ptr = p;
807 			p += RL[reg].dw_offset_or_block_len;
808 #ifdef FRAME_DEBUG
809 			printf("DW_CFA_expression\n");
810 #endif
811 			break;
812 		case DW_CFA_offset_extended_sf:
813 			*row_pc = pc;
814 			reg = _dwarf_decode_uleb128(&p);
815 			soff = _dwarf_decode_sleb128(&p);
816 			CHECK_TABLE_SIZE(reg);
817 			RL[reg].dw_offset_relevant = 1;
818 			RL[reg].dw_value_type = DW_EXPR_OFFSET;
819 			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
820 			RL[reg].dw_offset_or_block_len = soff * daf;
821 #ifdef FRAME_DEBUG
822 			printf("DW_CFA_offset_extended_sf(reg=%ju,soff=%jd)\n",
823 			    reg, soff);
824 #endif
825 			break;
826 		case DW_CFA_def_cfa_sf:
827 			*row_pc = pc;
828 			reg = _dwarf_decode_uleb128(&p);
829 			soff = _dwarf_decode_sleb128(&p);
830 			CFA.dw_offset_relevant = 1;
831 			CFA.dw_value_type = DW_EXPR_OFFSET;
832 			CFA.dw_regnum = reg;
833 			CFA.dw_offset_or_block_len = soff * daf;
834 #ifdef FRAME_DEBUG
835 			printf("DW_CFA_def_cfa_sf(reg=%ju,soff=%jd)\n", reg,
836 			    soff);
837 #endif
838 			break;
839 		case DW_CFA_def_cfa_offset_sf:
840 			*row_pc = pc;
841 			soff = _dwarf_decode_sleb128(&p);
842 			CFA.dw_offset_relevant = 1;
843 			CFA.dw_value_type = DW_EXPR_OFFSET;
844 			CFA.dw_offset_or_block_len = soff * daf;
845 #ifdef FRAME_DEBUG
846 			printf("DW_CFA_def_cfa_offset_sf(soff=%jd)\n", soff);
847 #endif
848 			break;
849 		case DW_CFA_val_offset:
850 			*row_pc = pc;
851 			reg = _dwarf_decode_uleb128(&p);
852 			uoff = _dwarf_decode_uleb128(&p);
853 			CHECK_TABLE_SIZE(reg);
854 			RL[reg].dw_offset_relevant = 1;
855 			RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
856 			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
857 			RL[reg].dw_offset_or_block_len = uoff * daf;
858 #ifdef FRAME_DEBUG
859 			printf("DW_CFA_val_offset(reg=%ju,uoff=%ju)\n", reg,
860 			    uoff);
861 #endif
862 			break;
863 		case DW_CFA_val_offset_sf:
864 			*row_pc = pc;
865 			reg = _dwarf_decode_uleb128(&p);
866 			soff = _dwarf_decode_sleb128(&p);
867 			CHECK_TABLE_SIZE(reg);
868 			RL[reg].dw_offset_relevant = 1;
869 			RL[reg].dw_value_type = DW_EXPR_VAL_OFFSET;
870 			RL[reg].dw_regnum = dbg->dbg_frame_cfa_value;
871 			RL[reg].dw_offset_or_block_len = soff * daf;
872 #ifdef FRAME_DEBUG
873 			printf("DW_CFA_val_offset_sf(reg=%ju,soff=%jd)\n", reg,
874 			    soff);
875 #endif
876 			break;
877 		case DW_CFA_val_expression:
878 			*row_pc = pc;
879 			reg = _dwarf_decode_uleb128(&p);
880 			CHECK_TABLE_SIZE(reg);
881 			RL[reg].dw_offset_relevant = 0;
882 			RL[reg].dw_value_type = DW_EXPR_VAL_EXPRESSION;
883 			RL[reg].dw_offset_or_block_len =
884 			    _dwarf_decode_uleb128(&p);
885 			RL[reg].dw_block_ptr = p;
886 			p += RL[reg].dw_offset_or_block_len;
887 #ifdef FRAME_DEBUG
888 			printf("DW_CFA_val_expression\n");
889 #endif
890 			break;
891 		default:
892 			DWARF_SET_ERROR(dbg, error,
893 			    DW_DLE_FRAME_INSTR_EXEC_ERROR);
894 			ret = DW_DLE_FRAME_INSTR_EXEC_ERROR;
895 			goto program_done;
896 		}
897 	}
898 
899 program_done:
900 
901 	free(init_rt->rt3_rules);
902 	free(init_rt);
903 	if (saved_rt) {
904 		free(saved_rt->rt3_rules);
905 		free(saved_rt);
906 	}
907 
908 	return (ret);
909 
910 #undef	CFA
911 #undef	INITCFA
912 #undef	RL
913 #undef	INITRL
914 #undef	CHECK_TABLE_SIZE
915 }
916 
917 static int
918 _dwarf_frame_convert_inst(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts,
919     Dwarf_Unsigned len, Dwarf_Unsigned *count, Dwarf_Frame_Op *fop,
920     Dwarf_Frame_Op3 *fop3, Dwarf_Error *error)
921 {
922 	uint8_t *p, *pe;
923 	uint8_t high2, low6;
924 	uint64_t reg, reg2, uoff, soff, blen;
925 
926 #define	SET_BASE_OP(x)						\
927 	do {							\
928 		if (fop != NULL)				\
929 			fop[*count].fp_base_op = (x) >> 6;	\
930 		if (fop3 != NULL)				\
931 			fop3[*count].fp_base_op = (x) >> 6;	\
932 	} while(0)
933 
934 #define	SET_EXTENDED_OP(x)					\
935 	do {							\
936 		if (fop != NULL)				\
937 			fop[*count].fp_extended_op = (x);	\
938 		if (fop3 != NULL)				\
939 			fop3[*count].fp_extended_op = (x);	\
940 	} while(0)
941 
942 #define	SET_REGISTER(x)						\
943 	do {							\
944 		if (fop != NULL)				\
945 			fop[*count].fp_register = (x);		\
946 		if (fop3 != NULL)				\
947 			fop3[*count].fp_register = (x);		\
948 	} while(0)
949 
950 #define	SET_OFFSET(x)						\
951 	do {							\
952 		if (fop != NULL)				\
953 			fop[*count].fp_offset = (x);		\
954 		if (fop3 != NULL)				\
955 			fop3[*count].fp_offset_or_block_len =	\
956 			    (x);				\
957 	} while(0)
958 
959 #define	SET_INSTR_OFFSET(x)					\
960 	do {							\
961 		if (fop != NULL)				\
962 			fop[*count].fp_instr_offset = (x);	\
963 		if (fop3 != NULL)				\
964 			fop3[*count].fp_instr_offset = (x);	\
965 	} while(0)
966 
967 #define	SET_BLOCK_LEN(x)					\
968 	do {							\
969 		if (fop3 != NULL)				\
970 			fop3[*count].fp_offset_or_block_len =	\
971 			    (x);				\
972 	} while(0)
973 
974 #define	SET_EXPR_BLOCK(addr, len)					\
975 	do {								\
976 		if (fop3 != NULL) {					\
977 			fop3[*count].fp_expr_block =			\
978 			    malloc((size_t) (len));			\
979 			if (fop3[*count].fp_expr_block == NULL)	{	\
980 				DWARF_SET_ERROR(dbg, error,		\
981 				    DW_DLE_MEMORY);			\
982 				return (DW_DLE_MEMORY);			\
983 			}						\
984 			memcpy(&fop3[*count].fp_expr_block,		\
985 			    (addr), (len));				\
986 		}							\
987 	} while(0)
988 
989 	*count = 0;
990 
991 	p = insts;
992 	pe = p + len;
993 
994 	while (p < pe) {
995 
996 		SET_INSTR_OFFSET(p - insts);
997 
998 		if (*p == DW_CFA_nop) {
999 			p++;
1000 			(*count)++;
1001 			continue;
1002 		}
1003 
1004 		high2 = *p & 0xc0;
1005 		low6 = *p & 0x3f;
1006 		p++;
1007 
1008 		if (high2 > 0) {
1009 			switch (high2) {
1010 			case DW_CFA_advance_loc:
1011 				SET_BASE_OP(high2);
1012 				SET_OFFSET(low6);
1013 				break;
1014 			case DW_CFA_offset:
1015 				SET_BASE_OP(high2);
1016 				SET_REGISTER(low6);
1017 				uoff = _dwarf_decode_uleb128(&p);
1018 				SET_OFFSET(uoff);
1019 				break;
1020 			case DW_CFA_restore:
1021 				SET_BASE_OP(high2);
1022 				SET_REGISTER(low6);
1023 				break;
1024 			default:
1025 				DWARF_SET_ERROR(dbg, error,
1026 				    DW_DLE_FRAME_INSTR_EXEC_ERROR);
1027 				return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1028 			}
1029 
1030 			(*count)++;
1031 			continue;
1032 		}
1033 
1034 		SET_EXTENDED_OP(low6);
1035 
1036 		switch (low6) {
1037 		case DW_CFA_set_loc:
1038 			uoff = dbg->decode(&p, addr_size);
1039 			SET_OFFSET(uoff);
1040 			break;
1041 		case DW_CFA_advance_loc1:
1042 			uoff = dbg->decode(&p, 1);
1043 			SET_OFFSET(uoff);
1044 			break;
1045 		case DW_CFA_advance_loc2:
1046 			uoff = dbg->decode(&p, 2);
1047 			SET_OFFSET(uoff);
1048 			break;
1049 		case DW_CFA_advance_loc4:
1050 			uoff = dbg->decode(&p, 4);
1051 			SET_OFFSET(uoff);
1052 			break;
1053 		case DW_CFA_offset_extended:
1054 		case DW_CFA_def_cfa:
1055 		case DW_CFA_val_offset:
1056 			reg = _dwarf_decode_uleb128(&p);
1057 			uoff = _dwarf_decode_uleb128(&p);
1058 			SET_REGISTER(reg);
1059 			SET_OFFSET(uoff);
1060 			break;
1061 		case DW_CFA_restore_extended:
1062 		case DW_CFA_undefined:
1063 		case DW_CFA_same_value:
1064 		case DW_CFA_def_cfa_register:
1065 			reg = _dwarf_decode_uleb128(&p);
1066 			SET_REGISTER(reg);
1067 			break;
1068 		case DW_CFA_register:
1069 			reg = _dwarf_decode_uleb128(&p);
1070 			reg2 = _dwarf_decode_uleb128(&p);
1071 			SET_REGISTER(reg);
1072 			SET_OFFSET(reg2);
1073 			break;
1074 		case DW_CFA_remember_state:
1075 		case DW_CFA_restore_state:
1076 			break;
1077 		case DW_CFA_def_cfa_offset:
1078 			uoff = _dwarf_decode_uleb128(&p);
1079 			SET_OFFSET(uoff);
1080 			break;
1081 		case DW_CFA_def_cfa_expression:
1082 			blen = _dwarf_decode_uleb128(&p);
1083 			SET_BLOCK_LEN(blen);
1084 			SET_EXPR_BLOCK(p, blen);
1085 			p += blen;
1086 			break;
1087 		case DW_CFA_expression:
1088 		case DW_CFA_val_expression:
1089 			reg = _dwarf_decode_uleb128(&p);
1090 			blen = _dwarf_decode_uleb128(&p);
1091 			SET_REGISTER(reg);
1092 			SET_BLOCK_LEN(blen);
1093 			SET_EXPR_BLOCK(p, blen);
1094 			p += blen;
1095 			break;
1096 		case DW_CFA_offset_extended_sf:
1097 		case DW_CFA_def_cfa_sf:
1098 		case DW_CFA_val_offset_sf:
1099 			reg = _dwarf_decode_uleb128(&p);
1100 			soff = _dwarf_decode_sleb128(&p);
1101 			SET_REGISTER(reg);
1102 			SET_OFFSET(soff);
1103 			break;
1104 		case DW_CFA_def_cfa_offset_sf:
1105 			soff = _dwarf_decode_sleb128(&p);
1106 			SET_OFFSET(soff);
1107 			break;
1108 		default:
1109 			DWARF_SET_ERROR(dbg, error,
1110 			    DW_DLE_FRAME_INSTR_EXEC_ERROR);
1111 			return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1112 		}
1113 
1114 		(*count)++;
1115 	}
1116 
1117 	return (DW_DLE_NONE);
1118 }
1119 
1120 int
1121 _dwarf_frame_get_fop(Dwarf_Debug dbg, uint8_t addr_size, uint8_t *insts,
1122     Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
1123     Dwarf_Error *error)
1124 {
1125 	Dwarf_Frame_Op *oplist;
1126 	Dwarf_Unsigned count;
1127 	int ret;
1128 
1129 	ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count,
1130 	    NULL, NULL, error);
1131 	if (ret != DW_DLE_NONE)
1132 		return (ret);
1133 
1134 	if ((oplist = calloc(count, sizeof(Dwarf_Frame_Op))) == NULL) {
1135 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1136 		return (DW_DLE_MEMORY);
1137 	}
1138 
1139 	ret = _dwarf_frame_convert_inst(dbg, addr_size, insts, len, &count,
1140 	    oplist, NULL, error);
1141 	if (ret != DW_DLE_NONE) {
1142 		free(oplist);
1143 		return (ret);
1144 	}
1145 
1146 	*ret_oplist = oplist;
1147 	*ret_opcnt = count;
1148 
1149 	return (DW_DLE_NONE);
1150 }
1151 
1152 int
1153 _dwarf_frame_regtable_copy(Dwarf_Debug dbg, Dwarf_Regtable3 **dest,
1154     Dwarf_Regtable3 *src, Dwarf_Error *error)
1155 {
1156 	int i;
1157 
1158 	assert(dest != NULL);
1159 	assert(src != NULL);
1160 
1161 	if (*dest == NULL) {
1162 		if ((*dest = malloc(sizeof(Dwarf_Regtable3))) == NULL) {
1163 			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1164 			return (DW_DLE_MEMORY);
1165 		}
1166 		(*dest)->rt3_reg_table_size = src->rt3_reg_table_size;
1167 		(*dest)->rt3_rules = malloc(src->rt3_reg_table_size *
1168 		    sizeof(Dwarf_Regtable_Entry3));
1169 		if ((*dest)->rt3_rules == NULL) {
1170 			free(*dest);
1171 			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1172 			return (DW_DLE_MEMORY);
1173 		}
1174 	}
1175 
1176 	memcpy(&(*dest)->rt3_cfa_rule, &src->rt3_cfa_rule,
1177 	    sizeof(Dwarf_Regtable_Entry3));
1178 
1179 	for (i = 0; i < (*dest)->rt3_reg_table_size &&
1180 	     i < src->rt3_reg_table_size; i++)
1181 		memcpy(&(*dest)->rt3_rules[i], &src->rt3_rules[i],
1182 		    sizeof(Dwarf_Regtable_Entry3));
1183 
1184 	for (; i < (*dest)->rt3_reg_table_size; i++)
1185 		(*dest)->rt3_rules[i].dw_regnum =
1186 		    dbg->dbg_frame_undefined_value;
1187 
1188 	return (DW_DLE_NONE);
1189 }
1190 
1191 int
1192 _dwarf_frame_get_internal_table(Dwarf_Fde fde, Dwarf_Addr pc_req,
1193     Dwarf_Regtable3 **ret_rt, Dwarf_Addr *ret_row_pc, Dwarf_Error *error)
1194 {
1195 	Dwarf_Debug dbg;
1196 	Dwarf_Cie cie;
1197 	Dwarf_Regtable3 *rt;
1198 	Dwarf_Addr row_pc;
1199 	int i, ret;
1200 
1201 	assert(ret_rt != NULL);
1202 
1203 	dbg = fde->fde_dbg;
1204 	assert(dbg != NULL);
1205 
1206 	rt = dbg->dbg_internal_reg_table;
1207 
1208 	/* Clear the content of regtable from previous run. */
1209 	memset(&rt->rt3_cfa_rule, 0, sizeof(Dwarf_Regtable_Entry3));
1210 	memset(rt->rt3_rules, 0, rt->rt3_reg_table_size *
1211 	    sizeof(Dwarf_Regtable_Entry3));
1212 
1213 	/* Set rules to initial values. */
1214 	for (i = 0; i < rt->rt3_reg_table_size; i++)
1215 		rt->rt3_rules[i].dw_regnum = dbg->dbg_frame_rule_initial_value;
1216 
1217 	/* Run initial instructions in CIE. */
1218 	cie = fde->fde_cie;
1219 	assert(cie != NULL);
1220 	ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize,
1221 	    cie->cie_initinst, cie->cie_instlen, cie->cie_caf, cie->cie_daf, 0,
1222 	    ~0ULL, &row_pc, error);
1223 	if (ret != DW_DLE_NONE)
1224 		return (ret);
1225 
1226 	/* Run instructions in FDE. */
1227 	if (pc_req >= fde->fde_initloc) {
1228 		ret = _dwarf_frame_run_inst(dbg, rt, cie->cie_addrsize,
1229 		    fde->fde_inst, fde->fde_instlen, cie->cie_caf,
1230 		    cie->cie_daf, fde->fde_initloc, pc_req, &row_pc, error);
1231 		if (ret != DW_DLE_NONE)
1232 			return (ret);
1233 	}
1234 
1235 	*ret_rt = rt;
1236 	*ret_row_pc = row_pc;
1237 
1238 	return (DW_DLE_NONE);
1239 }
1240 
1241 void
1242 _dwarf_frame_cleanup(Dwarf_Debug dbg)
1243 {
1244 	Dwarf_Regtable3 *rt;
1245 
1246 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_READ);
1247 
1248 	if (dbg->dbg_internal_reg_table) {
1249 		rt = dbg->dbg_internal_reg_table;
1250 		free(rt->rt3_rules);
1251 		free(rt);
1252 		dbg->dbg_internal_reg_table = NULL;
1253 	}
1254 
1255 	if (dbg->dbg_frame) {
1256 		_dwarf_frame_section_cleanup(dbg->dbg_frame);
1257 		dbg->dbg_frame = NULL;
1258 	}
1259 
1260 	if (dbg->dbg_eh_frame) {
1261 		_dwarf_frame_section_cleanup(dbg->dbg_eh_frame);
1262 		dbg->dbg_eh_frame = NULL;
1263 	}
1264 }
1265 
1266 int
1267 _dwarf_frame_section_load(Dwarf_Debug dbg, Dwarf_Error *error)
1268 {
1269 	Dwarf_Section *ds;
1270 
1271 	if ((ds = _dwarf_find_section(dbg, ".debug_frame")) != NULL) {
1272 		return (_dwarf_frame_section_init(dbg, &dbg->dbg_frame,
1273 		    ds, 0, error));
1274 	}
1275 
1276 	return (DW_DLE_NONE);
1277 }
1278 
1279 int
1280 _dwarf_frame_section_load_eh(Dwarf_Debug dbg, Dwarf_Error *error)
1281 {
1282 	Dwarf_Section *ds;
1283 
1284 	if ((ds = _dwarf_find_section(dbg, ".eh_frame")) != NULL) {
1285 		return (_dwarf_frame_section_init(dbg, &dbg->dbg_eh_frame,
1286 		    ds, 1, error));
1287 	}
1288 
1289 	return (DW_DLE_NONE);
1290 }
1291 
1292 void
1293 _dwarf_frame_params_init(Dwarf_Debug dbg)
1294 {
1295 
1296 	/* Initialise call frame related parameters. */
1297 	dbg->dbg_frame_rule_table_size = DW_FRAME_LAST_REG_NUM;
1298 	dbg->dbg_frame_rule_initial_value = DW_FRAME_REG_INITIAL_VALUE;
1299 	dbg->dbg_frame_cfa_value = DW_FRAME_CFA_COL3;
1300 	dbg->dbg_frame_same_value = DW_FRAME_SAME_VAL;
1301 	dbg->dbg_frame_undefined_value = DW_FRAME_UNDEFINED_VAL;
1302 }
1303 
1304 int
1305 _dwarf_frame_interal_table_init(Dwarf_Debug dbg, Dwarf_Error *error)
1306 {
1307 	Dwarf_Regtable3 *rt;
1308 
1309 	if (dbg->dbg_internal_reg_table != NULL)
1310 		return (DW_DLE_NONE);
1311 
1312 	/* Initialise internal register table. */
1313 	if ((rt = calloc(1, sizeof(Dwarf_Regtable3))) == NULL) {
1314 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1315 		return (DW_DLE_MEMORY);
1316 	}
1317 
1318 	rt->rt3_reg_table_size = dbg->dbg_frame_rule_table_size;
1319 	if ((rt->rt3_rules = calloc(rt->rt3_reg_table_size,
1320 	    sizeof(Dwarf_Regtable_Entry3))) == NULL) {
1321 		free(rt);
1322 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1323 		return (DW_DLE_MEMORY);
1324 	}
1325 
1326 	dbg->dbg_internal_reg_table = rt;
1327 
1328 	return (DW_DLE_NONE);
1329 }
1330 
1331 #define	_FDE_INST_INIT_SIZE	128
1332 
1333 int
1334 _dwarf_frame_fde_add_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1,
1335     Dwarf_Unsigned val2, Dwarf_Error *error)
1336 {
1337 	Dwarf_P_Debug dbg;
1338 	uint8_t high2, low6;
1339 	int ret;
1340 
1341 #define	ds	fde
1342 #define	ds_data	fde_inst
1343 #define	ds_cap	fde_instcap
1344 #define	ds_size	fde_instlen
1345 
1346 	assert(fde != NULL && fde->fde_dbg != NULL);
1347 	dbg = fde->fde_dbg;
1348 
1349 	if (fde->fde_inst == NULL) {
1350 		fde->fde_instcap = _FDE_INST_INIT_SIZE;
1351 		fde->fde_instlen = 0;
1352 		if ((fde->fde_inst = malloc((size_t) fde->fde_instcap)) ==
1353 		    NULL) {
1354 			DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1355 			return (DW_DLE_MEMORY);
1356 		}
1357 	}
1358 	assert(fde->fde_instcap != 0);
1359 
1360 	RCHECK(WRITE_VALUE(op, 1));
1361 	if (op == DW_CFA_nop)
1362 		return (DW_DLE_NONE);
1363 
1364 	high2 = op & 0xc0;
1365 	low6 = op & 0x3f;
1366 
1367 	if (high2 > 0) {
1368 		switch (high2) {
1369 		case DW_CFA_advance_loc:
1370 		case DW_CFA_restore:
1371 			break;
1372 		case DW_CFA_offset:
1373 			RCHECK(WRITE_ULEB128(val1));
1374 			break;
1375 		default:
1376 			DWARF_SET_ERROR(dbg, error,
1377 			    DW_DLE_FRAME_INSTR_EXEC_ERROR);
1378 			return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1379 		}
1380 		return (DW_DLE_NONE);
1381 	}
1382 
1383 	switch (low6) {
1384 	case DW_CFA_set_loc:
1385 		RCHECK(WRITE_VALUE(val1, dbg->dbg_pointer_size));
1386 		break;
1387 	case DW_CFA_advance_loc1:
1388 		RCHECK(WRITE_VALUE(val1, 1));
1389 		break;
1390 	case DW_CFA_advance_loc2:
1391 		RCHECK(WRITE_VALUE(val1, 2));
1392 		break;
1393 	case DW_CFA_advance_loc4:
1394 		RCHECK(WRITE_VALUE(val1, 4));
1395 		break;
1396 	case DW_CFA_offset_extended:
1397 	case DW_CFA_def_cfa:
1398 	case DW_CFA_register:
1399 		RCHECK(WRITE_ULEB128(val1));
1400 		RCHECK(WRITE_ULEB128(val2));
1401 		break;
1402 	case DW_CFA_restore_extended:
1403 	case DW_CFA_undefined:
1404 	case DW_CFA_same_value:
1405 	case DW_CFA_def_cfa_register:
1406 	case DW_CFA_def_cfa_offset:
1407 		RCHECK(WRITE_ULEB128(val1));
1408 		break;
1409 	case DW_CFA_remember_state:
1410 	case DW_CFA_restore_state:
1411 		break;
1412 	default:
1413 		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_INSTR_EXEC_ERROR);
1414 		return (DW_DLE_FRAME_INSTR_EXEC_ERROR);
1415 	}
1416 
1417 	return (DW_DLE_NONE);
1418 
1419 gen_fail:
1420 	return (ret);
1421 
1422 #undef	ds
1423 #undef	ds_data
1424 #undef	ds_cap
1425 #undef	ds_size
1426 }
1427 
1428 static int
1429 _dwarf_frame_gen_cie(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_P_Cie cie,
1430     Dwarf_Error *error)
1431 {
1432 	Dwarf_Unsigned len;
1433 	uint64_t offset;
1434 	int ret;
1435 
1436 	assert(dbg != NULL && ds != NULL && cie != NULL);
1437 
1438 	cie->cie_offset = offset = ds->ds_size;
1439 	cie->cie_length = 0;
1440 	cie->cie_version = 1;
1441 
1442 	/* Length placeholder. */
1443 	RCHECK(WRITE_VALUE(cie->cie_length, 4));
1444 
1445 	/* .debug_frame use CIE id ~0. */
1446 	RCHECK(WRITE_VALUE(~0U, 4));
1447 
1448 	/* .debug_frame version is 1. (DWARF2) */
1449 	RCHECK(WRITE_VALUE(cie->cie_version, 1));
1450 
1451 	/* Write augmentation, if present. */
1452 	if (cie->cie_augment != NULL)
1453 		RCHECK(WRITE_BLOCK(cie->cie_augment,
1454 		    strlen((char *) cie->cie_augment) + 1));
1455 	else
1456 		RCHECK(WRITE_VALUE(0, 1));
1457 
1458 	/* Write caf, daf and ra. */
1459 	RCHECK(WRITE_ULEB128(cie->cie_caf));
1460 	RCHECK(WRITE_SLEB128(cie->cie_daf));
1461 	RCHECK(WRITE_VALUE(cie->cie_ra, 1));
1462 
1463 	/* Write initial instructions, if present. */
1464 	if (cie->cie_initinst != NULL)
1465 		RCHECK(WRITE_BLOCK(cie->cie_initinst, cie->cie_instlen));
1466 
1467 	/* Add padding. */
1468 	len = ds->ds_size - cie->cie_offset - 4;
1469 	cie->cie_length = roundup(len, dbg->dbg_pointer_size);
1470 	while (len++ < cie->cie_length)
1471 		RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
1472 
1473 	/* Fill in the length field. */
1474 	dbg->write(ds->ds_data, &offset, cie->cie_length, 4);
1475 
1476 	return (DW_DLE_NONE);
1477 
1478 gen_fail:
1479 	return (ret);
1480 }
1481 
1482 static int
1483 _dwarf_frame_gen_fde(Dwarf_P_Debug dbg, Dwarf_P_Section ds,
1484     Dwarf_Rel_Section drs, Dwarf_P_Fde fde, Dwarf_Error *error)
1485 {
1486 	Dwarf_Unsigned len;
1487 	uint64_t offset;
1488 	int ret;
1489 
1490 	assert(dbg != NULL && ds != NULL && drs != NULL);
1491 	assert(fde != NULL && fde->fde_cie != NULL);
1492 
1493 	fde->fde_offset = offset = ds->ds_size;
1494 	fde->fde_length = 0;
1495 	fde->fde_cieoff = fde->fde_cie->cie_offset;
1496 
1497 	/* Length placeholder. */
1498 	RCHECK(WRITE_VALUE(fde->fde_length, 4));
1499 
1500 	/* Write CIE pointer. */
1501 	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4,
1502 	    ds->ds_size, 0, fde->fde_cieoff, ".debug_frame", error));
1503 
1504 	/* Write FDE initial location. */
1505 	RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
1506 	    dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
1507 	    fde->fde_initloc, NULL, error));
1508 
1509 	/*
1510 	 * Write FDE address range. Use a pair of relocation entries if
1511 	 * application provided end symbol index. Otherwise write the
1512 	 * length without assoicating any relocation info.
1513 	 */
1514 	if (fde->fde_esymndx > 0)
1515 		RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds,
1516 		    dbg->dbg_pointer_size, ds->ds_size, fde->fde_symndx,
1517 		    fde->fde_esymndx, fde->fde_initloc, fde->fde_eoff, error));
1518 	else
1519 		RCHECK(WRITE_VALUE(fde->fde_adrange, dbg->dbg_pointer_size));
1520 
1521 	/* Write FDE frame instructions. */
1522 	RCHECK(WRITE_BLOCK(fde->fde_inst, fde->fde_instlen));
1523 
1524 	/* Add padding. */
1525 	len = ds->ds_size - fde->fde_offset - 4;
1526 	fde->fde_length = roundup(len, dbg->dbg_pointer_size);
1527 	while (len++ < fde->fde_length)
1528 		RCHECK(WRITE_VALUE(DW_CFA_nop, 1));
1529 
1530 	/* Fill in the length field. */
1531 	dbg->write(ds->ds_data, &offset, fde->fde_length, 4);
1532 
1533 	return (DW_DLE_NONE);
1534 
1535 gen_fail:
1536 	return (ret);
1537 }
1538 
1539 int
1540 _dwarf_frame_gen(Dwarf_P_Debug dbg, Dwarf_Error *error)
1541 {
1542 	Dwarf_P_Section ds;
1543 	Dwarf_Rel_Section drs;
1544 	Dwarf_P_Cie cie;
1545 	Dwarf_P_Fde fde;
1546 	int ret;
1547 
1548 	if (STAILQ_EMPTY(&dbg->dbgp_cielist))
1549 		return (DW_DLE_NONE);
1550 
1551 	/* Create .debug_frame section. */
1552 	if ((ret = _dwarf_section_init(dbg, &ds, ".debug_frame", 0, error)) !=
1553 	    DW_DLE_NONE)
1554 		goto gen_fail0;
1555 
1556 	/* Create relocation section for .debug_frame */
1557 	RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error));
1558 
1559 	/* Generate list of CIE. */
1560 	STAILQ_FOREACH(cie, &dbg->dbgp_cielist, cie_next)
1561 		RCHECK(_dwarf_frame_gen_cie(dbg, ds, cie, error));
1562 
1563 	/* Generate list of FDE. */
1564 	STAILQ_FOREACH(fde, &dbg->dbgp_fdelist, fde_next)
1565 		RCHECK(_dwarf_frame_gen_fde(dbg, ds, drs, fde, error));
1566 
1567 	/* Inform application the creation of .debug_frame ELF section. */
1568 	RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error));
1569 
1570 	/* Finalize relocation section for .debug_frame */
1571 	RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error));
1572 
1573 	return (DW_DLE_NONE);
1574 
1575 gen_fail:
1576 	_dwarf_reloc_section_free(dbg, &drs);
1577 
1578 gen_fail0:
1579 	_dwarf_section_free(dbg, &ds);
1580 
1581 	return (ret);
1582 }
1583 
1584 void
1585 _dwarf_frame_pro_cleanup(Dwarf_P_Debug dbg)
1586 {
1587 	Dwarf_P_Cie cie, tcie;
1588 	Dwarf_P_Fde fde, tfde;
1589 
1590 	assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE);
1591 
1592 	STAILQ_FOREACH_SAFE(cie, &dbg->dbgp_cielist, cie_next, tcie) {
1593 		STAILQ_REMOVE(&dbg->dbgp_cielist, cie, _Dwarf_Cie, cie_next);
1594 		if (cie->cie_augment)
1595 			free(cie->cie_augment);
1596 		if (cie->cie_initinst)
1597 			free(cie->cie_initinst);
1598 		free(cie);
1599 	}
1600 	dbg->dbgp_cielen = 0;
1601 
1602 	STAILQ_FOREACH_SAFE(fde, &dbg->dbgp_fdelist, fde_next, tfde) {
1603 		STAILQ_REMOVE(&dbg->dbgp_fdelist, fde, _Dwarf_Fde, fde_next);
1604 		if (fde->fde_inst != NULL)
1605 			free(fde->fde_inst);
1606 		free(fde);
1607 	}
1608 	dbg->dbgp_fdelen = 0;
1609 }
1610