12de3b87aSKai Wang /*-
22de3b87aSKai Wang  * Copyright (c) 2009,2011 Kai Wang
32de3b87aSKai Wang  * All rights reserved.
42de3b87aSKai Wang  *
52de3b87aSKai Wang  * Redistribution and use in source and binary forms, with or without
62de3b87aSKai Wang  * modification, are permitted provided that the following conditions
72de3b87aSKai Wang  * are met:
82de3b87aSKai Wang  * 1. Redistributions of source code must retain the above copyright
92de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer.
102de3b87aSKai Wang  * 2. Redistributions in binary form must reproduce the above copyright
112de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer in the
122de3b87aSKai Wang  *    documentation and/or other materials provided with the distribution.
132de3b87aSKai Wang  *
142de3b87aSKai Wang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152de3b87aSKai Wang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162de3b87aSKai Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172de3b87aSKai Wang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182de3b87aSKai Wang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192de3b87aSKai Wang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202de3b87aSKai Wang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212de3b87aSKai Wang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222de3b87aSKai Wang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232de3b87aSKai Wang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242de3b87aSKai Wang  * SUCH DAMAGE.
252de3b87aSKai Wang  */
262de3b87aSKai Wang 
272de3b87aSKai Wang #include "_libdwarf.h"
282de3b87aSKai Wang 
29*cf781b2eSEd Maste ELFTC_VCSID("$Id: dwarf_frame.c 3106 2014-12-19 16:00:58Z kaiwang27 $");
302de3b87aSKai Wang 
312de3b87aSKai Wang 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)322de3b87aSKai Wang dwarf_get_fde_list(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
332de3b87aSKai Wang     Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
342de3b87aSKai Wang     Dwarf_Error *error)
352de3b87aSKai Wang {
362de3b87aSKai Wang 
372de3b87aSKai Wang 	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
382de3b87aSKai Wang 	    fde_list == NULL || fde_count == NULL) {
392de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
402de3b87aSKai Wang 		return (DW_DLV_ERROR);
412de3b87aSKai Wang 	}
422de3b87aSKai Wang 
432de3b87aSKai Wang 	if (dbg->dbg_internal_reg_table == NULL) {
442de3b87aSKai Wang 		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
452de3b87aSKai Wang 			return (DW_DLV_ERROR);
462de3b87aSKai Wang 	}
472de3b87aSKai Wang 
482de3b87aSKai Wang 	if (dbg->dbg_frame == NULL) {
492de3b87aSKai Wang 		if (_dwarf_frame_section_load(dbg, error) != DW_DLE_NONE)
502de3b87aSKai Wang 			return (DW_DLV_ERROR);
512de3b87aSKai Wang 		if (dbg->dbg_frame == NULL) {
522de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
532de3b87aSKai Wang 			return (DW_DLV_NO_ENTRY);
542de3b87aSKai Wang 		}
552de3b87aSKai Wang 	}
562de3b87aSKai Wang 
572de3b87aSKai Wang 	if (dbg->dbg_frame->fs_ciearray == NULL ||
582de3b87aSKai Wang 	    dbg->dbg_frame->fs_fdearray == NULL) {
592de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
602de3b87aSKai Wang 		return (DW_DLV_NO_ENTRY);
612de3b87aSKai Wang 	}
622de3b87aSKai Wang 
632de3b87aSKai Wang 	*cie_list = dbg->dbg_frame->fs_ciearray;
642de3b87aSKai Wang 	*cie_count = dbg->dbg_frame->fs_cielen;
652de3b87aSKai Wang 	*fde_list = dbg->dbg_frame->fs_fdearray;
662de3b87aSKai Wang 	*fde_count = dbg->dbg_frame->fs_fdelen;
672de3b87aSKai Wang 
682de3b87aSKai Wang 	return (DW_DLV_OK);
692de3b87aSKai Wang }
702de3b87aSKai Wang 
712de3b87aSKai Wang 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)722de3b87aSKai Wang dwarf_get_fde_list_eh(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
732de3b87aSKai Wang     Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
742de3b87aSKai Wang     Dwarf_Error *error)
752de3b87aSKai Wang {
762de3b87aSKai Wang 
772de3b87aSKai Wang 	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
782de3b87aSKai Wang 	    fde_list == NULL || fde_count == NULL) {
792de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
802de3b87aSKai Wang 		return (DW_DLV_ERROR);
812de3b87aSKai Wang 	}
822de3b87aSKai Wang 
832de3b87aSKai Wang 	if (dbg->dbg_internal_reg_table == NULL) {
842de3b87aSKai Wang 		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
852de3b87aSKai Wang 			return (DW_DLV_ERROR);
862de3b87aSKai Wang 	}
872de3b87aSKai Wang 
882de3b87aSKai Wang 	if (dbg->dbg_eh_frame == NULL) {
892de3b87aSKai Wang 		if (_dwarf_frame_section_load_eh(dbg, error) != DW_DLE_NONE)
902de3b87aSKai Wang 			return (DW_DLV_ERROR);
912de3b87aSKai Wang 		if (dbg->dbg_eh_frame == NULL) {
922de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
932de3b87aSKai Wang 			return (DW_DLV_NO_ENTRY);
942de3b87aSKai Wang 		}
952de3b87aSKai Wang 	}
962de3b87aSKai Wang 
972de3b87aSKai Wang 	if (dbg->dbg_eh_frame->fs_ciearray == NULL ||
982de3b87aSKai Wang 	    dbg->dbg_eh_frame->fs_fdearray == NULL) {
992de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
1002de3b87aSKai Wang 		return (DW_DLV_NO_ENTRY);
1012de3b87aSKai Wang 	}
1022de3b87aSKai Wang 
1032de3b87aSKai Wang 	*cie_list = dbg->dbg_eh_frame->fs_ciearray;
1042de3b87aSKai Wang 	*cie_count = dbg->dbg_eh_frame->fs_cielen;
1052de3b87aSKai Wang 	*fde_list = dbg->dbg_eh_frame->fs_fdearray;
1062de3b87aSKai Wang 	*fde_count = dbg->dbg_eh_frame->fs_fdelen;
1072de3b87aSKai Wang 
1082de3b87aSKai Wang 	return (DW_DLV_OK);
1092de3b87aSKai Wang }
1102de3b87aSKai Wang 
1112de3b87aSKai Wang int
dwarf_get_fde_n(Dwarf_Fde * fdelist,Dwarf_Unsigned fde_index,Dwarf_Fde * ret_fde,Dwarf_Error * error)1122de3b87aSKai Wang dwarf_get_fde_n(Dwarf_Fde *fdelist, Dwarf_Unsigned fde_index,
1132de3b87aSKai Wang     Dwarf_Fde *ret_fde, Dwarf_Error *error)
1142de3b87aSKai Wang {
1152de3b87aSKai Wang 	Dwarf_FrameSec fs;
1162de3b87aSKai Wang 	Dwarf_Debug dbg;
1172de3b87aSKai Wang 
1182de3b87aSKai Wang 	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
1192de3b87aSKai Wang 
1202de3b87aSKai Wang 	if (fdelist == NULL || ret_fde == NULL) {
1212de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1222de3b87aSKai Wang 		return (DW_DLV_ERROR);
1232de3b87aSKai Wang 	}
1242de3b87aSKai Wang 
1252de3b87aSKai Wang 	fs = fdelist[0]->fde_fs;
1262de3b87aSKai Wang 	assert(fs != NULL);
1272de3b87aSKai Wang 
1282de3b87aSKai Wang 	if (fde_index >= fs->fs_fdelen) {
1292de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
1302de3b87aSKai Wang 		return (DW_DLV_NO_ENTRY);
1312de3b87aSKai Wang 	}
1322de3b87aSKai Wang 
1332de3b87aSKai Wang 	*ret_fde = fdelist[fde_index];
1342de3b87aSKai Wang 
1352de3b87aSKai Wang 	return (DW_DLV_OK);
1362de3b87aSKai Wang }
1372de3b87aSKai Wang 
1382de3b87aSKai Wang 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)1392de3b87aSKai Wang dwarf_get_fde_at_pc(Dwarf_Fde *fdelist, Dwarf_Addr pc, Dwarf_Fde *ret_fde,
1402de3b87aSKai Wang     Dwarf_Addr *lopc, Dwarf_Addr *hipc, Dwarf_Error *error)
1412de3b87aSKai Wang {
1422de3b87aSKai Wang 	Dwarf_FrameSec fs;
1432de3b87aSKai Wang 	Dwarf_Debug dbg;
1442de3b87aSKai Wang 	Dwarf_Fde fde;
1452de3b87aSKai Wang 	int i;
1462de3b87aSKai Wang 
1472de3b87aSKai Wang 	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
1482de3b87aSKai Wang 
1492de3b87aSKai Wang 	if (fdelist == NULL || ret_fde == NULL || lopc == NULL ||
1502de3b87aSKai Wang 	    hipc == NULL) {
1512de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1522de3b87aSKai Wang 		return (DW_DLV_ERROR);
1532de3b87aSKai Wang 	}
1542de3b87aSKai Wang 
1552de3b87aSKai Wang 	fs = fdelist[0]->fde_fs;
1562de3b87aSKai Wang 	assert(fs != NULL);
1572de3b87aSKai Wang 
1582de3b87aSKai Wang 	for (i = 0; (Dwarf_Unsigned)i < fs->fs_fdelen; i++) {
1592de3b87aSKai Wang 		fde = fdelist[i];
1602de3b87aSKai Wang 		if (pc >= fde->fde_initloc && pc < fde->fde_initloc +
1612de3b87aSKai Wang 		    fde->fde_adrange) {
1622de3b87aSKai Wang 			*ret_fde = fde;
1632de3b87aSKai Wang 			*lopc = fde->fde_initloc;
1642de3b87aSKai Wang 			*hipc = fde->fde_initloc + fde->fde_adrange - 1;
1652de3b87aSKai Wang 			return (DW_DLV_OK);
1662de3b87aSKai Wang 		}
1672de3b87aSKai Wang 	}
1682de3b87aSKai Wang 
1692de3b87aSKai Wang 	DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
1702de3b87aSKai Wang 	return (DW_DLV_NO_ENTRY);
1712de3b87aSKai Wang }
1722de3b87aSKai Wang 
1732de3b87aSKai Wang int
dwarf_get_cie_of_fde(Dwarf_Fde fde,Dwarf_Cie * ret_cie,Dwarf_Error * error)1742de3b87aSKai Wang dwarf_get_cie_of_fde(Dwarf_Fde fde, Dwarf_Cie *ret_cie, Dwarf_Error *error)
1752de3b87aSKai Wang {
1762de3b87aSKai Wang 	Dwarf_Debug dbg;
1772de3b87aSKai Wang 
1782de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
1792de3b87aSKai Wang 
1802de3b87aSKai Wang 	if (fde == NULL || ret_cie == NULL) {
1812de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
1822de3b87aSKai Wang 		return (DW_DLV_ERROR);
1832de3b87aSKai Wang 	}
1842de3b87aSKai Wang 
1852de3b87aSKai Wang 	*ret_cie = fde->fde_cie;
1862de3b87aSKai Wang 
1872de3b87aSKai Wang 	return (DW_DLV_OK);
1882de3b87aSKai Wang }
1892de3b87aSKai Wang 
1902de3b87aSKai Wang 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)1912de3b87aSKai Wang dwarf_get_fde_range(Dwarf_Fde fde, Dwarf_Addr *low_pc, Dwarf_Unsigned *func_len,
1922de3b87aSKai Wang     Dwarf_Ptr *fde_bytes, Dwarf_Unsigned *fde_byte_len, Dwarf_Off *cie_offset,
1932de3b87aSKai Wang     Dwarf_Signed *cie_index, Dwarf_Off *fde_offset, Dwarf_Error *error)
1942de3b87aSKai Wang {
1952de3b87aSKai Wang 	Dwarf_Debug dbg;
1962de3b87aSKai Wang 
1972de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
1982de3b87aSKai Wang 
1992de3b87aSKai Wang 	if (fde == NULL || low_pc == NULL || func_len == NULL ||
2002de3b87aSKai Wang 	    fde_bytes == NULL || fde_byte_len == NULL || cie_offset == NULL ||
2012de3b87aSKai Wang 	    cie_index == NULL || fde_offset == NULL) {
2022de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2032de3b87aSKai Wang 		return (DW_DLV_ERROR);
2042de3b87aSKai Wang 	}
2052de3b87aSKai Wang 
2062de3b87aSKai Wang 	*low_pc = fde->fde_initloc;
2072de3b87aSKai Wang 	*func_len = fde->fde_adrange;
2082de3b87aSKai Wang 	*fde_bytes = fde->fde_addr;
2092de3b87aSKai Wang 	*fde_byte_len = fde->fde_length;
2102de3b87aSKai Wang 	*cie_offset = fde->fde_cieoff;
2112de3b87aSKai Wang 	*cie_index = fde->fde_cie->cie_index;
2122de3b87aSKai Wang 	*fde_offset = fde->fde_offset;
2132de3b87aSKai Wang 
2142de3b87aSKai Wang 	return (DW_DLV_OK);
2152de3b87aSKai Wang }
2162de3b87aSKai Wang 
2172de3b87aSKai Wang 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)2182de3b87aSKai Wang dwarf_get_cie_info(Dwarf_Cie cie, Dwarf_Unsigned *bytes_in_cie,
2192de3b87aSKai Wang     Dwarf_Small *version, char **augmenter, Dwarf_Unsigned *caf,
2202de3b87aSKai Wang     Dwarf_Unsigned *daf, Dwarf_Half *ra, Dwarf_Ptr *initinst,
2212de3b87aSKai Wang     Dwarf_Unsigned *inst_len, Dwarf_Error *error)
2222de3b87aSKai Wang {
2232de3b87aSKai Wang 
2242de3b87aSKai Wang 	if (cie == NULL || bytes_in_cie == NULL || version == NULL ||
2252de3b87aSKai Wang 	    augmenter == NULL || caf == NULL || daf == NULL || ra == NULL ||
2262de3b87aSKai Wang 	    initinst == NULL || inst_len == NULL) {
2272de3b87aSKai Wang 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
2282de3b87aSKai Wang 		return (DW_DLV_ERROR);
2292de3b87aSKai Wang 	}
2302de3b87aSKai Wang 
2312de3b87aSKai Wang 	*bytes_in_cie = cie->cie_length;
2322de3b87aSKai Wang 	*version = cie->cie_version;
2332de3b87aSKai Wang 	*augmenter = (char *) cie->cie_augment;
2342de3b87aSKai Wang 	*caf = cie->cie_caf;
2352de3b87aSKai Wang 	*daf = cie->cie_daf;
2362de3b87aSKai Wang 	*ra = cie->cie_ra;
2372de3b87aSKai Wang 	*initinst = cie->cie_initinst;
2382de3b87aSKai Wang 	*inst_len = cie->cie_instlen;
2392de3b87aSKai Wang 
2402de3b87aSKai Wang 	return (DW_DLV_OK);
2412de3b87aSKai Wang }
2422de3b87aSKai Wang 
2432de3b87aSKai Wang int
dwarf_get_cie_index(Dwarf_Cie cie,Dwarf_Signed * cie_index,Dwarf_Error * error)2442de3b87aSKai Wang dwarf_get_cie_index(Dwarf_Cie cie, Dwarf_Signed *cie_index, Dwarf_Error *error)
2452de3b87aSKai Wang {
2462de3b87aSKai Wang 
2472de3b87aSKai Wang 	if (cie == NULL || cie_index == NULL) {
2482de3b87aSKai Wang 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
2492de3b87aSKai Wang 		return (DW_DLV_ERROR);
2502de3b87aSKai Wang 	}
2512de3b87aSKai Wang 
2522de3b87aSKai Wang 	*cie_index = cie->cie_index;
2532de3b87aSKai Wang 
2542de3b87aSKai Wang 	return (DW_DLV_OK);
2552de3b87aSKai Wang }
2562de3b87aSKai Wang 
2572de3b87aSKai Wang int
dwarf_get_fde_instr_bytes(Dwarf_Fde fde,Dwarf_Ptr * ret_inst,Dwarf_Unsigned * ret_len,Dwarf_Error * error)2582de3b87aSKai Wang dwarf_get_fde_instr_bytes(Dwarf_Fde fde, Dwarf_Ptr *ret_inst,
2592de3b87aSKai Wang     Dwarf_Unsigned *ret_len, Dwarf_Error *error)
2602de3b87aSKai Wang {
2612de3b87aSKai Wang 	Dwarf_Debug dbg;
2622de3b87aSKai Wang 
2632de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
2642de3b87aSKai Wang 
2652de3b87aSKai Wang 	if (fde == NULL || ret_inst == NULL || ret_len == NULL) {
2662de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2672de3b87aSKai Wang 		return (DW_DLV_ERROR);
2682de3b87aSKai Wang 	}
2692de3b87aSKai Wang 
2702de3b87aSKai Wang 	*ret_inst = fde->fde_inst;
2712de3b87aSKai Wang 	*ret_len = fde->fde_instlen;
2722de3b87aSKai Wang 
2732de3b87aSKai Wang 	return (DW_DLV_OK);
2742de3b87aSKai Wang }
2752de3b87aSKai Wang 
2762de3b87aSKai Wang #define	RL	rt->rt3_rules[table_column]
2772de3b87aSKai Wang #define	CFA	rt->rt3_cfa_rule
2782de3b87aSKai Wang 
2792de3b87aSKai Wang 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)2802de3b87aSKai Wang dwarf_get_fde_info_for_reg(Dwarf_Fde fde, Dwarf_Half table_column,
2812de3b87aSKai Wang     Dwarf_Addr pc_requested, Dwarf_Signed *offset_relevant,
2822de3b87aSKai Wang     Dwarf_Signed *register_num, Dwarf_Signed *offset, Dwarf_Addr *row_pc,
2832de3b87aSKai Wang     Dwarf_Error *error)
2842de3b87aSKai Wang {
2852de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
2862de3b87aSKai Wang 	Dwarf_Debug dbg;
2872de3b87aSKai Wang 	Dwarf_Addr pc;
2882de3b87aSKai Wang 	int ret;
2892de3b87aSKai Wang 
2902de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
2912de3b87aSKai Wang 
2922de3b87aSKai Wang 	if (fde == NULL || offset_relevant == NULL || register_num == NULL ||
2932de3b87aSKai Wang 	    offset == NULL || row_pc == NULL) {
2942de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
2952de3b87aSKai Wang 		return (DW_DLV_ERROR);
2962de3b87aSKai Wang 	}
2972de3b87aSKai Wang 
2982de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
2992de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
3002de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
3012de3b87aSKai Wang 		return (DW_DLV_ERROR);
3022de3b87aSKai Wang 	}
3032de3b87aSKai Wang 
3042de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
3052de3b87aSKai Wang 	    error);
3062de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
3072de3b87aSKai Wang 		return (DW_DLV_ERROR);
3082de3b87aSKai Wang 
3092de3b87aSKai Wang 	if (table_column == dbg->dbg_frame_cfa_value) {
3102de3b87aSKai Wang 		/* Application ask for CFA. */
3112de3b87aSKai Wang 		*offset_relevant = CFA.dw_offset_relevant;
3122de3b87aSKai Wang 		*register_num = CFA.dw_regnum;
3132de3b87aSKai Wang 		*offset = CFA.dw_offset_or_block_len;
3142de3b87aSKai Wang 	} else {
3152de3b87aSKai Wang 		/* Application ask for normal registers. */
3162de3b87aSKai Wang 		if (table_column >= dbg->dbg_frame_rule_table_size ||
3172de3b87aSKai Wang 		    table_column >= DW_REG_TABLE_SIZE) {
3182de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
3192de3b87aSKai Wang 			return (DW_DLV_ERROR);
3202de3b87aSKai Wang 		}
3212de3b87aSKai Wang 
3222de3b87aSKai Wang 		*offset_relevant = RL.dw_offset_relevant;
3232de3b87aSKai Wang 		*register_num = RL.dw_regnum;
3242de3b87aSKai Wang 		*offset = RL.dw_offset_or_block_len;
3252de3b87aSKai Wang 	}
3262de3b87aSKai Wang 
3272de3b87aSKai Wang 	*row_pc = pc;
3282de3b87aSKai Wang 
3292de3b87aSKai Wang 	return (DW_DLV_OK);
3302de3b87aSKai Wang }
3312de3b87aSKai Wang 
3322de3b87aSKai Wang 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)3332de3b87aSKai Wang dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, Dwarf_Addr pc_requested,
3342de3b87aSKai Wang     Dwarf_Regtable *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
3352de3b87aSKai Wang {
3362de3b87aSKai Wang 	Dwarf_Debug dbg;
3372de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
3382de3b87aSKai Wang 	Dwarf_Addr pc;
3392de3b87aSKai Wang 	Dwarf_Half cfa;
3402de3b87aSKai Wang 	int i, ret;
3412de3b87aSKai Wang 
3422de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
3432de3b87aSKai Wang 
3442de3b87aSKai Wang 	if (fde == NULL || reg_table == NULL || row_pc == NULL) {
3452de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
3462de3b87aSKai Wang 		return (DW_DLV_ERROR);
3472de3b87aSKai Wang 	}
3482de3b87aSKai Wang 
3492de3b87aSKai Wang 	assert(dbg != NULL);
3502de3b87aSKai Wang 
3512de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
3522de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
3532de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
3542de3b87aSKai Wang 		return (DW_DLV_ERROR);
3552de3b87aSKai Wang 	}
3562de3b87aSKai Wang 
3572de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
3582de3b87aSKai Wang 	    error);
3592de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
3602de3b87aSKai Wang 		return (DW_DLV_ERROR);
3612de3b87aSKai Wang 
3622de3b87aSKai Wang 	/*
3632de3b87aSKai Wang 	 * Copy the CFA rule to the column intended for holding the CFA,
3642de3b87aSKai Wang 	 * if it's within the range of regtable.
3652de3b87aSKai Wang 	 */
3662de3b87aSKai Wang 	cfa = dbg->dbg_frame_cfa_value;
3672de3b87aSKai Wang 	if (cfa < DW_REG_TABLE_SIZE) {
3682de3b87aSKai Wang 		reg_table->rules[cfa].dw_offset_relevant =
3692de3b87aSKai Wang 		    CFA.dw_offset_relevant;
3702de3b87aSKai Wang 		reg_table->rules[cfa].dw_regnum = CFA.dw_regnum;
3712de3b87aSKai Wang 		reg_table->rules[cfa].dw_offset = CFA.dw_offset_or_block_len;
3722de3b87aSKai Wang 	}
3732de3b87aSKai Wang 
3742de3b87aSKai Wang 	/*
3752de3b87aSKai Wang 	 * Copy other columns.
3762de3b87aSKai Wang 	 */
3772de3b87aSKai Wang 	for (i = 0; i < DW_REG_TABLE_SIZE && i < dbg->dbg_frame_rule_table_size;
3782de3b87aSKai Wang 	     i++) {
3792de3b87aSKai Wang 
3802de3b87aSKai Wang 		/* Do not overwrite CFA column */
3812de3b87aSKai Wang 		if (i == cfa)
3822de3b87aSKai Wang 			continue;
3832de3b87aSKai Wang 
3842de3b87aSKai Wang 		reg_table->rules[i].dw_offset_relevant =
3852de3b87aSKai Wang 		    rt->rt3_rules[i].dw_offset_relevant;
3862de3b87aSKai Wang 		reg_table->rules[i].dw_regnum = rt->rt3_rules[i].dw_regnum;
3872de3b87aSKai Wang 		reg_table->rules[i].dw_offset =
3882de3b87aSKai Wang 		    rt->rt3_rules[i].dw_offset_or_block_len;
3892de3b87aSKai Wang 	}
3902de3b87aSKai Wang 
3912de3b87aSKai Wang 	*row_pc = pc;
3922de3b87aSKai Wang 
3932de3b87aSKai Wang 	return (DW_DLV_OK);
3942de3b87aSKai Wang }
3952de3b87aSKai Wang 
3962de3b87aSKai Wang 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)3972de3b87aSKai Wang dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, Dwarf_Half table_column,
3982de3b87aSKai Wang     Dwarf_Addr pc_requested, Dwarf_Small *value_type,
3992de3b87aSKai Wang     Dwarf_Signed *offset_relevant, Dwarf_Signed *register_num,
4002de3b87aSKai Wang     Dwarf_Signed *offset_or_block_len, Dwarf_Ptr *block_ptr,
4012de3b87aSKai Wang     Dwarf_Addr *row_pc, Dwarf_Error *error)
4022de3b87aSKai Wang {
4032de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
4042de3b87aSKai Wang 	Dwarf_Debug dbg;
4052de3b87aSKai Wang 	Dwarf_Addr pc;
4062de3b87aSKai Wang 	int ret;
4072de3b87aSKai Wang 
4082de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
4092de3b87aSKai Wang 
4102de3b87aSKai Wang 	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
4112de3b87aSKai Wang 	    register_num == NULL || offset_or_block_len == NULL ||
4122de3b87aSKai Wang 	    block_ptr == NULL || row_pc == NULL) {
4132de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
4142de3b87aSKai Wang 		return (DW_DLV_ERROR);
4152de3b87aSKai Wang 	}
4162de3b87aSKai Wang 
4172de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
4182de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
4192de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
4202de3b87aSKai Wang 		return (DW_DLV_ERROR);
4212de3b87aSKai Wang 	}
4222de3b87aSKai Wang 
4232de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
4242de3b87aSKai Wang 	    error);
4252de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
4262de3b87aSKai Wang 		return (DW_DLV_ERROR);
4272de3b87aSKai Wang 
4282de3b87aSKai Wang 	if (table_column >= dbg->dbg_frame_rule_table_size) {
4292de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
4302de3b87aSKai Wang 		return (DW_DLV_ERROR);
4312de3b87aSKai Wang 	}
4322de3b87aSKai Wang 
4332de3b87aSKai Wang 	*value_type = RL.dw_value_type;
4342de3b87aSKai Wang 	*offset_relevant = RL.dw_offset_relevant;
4352de3b87aSKai Wang 	*register_num = RL.dw_regnum;
4362de3b87aSKai Wang 	*offset_or_block_len = RL.dw_offset_or_block_len;
4372de3b87aSKai Wang 	*block_ptr = RL.dw_block_ptr;
4382de3b87aSKai Wang 	*row_pc = pc;
4392de3b87aSKai Wang 
4402de3b87aSKai Wang 	return (DW_DLV_OK);
4412de3b87aSKai Wang }
4422de3b87aSKai Wang 
4432de3b87aSKai Wang 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)4442de3b87aSKai Wang dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
4452de3b87aSKai Wang     Dwarf_Small *value_type, Dwarf_Signed *offset_relevant,
4462de3b87aSKai Wang     Dwarf_Signed *register_num, Dwarf_Signed *offset_or_block_len,
4472de3b87aSKai Wang     Dwarf_Ptr *block_ptr, Dwarf_Addr *row_pc, Dwarf_Error *error)
4482de3b87aSKai Wang {
4492de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
4502de3b87aSKai Wang 	Dwarf_Debug dbg;
4512de3b87aSKai Wang 	Dwarf_Addr pc;
4522de3b87aSKai Wang 	int ret;
4532de3b87aSKai Wang 
4542de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
4552de3b87aSKai Wang 
4562de3b87aSKai Wang 	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
4572de3b87aSKai Wang 	    register_num == NULL || offset_or_block_len == NULL ||
4582de3b87aSKai Wang 	    block_ptr == NULL || row_pc == NULL) {
4592de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
4602de3b87aSKai Wang 		return (DW_DLV_ERROR);
4612de3b87aSKai Wang 	}
4622de3b87aSKai Wang 
4632de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
4642de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
4652de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
4662de3b87aSKai Wang 		return (DW_DLV_ERROR);
4672de3b87aSKai Wang 	}
4682de3b87aSKai Wang 
4692de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
4702de3b87aSKai Wang 	    error);
4712de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
4722de3b87aSKai Wang 		return (DW_DLV_ERROR);
4732de3b87aSKai Wang 
4742de3b87aSKai Wang 	*value_type = CFA.dw_value_type;
4752de3b87aSKai Wang 	*offset_relevant = CFA.dw_offset_relevant;
4762de3b87aSKai Wang 	*register_num = CFA.dw_regnum;
4772de3b87aSKai Wang 	*offset_or_block_len = CFA.dw_offset_or_block_len;
4782de3b87aSKai Wang 	*block_ptr = CFA.dw_block_ptr;
4792de3b87aSKai Wang 	*row_pc = pc;
4802de3b87aSKai Wang 
4812de3b87aSKai Wang 	return (DW_DLV_OK);
4822de3b87aSKai Wang }
4832de3b87aSKai Wang 
4842de3b87aSKai Wang #undef	RL
4852de3b87aSKai Wang #undef	CFA
4862de3b87aSKai Wang 
4872de3b87aSKai Wang 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)4882de3b87aSKai Wang dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
4892de3b87aSKai Wang     Dwarf_Regtable3 *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
4902de3b87aSKai Wang {
4912de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
4922de3b87aSKai Wang 	Dwarf_Debug dbg;
4932de3b87aSKai Wang 	Dwarf_Addr pc;
4942de3b87aSKai Wang 	int ret;
4952de3b87aSKai Wang 
4962de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
4972de3b87aSKai Wang 
4982de3b87aSKai Wang 	if (fde == NULL || reg_table == NULL || reg_table->rt3_rules == NULL ||
4992de3b87aSKai Wang 	    row_pc == NULL) {
5002de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
5012de3b87aSKai Wang 		return (DW_DLV_ERROR);
5022de3b87aSKai Wang 	}
5032de3b87aSKai Wang 
5042de3b87aSKai Wang 	assert(dbg != NULL);
5052de3b87aSKai Wang 
5062de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
5072de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
5082de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
5092de3b87aSKai Wang 		return (DW_DLV_ERROR);
5102de3b87aSKai Wang 	}
5112de3b87aSKai Wang 
5122de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
5132de3b87aSKai Wang 	    error);
5142de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
5152de3b87aSKai Wang 		return (DW_DLV_ERROR);
5162de3b87aSKai Wang 
5172de3b87aSKai Wang 	ret = _dwarf_frame_regtable_copy(dbg, &reg_table, rt, error);
5182de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
5192de3b87aSKai Wang 		return (DW_DLV_ERROR);
5202de3b87aSKai Wang 
5212de3b87aSKai Wang 	*row_pc = pc;
5222de3b87aSKai Wang 
5232de3b87aSKai Wang 	return (DW_DLV_OK);
5242de3b87aSKai Wang }
5252de3b87aSKai Wang 
5262de3b87aSKai Wang 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)5272de3b87aSKai Wang dwarf_expand_frame_instructions(Dwarf_Cie cie, Dwarf_Ptr instruction,
5282de3b87aSKai Wang     Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
5292de3b87aSKai Wang     Dwarf_Error *error)
5302de3b87aSKai Wang {
5312de3b87aSKai Wang 	Dwarf_Debug dbg;
5322de3b87aSKai Wang 	int ret;
5332de3b87aSKai Wang 
5342de3b87aSKai Wang 	dbg = cie != NULL ? cie->cie_dbg : NULL;
5352de3b87aSKai Wang 
5362de3b87aSKai Wang 	if (cie == NULL || instruction == NULL || len == 0 ||
5372de3b87aSKai Wang 	    ret_oplist == NULL || ret_opcnt == NULL) {
5382de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
5392de3b87aSKai Wang 		return (DW_DLV_ERROR);
5402de3b87aSKai Wang 	}
5412de3b87aSKai Wang 
542*cf781b2eSEd Maste 	ret = _dwarf_frame_get_fop(dbg, cie->cie_addrsize, instruction, len,
543*cf781b2eSEd Maste 	    ret_oplist, ret_opcnt, error);
5442de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
5452de3b87aSKai Wang 		return (DW_DLV_ERROR);
5462de3b87aSKai Wang 
5472de3b87aSKai Wang 	return (DW_DLV_OK);
5482de3b87aSKai Wang }
5492de3b87aSKai Wang 
5502de3b87aSKai Wang Dwarf_Half
dwarf_set_frame_rule_table_size(Dwarf_Debug dbg,Dwarf_Half value)5512de3b87aSKai Wang dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
5522de3b87aSKai Wang {
5532de3b87aSKai Wang 	Dwarf_Half old_value;
5542de3b87aSKai Wang 
5552de3b87aSKai Wang 	old_value = dbg->dbg_frame_rule_table_size;
5562de3b87aSKai Wang 	dbg->dbg_frame_rule_table_size = value;
5572de3b87aSKai Wang 
5582de3b87aSKai Wang 	return (old_value);
5592de3b87aSKai Wang }
5602de3b87aSKai Wang 
5612de3b87aSKai Wang Dwarf_Half
dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg,Dwarf_Half value)5622de3b87aSKai Wang dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value)
5632de3b87aSKai Wang {
5642de3b87aSKai Wang 	Dwarf_Half old_value;
5652de3b87aSKai Wang 
5662de3b87aSKai Wang 	old_value = dbg->dbg_frame_rule_initial_value;
5672de3b87aSKai Wang 	dbg->dbg_frame_rule_initial_value = value;
5682de3b87aSKai Wang 
5692de3b87aSKai Wang 	return (old_value);
5702de3b87aSKai Wang }
5712de3b87aSKai Wang 
5722de3b87aSKai Wang Dwarf_Half
dwarf_set_frame_cfa_value(Dwarf_Debug dbg,Dwarf_Half value)5732de3b87aSKai Wang dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
5742de3b87aSKai Wang {
5752de3b87aSKai Wang 	Dwarf_Half old_value;
5762de3b87aSKai Wang 
5772de3b87aSKai Wang 	old_value = dbg->dbg_frame_cfa_value;
5782de3b87aSKai Wang 	dbg->dbg_frame_cfa_value = value;
5792de3b87aSKai Wang 
5802de3b87aSKai Wang 	return (old_value);
5812de3b87aSKai Wang }
5822de3b87aSKai Wang 
5832de3b87aSKai Wang Dwarf_Half
dwarf_set_frame_same_value(Dwarf_Debug dbg,Dwarf_Half value)5842de3b87aSKai Wang dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
5852de3b87aSKai Wang {
5862de3b87aSKai Wang 	Dwarf_Half old_value;
5872de3b87aSKai Wang 
5882de3b87aSKai Wang 	old_value = dbg->dbg_frame_same_value;
5892de3b87aSKai Wang 	dbg->dbg_frame_same_value = value;
5902de3b87aSKai Wang 
5912de3b87aSKai Wang 	return (old_value);
5922de3b87aSKai Wang }
5932de3b87aSKai Wang 
5942de3b87aSKai Wang Dwarf_Half
dwarf_set_frame_undefined_value(Dwarf_Debug dbg,Dwarf_Half value)5952de3b87aSKai Wang dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
5962de3b87aSKai Wang {
5972de3b87aSKai Wang 	Dwarf_Half old_value;
5982de3b87aSKai Wang 
5992de3b87aSKai Wang 	old_value = dbg->dbg_frame_undefined_value;
6002de3b87aSKai Wang 	dbg->dbg_frame_undefined_value = value;
6012de3b87aSKai Wang 
6022de3b87aSKai Wang 	return (old_value);
6032de3b87aSKai Wang }
604