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