xref: /netbsd-src/external/bsd/elftoolchain/dist/libdwarf/dwarf_frame.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
1*5ac3bc71Schristos /*	$NetBSD: dwarf_frame.c,v 1.5 2024/03/03 17:37:31 christos Exp $	*/
2e81373b4Schristos 
39dd9d0cfSchristos /*-
49dd9d0cfSchristos  * Copyright (c) 2009,2011 Kai Wang
59dd9d0cfSchristos  * All rights reserved.
69dd9d0cfSchristos  *
79dd9d0cfSchristos  * Redistribution and use in source and binary forms, with or without
89dd9d0cfSchristos  * modification, are permitted provided that the following conditions
99dd9d0cfSchristos  * are met:
109dd9d0cfSchristos  * 1. Redistributions of source code must retain the above copyright
119dd9d0cfSchristos  *    notice, this list of conditions and the following disclaimer.
129dd9d0cfSchristos  * 2. Redistributions in binary form must reproduce the above copyright
139dd9d0cfSchristos  *    notice, this list of conditions and the following disclaimer in the
149dd9d0cfSchristos  *    documentation and/or other materials provided with the distribution.
159dd9d0cfSchristos  *
169dd9d0cfSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
179dd9d0cfSchristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189dd9d0cfSchristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199dd9d0cfSchristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209dd9d0cfSchristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
219dd9d0cfSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
229dd9d0cfSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
239dd9d0cfSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
249dd9d0cfSchristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
259dd9d0cfSchristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269dd9d0cfSchristos  * SUCH DAMAGE.
279dd9d0cfSchristos  */
289dd9d0cfSchristos 
299dd9d0cfSchristos #include "_libdwarf.h"
309dd9d0cfSchristos 
31*5ac3bc71Schristos __RCSID("$NetBSD: dwarf_frame.c,v 1.5 2024/03/03 17:37:31 christos Exp $");
3242bd3019Schristos ELFTC_VCSID("Id: dwarf_frame.c 3106 2014-12-19 16:00:58Z kaiwang27");
339dd9d0cfSchristos 
349dd9d0cfSchristos int
dwarf_get_fde_list(Dwarf_Debug dbg,Dwarf_Cie ** cie_list,Dwarf_Signed * cie_count,Dwarf_Fde ** fde_list,Dwarf_Signed * fde_count,Dwarf_Error * error)359dd9d0cfSchristos dwarf_get_fde_list(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
369dd9d0cfSchristos     Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
379dd9d0cfSchristos     Dwarf_Error *error)
389dd9d0cfSchristos {
399dd9d0cfSchristos 
409dd9d0cfSchristos 	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
419dd9d0cfSchristos 	    fde_list == NULL || fde_count == NULL) {
429dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
439dd9d0cfSchristos 		return (DW_DLV_ERROR);
449dd9d0cfSchristos 	}
459dd9d0cfSchristos 
469dd9d0cfSchristos 	if (dbg->dbg_internal_reg_table == NULL) {
479dd9d0cfSchristos 		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
489dd9d0cfSchristos 			return (DW_DLV_ERROR);
499dd9d0cfSchristos 	}
509dd9d0cfSchristos 
519dd9d0cfSchristos 	if (dbg->dbg_frame == NULL) {
529dd9d0cfSchristos 		if (_dwarf_frame_section_load(dbg, error) != DW_DLE_NONE)
539dd9d0cfSchristos 			return (DW_DLV_ERROR);
549dd9d0cfSchristos 		if (dbg->dbg_frame == NULL) {
559dd9d0cfSchristos 			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
569dd9d0cfSchristos 			return (DW_DLV_NO_ENTRY);
579dd9d0cfSchristos 		}
589dd9d0cfSchristos 	}
599dd9d0cfSchristos 
609dd9d0cfSchristos 	if (dbg->dbg_frame->fs_ciearray == NULL ||
619dd9d0cfSchristos 	    dbg->dbg_frame->fs_fdearray == NULL) {
629dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
639dd9d0cfSchristos 		return (DW_DLV_NO_ENTRY);
649dd9d0cfSchristos 	}
659dd9d0cfSchristos 
669dd9d0cfSchristos 	*cie_list = dbg->dbg_frame->fs_ciearray;
679dd9d0cfSchristos 	*cie_count = dbg->dbg_frame->fs_cielen;
689dd9d0cfSchristos 	*fde_list = dbg->dbg_frame->fs_fdearray;
699dd9d0cfSchristos 	*fde_count = dbg->dbg_frame->fs_fdelen;
709dd9d0cfSchristos 
719dd9d0cfSchristos 	return (DW_DLV_OK);
729dd9d0cfSchristos }
739dd9d0cfSchristos 
749dd9d0cfSchristos int
dwarf_get_fde_list_eh(Dwarf_Debug dbg,Dwarf_Cie ** cie_list,Dwarf_Signed * cie_count,Dwarf_Fde ** fde_list,Dwarf_Signed * fde_count,Dwarf_Error * error)759dd9d0cfSchristos dwarf_get_fde_list_eh(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
769dd9d0cfSchristos     Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
779dd9d0cfSchristos     Dwarf_Error *error)
789dd9d0cfSchristos {
799dd9d0cfSchristos 
809dd9d0cfSchristos 	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
819dd9d0cfSchristos 	    fde_list == NULL || fde_count == NULL) {
829dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
839dd9d0cfSchristos 		return (DW_DLV_ERROR);
849dd9d0cfSchristos 	}
859dd9d0cfSchristos 
869dd9d0cfSchristos 	if (dbg->dbg_internal_reg_table == NULL) {
879dd9d0cfSchristos 		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
889dd9d0cfSchristos 			return (DW_DLV_ERROR);
899dd9d0cfSchristos 	}
909dd9d0cfSchristos 
919dd9d0cfSchristos 	if (dbg->dbg_eh_frame == NULL) {
929dd9d0cfSchristos 		if (_dwarf_frame_section_load_eh(dbg, error) != DW_DLE_NONE)
939dd9d0cfSchristos 			return (DW_DLV_ERROR);
949dd9d0cfSchristos 		if (dbg->dbg_eh_frame == NULL) {
959dd9d0cfSchristos 			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
969dd9d0cfSchristos 			return (DW_DLV_NO_ENTRY);
979dd9d0cfSchristos 		}
989dd9d0cfSchristos 	}
999dd9d0cfSchristos 
1009dd9d0cfSchristos 	if (dbg->dbg_eh_frame->fs_ciearray == NULL ||
1019dd9d0cfSchristos 	    dbg->dbg_eh_frame->fs_fdearray == NULL) {
1029dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
1039dd9d0cfSchristos 		return (DW_DLV_NO_ENTRY);
1049dd9d0cfSchristos 	}
1059dd9d0cfSchristos 
1069dd9d0cfSchristos 	*cie_list = dbg->dbg_eh_frame->fs_ciearray;
1079dd9d0cfSchristos 	*cie_count = dbg->dbg_eh_frame->fs_cielen;
1089dd9d0cfSchristos 	*fde_list = dbg->dbg_eh_frame->fs_fdearray;
1099dd9d0cfSchristos 	*fde_count = dbg->dbg_eh_frame->fs_fdelen;
1109dd9d0cfSchristos 
1119dd9d0cfSchristos 	return (DW_DLV_OK);
1129dd9d0cfSchristos }
1139dd9d0cfSchristos 
1149dd9d0cfSchristos int
dwarf_get_fde_n(Dwarf_Fde * fdelist,Dwarf_Unsigned fde_index,Dwarf_Fde * ret_fde,Dwarf_Error * error)1159dd9d0cfSchristos dwarf_get_fde_n(Dwarf_Fde *fdelist, Dwarf_Unsigned fde_index,
1169dd9d0cfSchristos     Dwarf_Fde *ret_fde, Dwarf_Error *error)
1179dd9d0cfSchristos {
1189dd9d0cfSchristos 	Dwarf_FrameSec fs;
1199dd9d0cfSchristos 	Dwarf_Debug dbg;
1209dd9d0cfSchristos 
1219dd9d0cfSchristos 	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
1229dd9d0cfSchristos 
1239dd9d0cfSchristos 	if (fdelist == NULL || ret_fde == NULL) {
1249dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1259dd9d0cfSchristos 		return (DW_DLV_ERROR);
1269dd9d0cfSchristos 	}
1279dd9d0cfSchristos 
1289dd9d0cfSchristos 	fs = fdelist[0]->fde_fs;
1299dd9d0cfSchristos 	assert(fs != NULL);
1309dd9d0cfSchristos 
1319dd9d0cfSchristos 	if (fde_index >= fs->fs_fdelen) {
1329dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
1339dd9d0cfSchristos 		return (DW_DLV_NO_ENTRY);
1349dd9d0cfSchristos 	}
1359dd9d0cfSchristos 
1369dd9d0cfSchristos 	*ret_fde = fdelist[fde_index];
1379dd9d0cfSchristos 
1389dd9d0cfSchristos 	return (DW_DLV_OK);
1399dd9d0cfSchristos }
1409dd9d0cfSchristos 
1419dd9d0cfSchristos int
dwarf_get_fde_at_pc(Dwarf_Fde * fdelist,Dwarf_Addr pc,Dwarf_Fde * ret_fde,Dwarf_Addr * lopc,Dwarf_Addr * hipc,Dwarf_Error * error)1429dd9d0cfSchristos dwarf_get_fde_at_pc(Dwarf_Fde *fdelist, Dwarf_Addr pc, Dwarf_Fde *ret_fde,
1439dd9d0cfSchristos     Dwarf_Addr *lopc, Dwarf_Addr *hipc, Dwarf_Error *error)
1449dd9d0cfSchristos {
1459dd9d0cfSchristos 	Dwarf_FrameSec fs;
1469dd9d0cfSchristos 	Dwarf_Debug dbg;
1479dd9d0cfSchristos 	Dwarf_Fde fde;
1489dd9d0cfSchristos 	int i;
1499dd9d0cfSchristos 
1509dd9d0cfSchristos 	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
1519dd9d0cfSchristos 
1529dd9d0cfSchristos 	if (fdelist == NULL || ret_fde == NULL || lopc == NULL ||
1539dd9d0cfSchristos 	    hipc == NULL) {
1549dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1559dd9d0cfSchristos 		return (DW_DLV_ERROR);
1569dd9d0cfSchristos 	}
1579dd9d0cfSchristos 
1589dd9d0cfSchristos 	fs = fdelist[0]->fde_fs;
1599dd9d0cfSchristos 	assert(fs != NULL);
1609dd9d0cfSchristos 
1619dd9d0cfSchristos 	for (i = 0; (Dwarf_Unsigned)i < fs->fs_fdelen; i++) {
1629dd9d0cfSchristos 		fde = fdelist[i];
1639dd9d0cfSchristos 		if (pc >= fde->fde_initloc && pc < fde->fde_initloc +
1649dd9d0cfSchristos 		    fde->fde_adrange) {
1659dd9d0cfSchristos 			*ret_fde = fde;
1669dd9d0cfSchristos 			*lopc = fde->fde_initloc;
1679dd9d0cfSchristos 			*hipc = fde->fde_initloc + fde->fde_adrange - 1;
1689dd9d0cfSchristos 			return (DW_DLV_OK);
1699dd9d0cfSchristos 		}
1709dd9d0cfSchristos 	}
1719dd9d0cfSchristos 
1729dd9d0cfSchristos 	DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
1739dd9d0cfSchristos 	return (DW_DLV_NO_ENTRY);
1749dd9d0cfSchristos }
1759dd9d0cfSchristos 
1769dd9d0cfSchristos int
dwarf_get_cie_of_fde(Dwarf_Fde fde,Dwarf_Cie * ret_cie,Dwarf_Error * error)1779dd9d0cfSchristos dwarf_get_cie_of_fde(Dwarf_Fde fde, Dwarf_Cie *ret_cie, Dwarf_Error *error)
1789dd9d0cfSchristos {
1799dd9d0cfSchristos 	Dwarf_Debug dbg;
1809dd9d0cfSchristos 
1819dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
1829dd9d0cfSchristos 
1839dd9d0cfSchristos 	if (fde == NULL || ret_cie == NULL) {
1849dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1859dd9d0cfSchristos 		return (DW_DLV_ERROR);
1869dd9d0cfSchristos 	}
1879dd9d0cfSchristos 
1889dd9d0cfSchristos 	*ret_cie = fde->fde_cie;
1899dd9d0cfSchristos 
1909dd9d0cfSchristos 	return (DW_DLV_OK);
1919dd9d0cfSchristos }
1929dd9d0cfSchristos 
1939dd9d0cfSchristos int
dwarf_get_fde_range(Dwarf_Fde fde,Dwarf_Addr * low_pc,Dwarf_Unsigned * func_len,Dwarf_Ptr * fde_bytes,Dwarf_Unsigned * fde_byte_len,Dwarf_Off * cie_offset,Dwarf_Signed * cie_index,Dwarf_Off * fde_offset,Dwarf_Error * error)1949dd9d0cfSchristos dwarf_get_fde_range(Dwarf_Fde fde, Dwarf_Addr *low_pc, Dwarf_Unsigned *func_len,
1959dd9d0cfSchristos     Dwarf_Ptr *fde_bytes, Dwarf_Unsigned *fde_byte_len, Dwarf_Off *cie_offset,
1969dd9d0cfSchristos     Dwarf_Signed *cie_index, Dwarf_Off *fde_offset, Dwarf_Error *error)
1979dd9d0cfSchristos {
1989dd9d0cfSchristos 	Dwarf_Debug dbg;
1999dd9d0cfSchristos 
2009dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
2019dd9d0cfSchristos 
2029dd9d0cfSchristos 	if (fde == NULL || low_pc == NULL || func_len == NULL ||
2039dd9d0cfSchristos 	    fde_bytes == NULL || fde_byte_len == NULL || cie_offset == NULL ||
2049dd9d0cfSchristos 	    cie_index == NULL || fde_offset == NULL) {
2059dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2069dd9d0cfSchristos 		return (DW_DLV_ERROR);
2079dd9d0cfSchristos 	}
2089dd9d0cfSchristos 
2099dd9d0cfSchristos 	*low_pc = fde->fde_initloc;
2109dd9d0cfSchristos 	*func_len = fde->fde_adrange;
2119dd9d0cfSchristos 	*fde_bytes = fde->fde_addr;
2129dd9d0cfSchristos 	*fde_byte_len = fde->fde_length;
2139dd9d0cfSchristos 	*cie_offset = fde->fde_cieoff;
2149dd9d0cfSchristos 	*cie_index = fde->fde_cie->cie_index;
2159dd9d0cfSchristos 	*fde_offset = fde->fde_offset;
2169dd9d0cfSchristos 
2179dd9d0cfSchristos 	return (DW_DLV_OK);
2189dd9d0cfSchristos }
2199dd9d0cfSchristos 
2209dd9d0cfSchristos int
dwarf_get_cie_info(Dwarf_Cie cie,Dwarf_Unsigned * bytes_in_cie,Dwarf_Small * version,char ** augmenter,Dwarf_Unsigned * caf,Dwarf_Unsigned * daf,Dwarf_Half * ra,Dwarf_Ptr * initinst,Dwarf_Unsigned * inst_len,Dwarf_Error * error)2219dd9d0cfSchristos dwarf_get_cie_info(Dwarf_Cie cie, Dwarf_Unsigned *bytes_in_cie,
2229dd9d0cfSchristos     Dwarf_Small *version, char **augmenter, Dwarf_Unsigned *caf,
2239dd9d0cfSchristos     Dwarf_Unsigned *daf, Dwarf_Half *ra, Dwarf_Ptr *initinst,
2249dd9d0cfSchristos     Dwarf_Unsigned *inst_len, Dwarf_Error *error)
2259dd9d0cfSchristos {
2269dd9d0cfSchristos 
2279dd9d0cfSchristos 	if (cie == NULL || bytes_in_cie == NULL || version == NULL ||
2289dd9d0cfSchristos 	    augmenter == NULL || caf == NULL || daf == NULL || ra == NULL ||
2299dd9d0cfSchristos 	    initinst == NULL || inst_len == NULL) {
2309dd9d0cfSchristos 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
2319dd9d0cfSchristos 		return (DW_DLV_ERROR);
2329dd9d0cfSchristos 	}
2339dd9d0cfSchristos 
2349dd9d0cfSchristos 	*bytes_in_cie = cie->cie_length;
2359dd9d0cfSchristos 	*version = cie->cie_version;
2369dd9d0cfSchristos 	*augmenter = (char *) cie->cie_augment;
2379dd9d0cfSchristos 	*caf = cie->cie_caf;
2389dd9d0cfSchristos 	*daf = cie->cie_daf;
2399dd9d0cfSchristos 	*ra = cie->cie_ra;
2409dd9d0cfSchristos 	*initinst = cie->cie_initinst;
2419dd9d0cfSchristos 	*inst_len = cie->cie_instlen;
2429dd9d0cfSchristos 
2439dd9d0cfSchristos 	return (DW_DLV_OK);
2449dd9d0cfSchristos }
2459dd9d0cfSchristos 
2469dd9d0cfSchristos int
dwarf_get_cie_index(Dwarf_Cie cie,Dwarf_Signed * cie_index,Dwarf_Error * error)2479dd9d0cfSchristos dwarf_get_cie_index(Dwarf_Cie cie, Dwarf_Signed *cie_index, Dwarf_Error *error)
2489dd9d0cfSchristos {
2499dd9d0cfSchristos 
2509dd9d0cfSchristos 	if (cie == NULL || cie_index == NULL) {
2519dd9d0cfSchristos 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
2529dd9d0cfSchristos 		return (DW_DLV_ERROR);
2539dd9d0cfSchristos 	}
2549dd9d0cfSchristos 
2559dd9d0cfSchristos 	*cie_index = cie->cie_index;
2569dd9d0cfSchristos 
2579dd9d0cfSchristos 	return (DW_DLV_OK);
2589dd9d0cfSchristos }
2599dd9d0cfSchristos 
2609dd9d0cfSchristos int
dwarf_get_fde_instr_bytes(Dwarf_Fde fde,Dwarf_Ptr * ret_inst,Dwarf_Unsigned * ret_len,Dwarf_Error * error)2619dd9d0cfSchristos dwarf_get_fde_instr_bytes(Dwarf_Fde fde, Dwarf_Ptr *ret_inst,
2629dd9d0cfSchristos     Dwarf_Unsigned *ret_len, Dwarf_Error *error)
2639dd9d0cfSchristos {
2649dd9d0cfSchristos 	Dwarf_Debug dbg;
2659dd9d0cfSchristos 
2669dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
2679dd9d0cfSchristos 
2689dd9d0cfSchristos 	if (fde == NULL || ret_inst == NULL || ret_len == NULL) {
2699dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2709dd9d0cfSchristos 		return (DW_DLV_ERROR);
2719dd9d0cfSchristos 	}
2729dd9d0cfSchristos 
2739dd9d0cfSchristos 	*ret_inst = fde->fde_inst;
2749dd9d0cfSchristos 	*ret_len = fde->fde_instlen;
2759dd9d0cfSchristos 
2769dd9d0cfSchristos 	return (DW_DLV_OK);
2779dd9d0cfSchristos }
2789dd9d0cfSchristos 
2799dd9d0cfSchristos #define	RL	rt->rt3_rules[table_column]
2809dd9d0cfSchristos #define	CFA	rt->rt3_cfa_rule
2819dd9d0cfSchristos 
2829dd9d0cfSchristos int
dwarf_get_fde_info_for_reg(Dwarf_Fde fde,Dwarf_Half table_column,Dwarf_Addr pc_requested,Dwarf_Signed * offset_relevant,Dwarf_Signed * register_num,Dwarf_Signed * offset,Dwarf_Addr * row_pc,Dwarf_Error * error)2839dd9d0cfSchristos dwarf_get_fde_info_for_reg(Dwarf_Fde fde, Dwarf_Half table_column,
2849dd9d0cfSchristos     Dwarf_Addr pc_requested, Dwarf_Signed *offset_relevant,
2859dd9d0cfSchristos     Dwarf_Signed *register_num, Dwarf_Signed *offset, Dwarf_Addr *row_pc,
2869dd9d0cfSchristos     Dwarf_Error *error)
2879dd9d0cfSchristos {
2889dd9d0cfSchristos 	Dwarf_Regtable3 *rt;
2899dd9d0cfSchristos 	Dwarf_Debug dbg;
2909dd9d0cfSchristos 	Dwarf_Addr pc;
2919dd9d0cfSchristos 	int ret;
2929dd9d0cfSchristos 
2939dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
2949dd9d0cfSchristos 
2959dd9d0cfSchristos 	if (fde == NULL || offset_relevant == NULL || register_num == NULL ||
2969dd9d0cfSchristos 	    offset == NULL || row_pc == NULL) {
2979dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2989dd9d0cfSchristos 		return (DW_DLV_ERROR);
2999dd9d0cfSchristos 	}
3009dd9d0cfSchristos 
3019dd9d0cfSchristos 	if (pc_requested < fde->fde_initloc ||
3029dd9d0cfSchristos 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
3039dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
3049dd9d0cfSchristos 		return (DW_DLV_ERROR);
3059dd9d0cfSchristos 	}
3069dd9d0cfSchristos 
3079dd9d0cfSchristos 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
3089dd9d0cfSchristos 	    error);
3099dd9d0cfSchristos 	if (ret != DW_DLE_NONE)
3109dd9d0cfSchristos 		return (DW_DLV_ERROR);
3119dd9d0cfSchristos 
3129dd9d0cfSchristos 	if (table_column == dbg->dbg_frame_cfa_value) {
3139dd9d0cfSchristos 		/* Application ask for CFA. */
3149dd9d0cfSchristos 		*offset_relevant = CFA.dw_offset_relevant;
3159dd9d0cfSchristos 		*register_num = CFA.dw_regnum;
3169dd9d0cfSchristos 		*offset = CFA.dw_offset_or_block_len;
3179dd9d0cfSchristos 	} else {
3189dd9d0cfSchristos 		/* Application ask for normal registers. */
3199dd9d0cfSchristos 		if (table_column >= dbg->dbg_frame_rule_table_size ||
3209dd9d0cfSchristos 		    table_column >= DW_REG_TABLE_SIZE) {
3219dd9d0cfSchristos 			DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
3229dd9d0cfSchristos 			return (DW_DLV_ERROR);
3239dd9d0cfSchristos 		}
3249dd9d0cfSchristos 
3259dd9d0cfSchristos 		*offset_relevant = RL.dw_offset_relevant;
3269dd9d0cfSchristos 		*register_num = RL.dw_regnum;
3279dd9d0cfSchristos 		*offset = RL.dw_offset_or_block_len;
3289dd9d0cfSchristos 	}
3299dd9d0cfSchristos 
3309dd9d0cfSchristos 	*row_pc = pc;
3319dd9d0cfSchristos 
3329dd9d0cfSchristos 	return (DW_DLV_OK);
3339dd9d0cfSchristos }
3349dd9d0cfSchristos 
3359dd9d0cfSchristos int
dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde,Dwarf_Addr pc_requested,Dwarf_Regtable * reg_table,Dwarf_Addr * row_pc,Dwarf_Error * error)3369dd9d0cfSchristos dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, Dwarf_Addr pc_requested,
3379dd9d0cfSchristos     Dwarf_Regtable *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
3389dd9d0cfSchristos {
3399dd9d0cfSchristos 	Dwarf_Debug dbg;
3409dd9d0cfSchristos 	Dwarf_Regtable3 *rt;
3419dd9d0cfSchristos 	Dwarf_Addr pc;
3429dd9d0cfSchristos 	Dwarf_Half cfa;
3439dd9d0cfSchristos 	int i, ret;
3449dd9d0cfSchristos 
3459dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
3469dd9d0cfSchristos 
3479dd9d0cfSchristos 	if (fde == NULL || reg_table == NULL || row_pc == NULL) {
3489dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
3499dd9d0cfSchristos 		return (DW_DLV_ERROR);
3509dd9d0cfSchristos 	}
3519dd9d0cfSchristos 
3529dd9d0cfSchristos 	assert(dbg != NULL);
3539dd9d0cfSchristos 
3549dd9d0cfSchristos 	if (pc_requested < fde->fde_initloc ||
3559dd9d0cfSchristos 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
3569dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
3579dd9d0cfSchristos 		return (DW_DLV_ERROR);
3589dd9d0cfSchristos 	}
3599dd9d0cfSchristos 
3609dd9d0cfSchristos 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
3619dd9d0cfSchristos 	    error);
3629dd9d0cfSchristos 	if (ret != DW_DLE_NONE)
3639dd9d0cfSchristos 		return (DW_DLV_ERROR);
3649dd9d0cfSchristos 
3659dd9d0cfSchristos 	/*
3669dd9d0cfSchristos 	 * Copy the CFA rule to the column intended for holding the CFA,
3679dd9d0cfSchristos 	 * if it's within the range of regtable.
3689dd9d0cfSchristos 	 */
3699dd9d0cfSchristos 	cfa = dbg->dbg_frame_cfa_value;
3709dd9d0cfSchristos 	if (cfa < DW_REG_TABLE_SIZE) {
3719dd9d0cfSchristos 		reg_table->rules[cfa].dw_offset_relevant =
3729dd9d0cfSchristos 		    CFA.dw_offset_relevant;
3739dd9d0cfSchristos 		reg_table->rules[cfa].dw_regnum = CFA.dw_regnum;
3749dd9d0cfSchristos 		reg_table->rules[cfa].dw_offset = CFA.dw_offset_or_block_len;
3759dd9d0cfSchristos 	}
3769dd9d0cfSchristos 
3779dd9d0cfSchristos 	/*
3789dd9d0cfSchristos 	 * Copy other columns.
3799dd9d0cfSchristos 	 */
3809dd9d0cfSchristos 	for (i = 0; i < DW_REG_TABLE_SIZE && i < dbg->dbg_frame_rule_table_size;
3819dd9d0cfSchristos 	     i++) {
3829dd9d0cfSchristos 
3839dd9d0cfSchristos 		/* Do not overwrite CFA column */
3849dd9d0cfSchristos 		if (i == cfa)
3859dd9d0cfSchristos 			continue;
3869dd9d0cfSchristos 
3879dd9d0cfSchristos 		reg_table->rules[i].dw_offset_relevant =
3889dd9d0cfSchristos 		    rt->rt3_rules[i].dw_offset_relevant;
3899dd9d0cfSchristos 		reg_table->rules[i].dw_regnum = rt->rt3_rules[i].dw_regnum;
3909dd9d0cfSchristos 		reg_table->rules[i].dw_offset =
3919dd9d0cfSchristos 		    rt->rt3_rules[i].dw_offset_or_block_len;
3929dd9d0cfSchristos 	}
3939dd9d0cfSchristos 
3949dd9d0cfSchristos 	*row_pc = pc;
3959dd9d0cfSchristos 
3969dd9d0cfSchristos 	return (DW_DLV_OK);
3979dd9d0cfSchristos }
3989dd9d0cfSchristos 
3999dd9d0cfSchristos int
dwarf_get_fde_info_for_reg3(Dwarf_Fde fde,Dwarf_Half table_column,Dwarf_Addr pc_requested,Dwarf_Small * value_type,Dwarf_Signed * offset_relevant,Dwarf_Signed * register_num,Dwarf_Signed * offset_or_block_len,Dwarf_Ptr * block_ptr,Dwarf_Addr * row_pc,Dwarf_Error * error)4009dd9d0cfSchristos dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, Dwarf_Half table_column,
4019dd9d0cfSchristos     Dwarf_Addr pc_requested, Dwarf_Small *value_type,
4029dd9d0cfSchristos     Dwarf_Signed *offset_relevant, Dwarf_Signed *register_num,
4039dd9d0cfSchristos     Dwarf_Signed *offset_or_block_len, Dwarf_Ptr *block_ptr,
4049dd9d0cfSchristos     Dwarf_Addr *row_pc, Dwarf_Error *error)
4059dd9d0cfSchristos {
4069dd9d0cfSchristos 	Dwarf_Regtable3 *rt;
4079dd9d0cfSchristos 	Dwarf_Debug dbg;
4089dd9d0cfSchristos 	Dwarf_Addr pc;
4099dd9d0cfSchristos 	int ret;
4109dd9d0cfSchristos 
4119dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
4129dd9d0cfSchristos 
4139dd9d0cfSchristos 	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
4149dd9d0cfSchristos 	    register_num == NULL || offset_or_block_len == NULL ||
4159dd9d0cfSchristos 	    block_ptr == NULL || row_pc == NULL) {
4169dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
4179dd9d0cfSchristos 		return (DW_DLV_ERROR);
4189dd9d0cfSchristos 	}
4199dd9d0cfSchristos 
4209dd9d0cfSchristos 	if (pc_requested < fde->fde_initloc ||
4219dd9d0cfSchristos 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
4229dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
4239dd9d0cfSchristos 		return (DW_DLV_ERROR);
4249dd9d0cfSchristos 	}
4259dd9d0cfSchristos 
4269dd9d0cfSchristos 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
4279dd9d0cfSchristos 	    error);
4289dd9d0cfSchristos 	if (ret != DW_DLE_NONE)
4299dd9d0cfSchristos 		return (DW_DLV_ERROR);
4309dd9d0cfSchristos 
4319dd9d0cfSchristos 	if (table_column >= dbg->dbg_frame_rule_table_size) {
4329dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
4339dd9d0cfSchristos 		return (DW_DLV_ERROR);
4349dd9d0cfSchristos 	}
4359dd9d0cfSchristos 
4369dd9d0cfSchristos 	*value_type = RL.dw_value_type;
4379dd9d0cfSchristos 	*offset_relevant = RL.dw_offset_relevant;
4389dd9d0cfSchristos 	*register_num = RL.dw_regnum;
4399dd9d0cfSchristos 	*offset_or_block_len = RL.dw_offset_or_block_len;
4409dd9d0cfSchristos 	*block_ptr = RL.dw_block_ptr;
4419dd9d0cfSchristos 	*row_pc = pc;
4429dd9d0cfSchristos 
4439dd9d0cfSchristos 	return (DW_DLV_OK);
4449dd9d0cfSchristos }
4459dd9d0cfSchristos 
4469dd9d0cfSchristos int
dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde,Dwarf_Addr pc_requested,Dwarf_Small * value_type,Dwarf_Signed * offset_relevant,Dwarf_Signed * register_num,Dwarf_Signed * offset_or_block_len,Dwarf_Ptr * block_ptr,Dwarf_Addr * row_pc,Dwarf_Error * error)4479dd9d0cfSchristos dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
4489dd9d0cfSchristos     Dwarf_Small *value_type, Dwarf_Signed *offset_relevant,
4499dd9d0cfSchristos     Dwarf_Signed *register_num, Dwarf_Signed *offset_or_block_len,
4509dd9d0cfSchristos     Dwarf_Ptr *block_ptr, Dwarf_Addr *row_pc, Dwarf_Error *error)
4519dd9d0cfSchristos {
4529dd9d0cfSchristos 	Dwarf_Regtable3 *rt;
4539dd9d0cfSchristos 	Dwarf_Debug dbg;
4549dd9d0cfSchristos 	Dwarf_Addr pc;
4559dd9d0cfSchristos 	int ret;
4569dd9d0cfSchristos 
4579dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
4589dd9d0cfSchristos 
4599dd9d0cfSchristos 	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
4609dd9d0cfSchristos 	    register_num == NULL || offset_or_block_len == NULL ||
4619dd9d0cfSchristos 	    block_ptr == NULL || row_pc == NULL) {
4629dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
4639dd9d0cfSchristos 		return (DW_DLV_ERROR);
4649dd9d0cfSchristos 	}
4659dd9d0cfSchristos 
4669dd9d0cfSchristos 	if (pc_requested < fde->fde_initloc ||
4679dd9d0cfSchristos 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
4689dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
4699dd9d0cfSchristos 		return (DW_DLV_ERROR);
4709dd9d0cfSchristos 	}
4719dd9d0cfSchristos 
4729dd9d0cfSchristos 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
4739dd9d0cfSchristos 	    error);
4749dd9d0cfSchristos 	if (ret != DW_DLE_NONE)
4759dd9d0cfSchristos 		return (DW_DLV_ERROR);
4769dd9d0cfSchristos 
4779dd9d0cfSchristos 	*value_type = CFA.dw_value_type;
4789dd9d0cfSchristos 	*offset_relevant = CFA.dw_offset_relevant;
4799dd9d0cfSchristos 	*register_num = CFA.dw_regnum;
4809dd9d0cfSchristos 	*offset_or_block_len = CFA.dw_offset_or_block_len;
4819dd9d0cfSchristos 	*block_ptr = CFA.dw_block_ptr;
4829dd9d0cfSchristos 	*row_pc = pc;
4839dd9d0cfSchristos 
4849dd9d0cfSchristos 	return (DW_DLV_OK);
4859dd9d0cfSchristos }
4869dd9d0cfSchristos 
4879dd9d0cfSchristos #undef	RL
4889dd9d0cfSchristos #undef	CFA
4899dd9d0cfSchristos 
4909dd9d0cfSchristos int
dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde,Dwarf_Addr pc_requested,Dwarf_Regtable3 * reg_table,Dwarf_Addr * row_pc,Dwarf_Error * error)4919dd9d0cfSchristos dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
4929dd9d0cfSchristos     Dwarf_Regtable3 *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
4939dd9d0cfSchristos {
4949dd9d0cfSchristos 	Dwarf_Regtable3 *rt;
4959dd9d0cfSchristos 	Dwarf_Debug dbg;
4969dd9d0cfSchristos 	Dwarf_Addr pc;
4979dd9d0cfSchristos 	int ret;
4989dd9d0cfSchristos 
4999dd9d0cfSchristos 	dbg = fde != NULL ? fde->fde_dbg : NULL;
5009dd9d0cfSchristos 
5019dd9d0cfSchristos 	if (fde == NULL || reg_table == NULL || reg_table->rt3_rules == NULL ||
5029dd9d0cfSchristos 	    row_pc == NULL) {
5039dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
5049dd9d0cfSchristos 		return (DW_DLV_ERROR);
5059dd9d0cfSchristos 	}
5069dd9d0cfSchristos 
5079dd9d0cfSchristos 	assert(dbg != NULL);
5089dd9d0cfSchristos 
5099dd9d0cfSchristos 	if (pc_requested < fde->fde_initloc ||
5109dd9d0cfSchristos 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
5119dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
5129dd9d0cfSchristos 		return (DW_DLV_ERROR);
5139dd9d0cfSchristos 	}
5149dd9d0cfSchristos 
5159dd9d0cfSchristos 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
5169dd9d0cfSchristos 	    error);
5179dd9d0cfSchristos 	if (ret != DW_DLE_NONE)
5189dd9d0cfSchristos 		return (DW_DLV_ERROR);
5199dd9d0cfSchristos 
5209dd9d0cfSchristos 	ret = _dwarf_frame_regtable_copy(dbg, &reg_table, rt, error);
5219dd9d0cfSchristos 	if (ret != DW_DLE_NONE)
5229dd9d0cfSchristos 		return (DW_DLV_ERROR);
5239dd9d0cfSchristos 
5249dd9d0cfSchristos 	*row_pc = pc;
5259dd9d0cfSchristos 
5269dd9d0cfSchristos 	return (DW_DLV_OK);
5279dd9d0cfSchristos }
5289dd9d0cfSchristos 
5299dd9d0cfSchristos int
dwarf_expand_frame_instructions(Dwarf_Cie cie,Dwarf_Ptr instruction,Dwarf_Unsigned len,Dwarf_Frame_Op ** ret_oplist,Dwarf_Signed * ret_opcnt,Dwarf_Error * error)5309dd9d0cfSchristos dwarf_expand_frame_instructions(Dwarf_Cie cie, Dwarf_Ptr instruction,
5319dd9d0cfSchristos     Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
5329dd9d0cfSchristos     Dwarf_Error *error)
5339dd9d0cfSchristos {
5349dd9d0cfSchristos 	Dwarf_Debug dbg;
5359dd9d0cfSchristos 	int ret;
5369dd9d0cfSchristos 
5379dd9d0cfSchristos 	dbg = cie != NULL ? cie->cie_dbg : NULL;
5389dd9d0cfSchristos 
5399dd9d0cfSchristos 	if (cie == NULL || instruction == NULL || len == 0 ||
5409dd9d0cfSchristos 	    ret_oplist == NULL || ret_opcnt == NULL) {
5419dd9d0cfSchristos 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
5429dd9d0cfSchristos 		return (DW_DLV_ERROR);
5439dd9d0cfSchristos 	}
5449dd9d0cfSchristos 
54542bd3019Schristos 	ret = _dwarf_frame_get_fop(dbg, cie->cie_addrsize, instruction, len,
54642bd3019Schristos 	    ret_oplist, ret_opcnt, error);
5479dd9d0cfSchristos 	if (ret != DW_DLE_NONE)
5489dd9d0cfSchristos 		return (DW_DLV_ERROR);
5499dd9d0cfSchristos 
5509dd9d0cfSchristos 	return (DW_DLV_OK);
5519dd9d0cfSchristos }
5529dd9d0cfSchristos 
5539dd9d0cfSchristos Dwarf_Half
dwarf_set_frame_rule_table_size(Dwarf_Debug dbg,Dwarf_Half value)5549dd9d0cfSchristos dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
5559dd9d0cfSchristos {
5569dd9d0cfSchristos 	Dwarf_Half old_value;
5579dd9d0cfSchristos 
5589dd9d0cfSchristos 	old_value = dbg->dbg_frame_rule_table_size;
5599dd9d0cfSchristos 	dbg->dbg_frame_rule_table_size = value;
5609dd9d0cfSchristos 
5619dd9d0cfSchristos 	return (old_value);
5629dd9d0cfSchristos }
5639dd9d0cfSchristos 
5649dd9d0cfSchristos Dwarf_Half
dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg,Dwarf_Half value)5659dd9d0cfSchristos dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value)
5669dd9d0cfSchristos {
5679dd9d0cfSchristos 	Dwarf_Half old_value;
5689dd9d0cfSchristos 
5699dd9d0cfSchristos 	old_value = dbg->dbg_frame_rule_initial_value;
5709dd9d0cfSchristos 	dbg->dbg_frame_rule_initial_value = value;
5719dd9d0cfSchristos 
5729dd9d0cfSchristos 	return (old_value);
5739dd9d0cfSchristos }
5749dd9d0cfSchristos 
5759dd9d0cfSchristos Dwarf_Half
dwarf_set_frame_cfa_value(Dwarf_Debug dbg,Dwarf_Half value)5769dd9d0cfSchristos dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
5779dd9d0cfSchristos {
5789dd9d0cfSchristos 	Dwarf_Half old_value;
5799dd9d0cfSchristos 
5809dd9d0cfSchristos 	old_value = dbg->dbg_frame_cfa_value;
5819dd9d0cfSchristos 	dbg->dbg_frame_cfa_value = value;
5829dd9d0cfSchristos 
5839dd9d0cfSchristos 	return (old_value);
5849dd9d0cfSchristos }
5859dd9d0cfSchristos 
5869dd9d0cfSchristos Dwarf_Half
dwarf_set_frame_same_value(Dwarf_Debug dbg,Dwarf_Half value)5879dd9d0cfSchristos dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
5889dd9d0cfSchristos {
5899dd9d0cfSchristos 	Dwarf_Half old_value;
5909dd9d0cfSchristos 
5919dd9d0cfSchristos 	old_value = dbg->dbg_frame_same_value;
5929dd9d0cfSchristos 	dbg->dbg_frame_same_value = value;
5939dd9d0cfSchristos 
5949dd9d0cfSchristos 	return (old_value);
5959dd9d0cfSchristos }
5969dd9d0cfSchristos 
5979dd9d0cfSchristos Dwarf_Half
dwarf_set_frame_undefined_value(Dwarf_Debug dbg,Dwarf_Half value)5989dd9d0cfSchristos dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
5999dd9d0cfSchristos {
6009dd9d0cfSchristos 	Dwarf_Half old_value;
6019dd9d0cfSchristos 
6029dd9d0cfSchristos 	old_value = dbg->dbg_frame_undefined_value;
6039dd9d0cfSchristos 	dbg->dbg_frame_undefined_value = value;
6049dd9d0cfSchristos 
6059dd9d0cfSchristos 	return (old_value);
6069dd9d0cfSchristos }
607