xref: /freebsd/contrib/elftoolchain/libdwarf/dwarf_frame.c (revision 2de3b87a120614a3b053be7dd845b72f1e9ce804)
1*2de3b87aSKai Wang /*-
2*2de3b87aSKai Wang  * Copyright (c) 2009,2011 Kai Wang
3*2de3b87aSKai Wang  * All rights reserved.
4*2de3b87aSKai Wang  *
5*2de3b87aSKai Wang  * Redistribution and use in source and binary forms, with or without
6*2de3b87aSKai Wang  * modification, are permitted provided that the following conditions
7*2de3b87aSKai Wang  * are met:
8*2de3b87aSKai Wang  * 1. Redistributions of source code must retain the above copyright
9*2de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer.
10*2de3b87aSKai Wang  * 2. Redistributions in binary form must reproduce the above copyright
11*2de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer in the
12*2de3b87aSKai Wang  *    documentation and/or other materials provided with the distribution.
13*2de3b87aSKai Wang  *
14*2de3b87aSKai Wang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*2de3b87aSKai Wang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*2de3b87aSKai Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*2de3b87aSKai Wang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*2de3b87aSKai Wang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*2de3b87aSKai Wang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*2de3b87aSKai Wang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*2de3b87aSKai Wang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*2de3b87aSKai Wang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*2de3b87aSKai Wang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*2de3b87aSKai Wang  * SUCH DAMAGE.
25*2de3b87aSKai Wang  */
26*2de3b87aSKai Wang 
27*2de3b87aSKai Wang #include "_libdwarf.h"
28*2de3b87aSKai Wang 
29*2de3b87aSKai Wang ELFTC_VCSID("$Id: dwarf_frame.c 2073 2011-10-27 03:30:47Z jkoshy $");
30*2de3b87aSKai Wang 
31*2de3b87aSKai Wang int
32*2de3b87aSKai Wang dwarf_get_fde_list(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
33*2de3b87aSKai Wang     Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
34*2de3b87aSKai Wang     Dwarf_Error *error)
35*2de3b87aSKai Wang {
36*2de3b87aSKai Wang 
37*2de3b87aSKai Wang 	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
38*2de3b87aSKai Wang 	    fde_list == NULL || fde_count == NULL) {
39*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
40*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
41*2de3b87aSKai Wang 	}
42*2de3b87aSKai Wang 
43*2de3b87aSKai Wang 	if (dbg->dbg_internal_reg_table == NULL) {
44*2de3b87aSKai Wang 		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
45*2de3b87aSKai Wang 			return (DW_DLV_ERROR);
46*2de3b87aSKai Wang 	}
47*2de3b87aSKai Wang 
48*2de3b87aSKai Wang 	if (dbg->dbg_frame == NULL) {
49*2de3b87aSKai Wang 		if (_dwarf_frame_section_load(dbg, error) != DW_DLE_NONE)
50*2de3b87aSKai Wang 			return (DW_DLV_ERROR);
51*2de3b87aSKai Wang 		if (dbg->dbg_frame == NULL) {
52*2de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
53*2de3b87aSKai Wang 			return (DW_DLV_NO_ENTRY);
54*2de3b87aSKai Wang 		}
55*2de3b87aSKai Wang 	}
56*2de3b87aSKai Wang 
57*2de3b87aSKai Wang 	if (dbg->dbg_frame->fs_ciearray == NULL ||
58*2de3b87aSKai Wang 	    dbg->dbg_frame->fs_fdearray == NULL) {
59*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
60*2de3b87aSKai Wang 		return (DW_DLV_NO_ENTRY);
61*2de3b87aSKai Wang 	}
62*2de3b87aSKai Wang 
63*2de3b87aSKai Wang 	*cie_list = dbg->dbg_frame->fs_ciearray;
64*2de3b87aSKai Wang 	*cie_count = dbg->dbg_frame->fs_cielen;
65*2de3b87aSKai Wang 	*fde_list = dbg->dbg_frame->fs_fdearray;
66*2de3b87aSKai Wang 	*fde_count = dbg->dbg_frame->fs_fdelen;
67*2de3b87aSKai Wang 
68*2de3b87aSKai Wang 	return (DW_DLV_OK);
69*2de3b87aSKai Wang }
70*2de3b87aSKai Wang 
71*2de3b87aSKai Wang int
72*2de3b87aSKai Wang dwarf_get_fde_list_eh(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
73*2de3b87aSKai Wang     Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
74*2de3b87aSKai Wang     Dwarf_Error *error)
75*2de3b87aSKai Wang {
76*2de3b87aSKai Wang 
77*2de3b87aSKai Wang 	if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
78*2de3b87aSKai Wang 	    fde_list == NULL || fde_count == NULL) {
79*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
80*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
81*2de3b87aSKai Wang 	}
82*2de3b87aSKai Wang 
83*2de3b87aSKai Wang 	if (dbg->dbg_internal_reg_table == NULL) {
84*2de3b87aSKai Wang 		if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
85*2de3b87aSKai Wang 			return (DW_DLV_ERROR);
86*2de3b87aSKai Wang 	}
87*2de3b87aSKai Wang 
88*2de3b87aSKai Wang 	if (dbg->dbg_eh_frame == NULL) {
89*2de3b87aSKai Wang 		if (_dwarf_frame_section_load_eh(dbg, error) != DW_DLE_NONE)
90*2de3b87aSKai Wang 			return (DW_DLV_ERROR);
91*2de3b87aSKai Wang 		if (dbg->dbg_eh_frame == NULL) {
92*2de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
93*2de3b87aSKai Wang 			return (DW_DLV_NO_ENTRY);
94*2de3b87aSKai Wang 		}
95*2de3b87aSKai Wang 	}
96*2de3b87aSKai Wang 
97*2de3b87aSKai Wang 	if (dbg->dbg_eh_frame->fs_ciearray == NULL ||
98*2de3b87aSKai Wang 	    dbg->dbg_eh_frame->fs_fdearray == NULL) {
99*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
100*2de3b87aSKai Wang 		return (DW_DLV_NO_ENTRY);
101*2de3b87aSKai Wang 	}
102*2de3b87aSKai Wang 
103*2de3b87aSKai Wang 	*cie_list = dbg->dbg_eh_frame->fs_ciearray;
104*2de3b87aSKai Wang 	*cie_count = dbg->dbg_eh_frame->fs_cielen;
105*2de3b87aSKai Wang 	*fde_list = dbg->dbg_eh_frame->fs_fdearray;
106*2de3b87aSKai Wang 	*fde_count = dbg->dbg_eh_frame->fs_fdelen;
107*2de3b87aSKai Wang 
108*2de3b87aSKai Wang 	return (DW_DLV_OK);
109*2de3b87aSKai Wang }
110*2de3b87aSKai Wang 
111*2de3b87aSKai Wang int
112*2de3b87aSKai Wang dwarf_get_fde_n(Dwarf_Fde *fdelist, Dwarf_Unsigned fde_index,
113*2de3b87aSKai Wang     Dwarf_Fde *ret_fde, Dwarf_Error *error)
114*2de3b87aSKai Wang {
115*2de3b87aSKai Wang 	Dwarf_FrameSec fs;
116*2de3b87aSKai Wang 	Dwarf_Debug dbg;
117*2de3b87aSKai Wang 
118*2de3b87aSKai Wang 	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
119*2de3b87aSKai Wang 
120*2de3b87aSKai Wang 	if (fdelist == NULL || ret_fde == NULL) {
121*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
122*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
123*2de3b87aSKai Wang 	}
124*2de3b87aSKai Wang 
125*2de3b87aSKai Wang 	fs = fdelist[0]->fde_fs;
126*2de3b87aSKai Wang 	assert(fs != NULL);
127*2de3b87aSKai Wang 
128*2de3b87aSKai Wang 	if (fde_index >= fs->fs_fdelen) {
129*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
130*2de3b87aSKai Wang 		return (DW_DLV_NO_ENTRY);
131*2de3b87aSKai Wang 	}
132*2de3b87aSKai Wang 
133*2de3b87aSKai Wang 	*ret_fde = fdelist[fde_index];
134*2de3b87aSKai Wang 
135*2de3b87aSKai Wang 	return (DW_DLV_OK);
136*2de3b87aSKai Wang }
137*2de3b87aSKai Wang 
138*2de3b87aSKai Wang int
139*2de3b87aSKai Wang dwarf_get_fde_at_pc(Dwarf_Fde *fdelist, Dwarf_Addr pc, Dwarf_Fde *ret_fde,
140*2de3b87aSKai Wang     Dwarf_Addr *lopc, Dwarf_Addr *hipc, Dwarf_Error *error)
141*2de3b87aSKai Wang {
142*2de3b87aSKai Wang 	Dwarf_FrameSec fs;
143*2de3b87aSKai Wang 	Dwarf_Debug dbg;
144*2de3b87aSKai Wang 	Dwarf_Fde fde;
145*2de3b87aSKai Wang 	int i;
146*2de3b87aSKai Wang 
147*2de3b87aSKai Wang 	dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
148*2de3b87aSKai Wang 
149*2de3b87aSKai Wang 	if (fdelist == NULL || ret_fde == NULL || lopc == NULL ||
150*2de3b87aSKai Wang 	    hipc == NULL) {
151*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
152*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
153*2de3b87aSKai Wang 	}
154*2de3b87aSKai Wang 
155*2de3b87aSKai Wang 	fs = fdelist[0]->fde_fs;
156*2de3b87aSKai Wang 	assert(fs != NULL);
157*2de3b87aSKai Wang 
158*2de3b87aSKai Wang 	for (i = 0; (Dwarf_Unsigned)i < fs->fs_fdelen; i++) {
159*2de3b87aSKai Wang 		fde = fdelist[i];
160*2de3b87aSKai Wang 		if (pc >= fde->fde_initloc && pc < fde->fde_initloc +
161*2de3b87aSKai Wang 		    fde->fde_adrange) {
162*2de3b87aSKai Wang 			*ret_fde = fde;
163*2de3b87aSKai Wang 			*lopc = fde->fde_initloc;
164*2de3b87aSKai Wang 			*hipc = fde->fde_initloc + fde->fde_adrange - 1;
165*2de3b87aSKai Wang 			return (DW_DLV_OK);
166*2de3b87aSKai Wang 		}
167*2de3b87aSKai Wang 	}
168*2de3b87aSKai Wang 
169*2de3b87aSKai Wang 	DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
170*2de3b87aSKai Wang 	return (DW_DLV_NO_ENTRY);
171*2de3b87aSKai Wang }
172*2de3b87aSKai Wang 
173*2de3b87aSKai Wang int
174*2de3b87aSKai Wang dwarf_get_cie_of_fde(Dwarf_Fde fde, Dwarf_Cie *ret_cie, Dwarf_Error *error)
175*2de3b87aSKai Wang {
176*2de3b87aSKai Wang 	Dwarf_Debug dbg;
177*2de3b87aSKai Wang 
178*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
179*2de3b87aSKai Wang 
180*2de3b87aSKai Wang 	if (fde == NULL || ret_cie == NULL) {
181*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
182*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
183*2de3b87aSKai Wang 	}
184*2de3b87aSKai Wang 
185*2de3b87aSKai Wang 	*ret_cie = fde->fde_cie;
186*2de3b87aSKai Wang 
187*2de3b87aSKai Wang 	return (DW_DLV_OK);
188*2de3b87aSKai Wang }
189*2de3b87aSKai Wang 
190*2de3b87aSKai Wang int
191*2de3b87aSKai Wang dwarf_get_fde_range(Dwarf_Fde fde, Dwarf_Addr *low_pc, Dwarf_Unsigned *func_len,
192*2de3b87aSKai Wang     Dwarf_Ptr *fde_bytes, Dwarf_Unsigned *fde_byte_len, Dwarf_Off *cie_offset,
193*2de3b87aSKai Wang     Dwarf_Signed *cie_index, Dwarf_Off *fde_offset, Dwarf_Error *error)
194*2de3b87aSKai Wang {
195*2de3b87aSKai Wang 	Dwarf_Debug dbg;
196*2de3b87aSKai Wang 
197*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
198*2de3b87aSKai Wang 
199*2de3b87aSKai Wang 	if (fde == NULL || low_pc == NULL || func_len == NULL ||
200*2de3b87aSKai Wang 	    fde_bytes == NULL || fde_byte_len == NULL || cie_offset == NULL ||
201*2de3b87aSKai Wang 	    cie_index == NULL || fde_offset == NULL) {
202*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
203*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
204*2de3b87aSKai Wang 	}
205*2de3b87aSKai Wang 
206*2de3b87aSKai Wang 	*low_pc = fde->fde_initloc;
207*2de3b87aSKai Wang 	*func_len = fde->fde_adrange;
208*2de3b87aSKai Wang 	*fde_bytes = fde->fde_addr;
209*2de3b87aSKai Wang 	*fde_byte_len = fde->fde_length;
210*2de3b87aSKai Wang 	*cie_offset = fde->fde_cieoff;
211*2de3b87aSKai Wang 	*cie_index = fde->fde_cie->cie_index;
212*2de3b87aSKai Wang 	*fde_offset = fde->fde_offset;
213*2de3b87aSKai Wang 
214*2de3b87aSKai Wang 	return (DW_DLV_OK);
215*2de3b87aSKai Wang }
216*2de3b87aSKai Wang 
217*2de3b87aSKai Wang int
218*2de3b87aSKai Wang dwarf_get_cie_info(Dwarf_Cie cie, Dwarf_Unsigned *bytes_in_cie,
219*2de3b87aSKai Wang     Dwarf_Small *version, char **augmenter, Dwarf_Unsigned *caf,
220*2de3b87aSKai Wang     Dwarf_Unsigned *daf, Dwarf_Half *ra, Dwarf_Ptr *initinst,
221*2de3b87aSKai Wang     Dwarf_Unsigned *inst_len, Dwarf_Error *error)
222*2de3b87aSKai Wang {
223*2de3b87aSKai Wang 
224*2de3b87aSKai Wang 	if (cie == NULL || bytes_in_cie == NULL || version == NULL ||
225*2de3b87aSKai Wang 	    augmenter == NULL || caf == NULL || daf == NULL || ra == NULL ||
226*2de3b87aSKai Wang 	    initinst == NULL || inst_len == NULL) {
227*2de3b87aSKai Wang 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
228*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
229*2de3b87aSKai Wang 	}
230*2de3b87aSKai Wang 
231*2de3b87aSKai Wang 	*bytes_in_cie = cie->cie_length;
232*2de3b87aSKai Wang 	*version = cie->cie_version;
233*2de3b87aSKai Wang 	*augmenter = (char *) cie->cie_augment;
234*2de3b87aSKai Wang 	*caf = cie->cie_caf;
235*2de3b87aSKai Wang 	*daf = cie->cie_daf;
236*2de3b87aSKai Wang 	*ra = cie->cie_ra;
237*2de3b87aSKai Wang 	*initinst = cie->cie_initinst;
238*2de3b87aSKai Wang 	*inst_len = cie->cie_instlen;
239*2de3b87aSKai Wang 
240*2de3b87aSKai Wang 	return (DW_DLV_OK);
241*2de3b87aSKai Wang }
242*2de3b87aSKai Wang 
243*2de3b87aSKai Wang int
244*2de3b87aSKai Wang dwarf_get_cie_index(Dwarf_Cie cie, Dwarf_Signed *cie_index, Dwarf_Error *error)
245*2de3b87aSKai Wang {
246*2de3b87aSKai Wang 
247*2de3b87aSKai Wang 	if (cie == NULL || cie_index == NULL) {
248*2de3b87aSKai Wang 		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
249*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
250*2de3b87aSKai Wang 	}
251*2de3b87aSKai Wang 
252*2de3b87aSKai Wang 	*cie_index = cie->cie_index;
253*2de3b87aSKai Wang 
254*2de3b87aSKai Wang 	return (DW_DLV_OK);
255*2de3b87aSKai Wang }
256*2de3b87aSKai Wang 
257*2de3b87aSKai Wang int
258*2de3b87aSKai Wang dwarf_get_fde_instr_bytes(Dwarf_Fde fde, Dwarf_Ptr *ret_inst,
259*2de3b87aSKai Wang     Dwarf_Unsigned *ret_len, Dwarf_Error *error)
260*2de3b87aSKai Wang {
261*2de3b87aSKai Wang 	Dwarf_Debug dbg;
262*2de3b87aSKai Wang 
263*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
264*2de3b87aSKai Wang 
265*2de3b87aSKai Wang 	if (fde == NULL || ret_inst == NULL || ret_len == NULL) {
266*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
267*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
268*2de3b87aSKai Wang 	}
269*2de3b87aSKai Wang 
270*2de3b87aSKai Wang 	*ret_inst = fde->fde_inst;
271*2de3b87aSKai Wang 	*ret_len = fde->fde_instlen;
272*2de3b87aSKai Wang 
273*2de3b87aSKai Wang 	return (DW_DLV_OK);
274*2de3b87aSKai Wang }
275*2de3b87aSKai Wang 
276*2de3b87aSKai Wang #define	RL	rt->rt3_rules[table_column]
277*2de3b87aSKai Wang #define	CFA	rt->rt3_cfa_rule
278*2de3b87aSKai Wang 
279*2de3b87aSKai Wang int
280*2de3b87aSKai Wang dwarf_get_fde_info_for_reg(Dwarf_Fde fde, Dwarf_Half table_column,
281*2de3b87aSKai Wang     Dwarf_Addr pc_requested, Dwarf_Signed *offset_relevant,
282*2de3b87aSKai Wang     Dwarf_Signed *register_num, Dwarf_Signed *offset, Dwarf_Addr *row_pc,
283*2de3b87aSKai Wang     Dwarf_Error *error)
284*2de3b87aSKai Wang {
285*2de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
286*2de3b87aSKai Wang 	Dwarf_Debug dbg;
287*2de3b87aSKai Wang 	Dwarf_Addr pc;
288*2de3b87aSKai Wang 	int ret;
289*2de3b87aSKai Wang 
290*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
291*2de3b87aSKai Wang 
292*2de3b87aSKai Wang 	if (fde == NULL || offset_relevant == NULL || register_num == NULL ||
293*2de3b87aSKai Wang 	    offset == NULL || row_pc == NULL) {
294*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
295*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
296*2de3b87aSKai Wang 	}
297*2de3b87aSKai Wang 
298*2de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
299*2de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
300*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
301*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
302*2de3b87aSKai Wang 	}
303*2de3b87aSKai Wang 
304*2de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
305*2de3b87aSKai Wang 	    error);
306*2de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
307*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
308*2de3b87aSKai Wang 
309*2de3b87aSKai Wang 	if (table_column == dbg->dbg_frame_cfa_value) {
310*2de3b87aSKai Wang 		/* Application ask for CFA. */
311*2de3b87aSKai Wang 		*offset_relevant = CFA.dw_offset_relevant;
312*2de3b87aSKai Wang 		*register_num = CFA.dw_regnum;
313*2de3b87aSKai Wang 		*offset = CFA.dw_offset_or_block_len;
314*2de3b87aSKai Wang 	} else {
315*2de3b87aSKai Wang 		/* Application ask for normal registers. */
316*2de3b87aSKai Wang 		if (table_column >= dbg->dbg_frame_rule_table_size ||
317*2de3b87aSKai Wang 		    table_column >= DW_REG_TABLE_SIZE) {
318*2de3b87aSKai Wang 			DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
319*2de3b87aSKai Wang 			return (DW_DLV_ERROR);
320*2de3b87aSKai Wang 		}
321*2de3b87aSKai Wang 
322*2de3b87aSKai Wang 		*offset_relevant = RL.dw_offset_relevant;
323*2de3b87aSKai Wang 		*register_num = RL.dw_regnum;
324*2de3b87aSKai Wang 		*offset = RL.dw_offset_or_block_len;
325*2de3b87aSKai Wang 	}
326*2de3b87aSKai Wang 
327*2de3b87aSKai Wang 	*row_pc = pc;
328*2de3b87aSKai Wang 
329*2de3b87aSKai Wang 	return (DW_DLV_OK);
330*2de3b87aSKai Wang }
331*2de3b87aSKai Wang 
332*2de3b87aSKai Wang int
333*2de3b87aSKai Wang dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, Dwarf_Addr pc_requested,
334*2de3b87aSKai Wang     Dwarf_Regtable *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
335*2de3b87aSKai Wang {
336*2de3b87aSKai Wang 	Dwarf_Debug dbg;
337*2de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
338*2de3b87aSKai Wang 	Dwarf_Addr pc;
339*2de3b87aSKai Wang 	Dwarf_Half cfa;
340*2de3b87aSKai Wang 	int i, ret;
341*2de3b87aSKai Wang 
342*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
343*2de3b87aSKai Wang 
344*2de3b87aSKai Wang 	if (fde == NULL || reg_table == NULL || row_pc == NULL) {
345*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
346*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
347*2de3b87aSKai Wang 	}
348*2de3b87aSKai Wang 
349*2de3b87aSKai Wang 	assert(dbg != NULL);
350*2de3b87aSKai Wang 
351*2de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
352*2de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
353*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
354*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
355*2de3b87aSKai Wang 	}
356*2de3b87aSKai Wang 
357*2de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
358*2de3b87aSKai Wang 	    error);
359*2de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
360*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
361*2de3b87aSKai Wang 
362*2de3b87aSKai Wang 	/*
363*2de3b87aSKai Wang 	 * Copy the CFA rule to the column intended for holding the CFA,
364*2de3b87aSKai Wang 	 * if it's within the range of regtable.
365*2de3b87aSKai Wang 	 */
366*2de3b87aSKai Wang 	cfa = dbg->dbg_frame_cfa_value;
367*2de3b87aSKai Wang 	if (cfa < DW_REG_TABLE_SIZE) {
368*2de3b87aSKai Wang 		reg_table->rules[cfa].dw_offset_relevant =
369*2de3b87aSKai Wang 		    CFA.dw_offset_relevant;
370*2de3b87aSKai Wang 		reg_table->rules[cfa].dw_regnum = CFA.dw_regnum;
371*2de3b87aSKai Wang 		reg_table->rules[cfa].dw_offset = CFA.dw_offset_or_block_len;
372*2de3b87aSKai Wang 	}
373*2de3b87aSKai Wang 
374*2de3b87aSKai Wang 	/*
375*2de3b87aSKai Wang 	 * Copy other columns.
376*2de3b87aSKai Wang 	 */
377*2de3b87aSKai Wang 	for (i = 0; i < DW_REG_TABLE_SIZE && i < dbg->dbg_frame_rule_table_size;
378*2de3b87aSKai Wang 	     i++) {
379*2de3b87aSKai Wang 
380*2de3b87aSKai Wang 		/* Do not overwrite CFA column */
381*2de3b87aSKai Wang 		if (i == cfa)
382*2de3b87aSKai Wang 			continue;
383*2de3b87aSKai Wang 
384*2de3b87aSKai Wang 		reg_table->rules[i].dw_offset_relevant =
385*2de3b87aSKai Wang 		    rt->rt3_rules[i].dw_offset_relevant;
386*2de3b87aSKai Wang 		reg_table->rules[i].dw_regnum = rt->rt3_rules[i].dw_regnum;
387*2de3b87aSKai Wang 		reg_table->rules[i].dw_offset =
388*2de3b87aSKai Wang 		    rt->rt3_rules[i].dw_offset_or_block_len;
389*2de3b87aSKai Wang 	}
390*2de3b87aSKai Wang 
391*2de3b87aSKai Wang 	*row_pc = pc;
392*2de3b87aSKai Wang 
393*2de3b87aSKai Wang 	return (DW_DLV_OK);
394*2de3b87aSKai Wang }
395*2de3b87aSKai Wang 
396*2de3b87aSKai Wang int
397*2de3b87aSKai Wang dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, Dwarf_Half table_column,
398*2de3b87aSKai Wang     Dwarf_Addr pc_requested, Dwarf_Small *value_type,
399*2de3b87aSKai Wang     Dwarf_Signed *offset_relevant, Dwarf_Signed *register_num,
400*2de3b87aSKai Wang     Dwarf_Signed *offset_or_block_len, Dwarf_Ptr *block_ptr,
401*2de3b87aSKai Wang     Dwarf_Addr *row_pc, Dwarf_Error *error)
402*2de3b87aSKai Wang {
403*2de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
404*2de3b87aSKai Wang 	Dwarf_Debug dbg;
405*2de3b87aSKai Wang 	Dwarf_Addr pc;
406*2de3b87aSKai Wang 	int ret;
407*2de3b87aSKai Wang 
408*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
409*2de3b87aSKai Wang 
410*2de3b87aSKai Wang 	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
411*2de3b87aSKai Wang 	    register_num == NULL || offset_or_block_len == NULL ||
412*2de3b87aSKai Wang 	    block_ptr == NULL || row_pc == NULL) {
413*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
414*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
415*2de3b87aSKai Wang 	}
416*2de3b87aSKai Wang 
417*2de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
418*2de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
419*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
420*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
421*2de3b87aSKai Wang 	}
422*2de3b87aSKai Wang 
423*2de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
424*2de3b87aSKai Wang 	    error);
425*2de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
426*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
427*2de3b87aSKai Wang 
428*2de3b87aSKai Wang 	if (table_column >= dbg->dbg_frame_rule_table_size) {
429*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
430*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
431*2de3b87aSKai Wang 	}
432*2de3b87aSKai Wang 
433*2de3b87aSKai Wang 	*value_type = RL.dw_value_type;
434*2de3b87aSKai Wang 	*offset_relevant = RL.dw_offset_relevant;
435*2de3b87aSKai Wang 	*register_num = RL.dw_regnum;
436*2de3b87aSKai Wang 	*offset_or_block_len = RL.dw_offset_or_block_len;
437*2de3b87aSKai Wang 	*block_ptr = RL.dw_block_ptr;
438*2de3b87aSKai Wang 	*row_pc = pc;
439*2de3b87aSKai Wang 
440*2de3b87aSKai Wang 	return (DW_DLV_OK);
441*2de3b87aSKai Wang }
442*2de3b87aSKai Wang 
443*2de3b87aSKai Wang int
444*2de3b87aSKai Wang dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
445*2de3b87aSKai Wang     Dwarf_Small *value_type, Dwarf_Signed *offset_relevant,
446*2de3b87aSKai Wang     Dwarf_Signed *register_num, Dwarf_Signed *offset_or_block_len,
447*2de3b87aSKai Wang     Dwarf_Ptr *block_ptr, Dwarf_Addr *row_pc, Dwarf_Error *error)
448*2de3b87aSKai Wang {
449*2de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
450*2de3b87aSKai Wang 	Dwarf_Debug dbg;
451*2de3b87aSKai Wang 	Dwarf_Addr pc;
452*2de3b87aSKai Wang 	int ret;
453*2de3b87aSKai Wang 
454*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
455*2de3b87aSKai Wang 
456*2de3b87aSKai Wang 	if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
457*2de3b87aSKai Wang 	    register_num == NULL || offset_or_block_len == NULL ||
458*2de3b87aSKai Wang 	    block_ptr == NULL || row_pc == NULL) {
459*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
460*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
461*2de3b87aSKai Wang 	}
462*2de3b87aSKai Wang 
463*2de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
464*2de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
465*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
466*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
467*2de3b87aSKai Wang 	}
468*2de3b87aSKai Wang 
469*2de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
470*2de3b87aSKai Wang 	    error);
471*2de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
472*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
473*2de3b87aSKai Wang 
474*2de3b87aSKai Wang 	*value_type = CFA.dw_value_type;
475*2de3b87aSKai Wang 	*offset_relevant = CFA.dw_offset_relevant;
476*2de3b87aSKai Wang 	*register_num = CFA.dw_regnum;
477*2de3b87aSKai Wang 	*offset_or_block_len = CFA.dw_offset_or_block_len;
478*2de3b87aSKai Wang 	*block_ptr = CFA.dw_block_ptr;
479*2de3b87aSKai Wang 	*row_pc = pc;
480*2de3b87aSKai Wang 
481*2de3b87aSKai Wang 	return (DW_DLV_OK);
482*2de3b87aSKai Wang }
483*2de3b87aSKai Wang 
484*2de3b87aSKai Wang #undef	RL
485*2de3b87aSKai Wang #undef	CFA
486*2de3b87aSKai Wang 
487*2de3b87aSKai Wang int
488*2de3b87aSKai Wang dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
489*2de3b87aSKai Wang     Dwarf_Regtable3 *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
490*2de3b87aSKai Wang {
491*2de3b87aSKai Wang 	Dwarf_Regtable3 *rt;
492*2de3b87aSKai Wang 	Dwarf_Debug dbg;
493*2de3b87aSKai Wang 	Dwarf_Addr pc;
494*2de3b87aSKai Wang 	int ret;
495*2de3b87aSKai Wang 
496*2de3b87aSKai Wang 	dbg = fde != NULL ? fde->fde_dbg : NULL;
497*2de3b87aSKai Wang 
498*2de3b87aSKai Wang 	if (fde == NULL || reg_table == NULL || reg_table->rt3_rules == NULL ||
499*2de3b87aSKai Wang 	    row_pc == NULL) {
500*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
501*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
502*2de3b87aSKai Wang 	}
503*2de3b87aSKai Wang 
504*2de3b87aSKai Wang 	assert(dbg != NULL);
505*2de3b87aSKai Wang 
506*2de3b87aSKai Wang 	if (pc_requested < fde->fde_initloc ||
507*2de3b87aSKai Wang 	    pc_requested >= fde->fde_initloc + fde->fde_adrange) {
508*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
509*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
510*2de3b87aSKai Wang 	}
511*2de3b87aSKai Wang 
512*2de3b87aSKai Wang 	ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
513*2de3b87aSKai Wang 	    error);
514*2de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
515*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
516*2de3b87aSKai Wang 
517*2de3b87aSKai Wang 	ret = _dwarf_frame_regtable_copy(dbg, &reg_table, rt, error);
518*2de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
519*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
520*2de3b87aSKai Wang 
521*2de3b87aSKai Wang 	*row_pc = pc;
522*2de3b87aSKai Wang 
523*2de3b87aSKai Wang 	return (DW_DLV_OK);
524*2de3b87aSKai Wang }
525*2de3b87aSKai Wang 
526*2de3b87aSKai Wang int
527*2de3b87aSKai Wang dwarf_expand_frame_instructions(Dwarf_Cie cie, Dwarf_Ptr instruction,
528*2de3b87aSKai Wang     Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
529*2de3b87aSKai Wang     Dwarf_Error *error)
530*2de3b87aSKai Wang {
531*2de3b87aSKai Wang 	Dwarf_Debug dbg;
532*2de3b87aSKai Wang 	int ret;
533*2de3b87aSKai Wang 
534*2de3b87aSKai Wang 	dbg = cie != NULL ? cie->cie_dbg : NULL;
535*2de3b87aSKai Wang 
536*2de3b87aSKai Wang 	if (cie == NULL || instruction == NULL || len == 0 ||
537*2de3b87aSKai Wang 	    ret_oplist == NULL || ret_opcnt == NULL) {
538*2de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
539*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
540*2de3b87aSKai Wang 	}
541*2de3b87aSKai Wang 
542*2de3b87aSKai Wang 	ret = _dwarf_frame_get_fop(dbg, instruction, len, ret_oplist, ret_opcnt,
543*2de3b87aSKai Wang 	    error);
544*2de3b87aSKai Wang 	if (ret != DW_DLE_NONE)
545*2de3b87aSKai Wang 		return (DW_DLV_ERROR);
546*2de3b87aSKai Wang 
547*2de3b87aSKai Wang 	return (DW_DLV_OK);
548*2de3b87aSKai Wang }
549*2de3b87aSKai Wang 
550*2de3b87aSKai Wang Dwarf_Half
551*2de3b87aSKai Wang dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
552*2de3b87aSKai Wang {
553*2de3b87aSKai Wang 	Dwarf_Half old_value;
554*2de3b87aSKai Wang 
555*2de3b87aSKai Wang 	old_value = dbg->dbg_frame_rule_table_size;
556*2de3b87aSKai Wang 	dbg->dbg_frame_rule_table_size = value;
557*2de3b87aSKai Wang 
558*2de3b87aSKai Wang 	return (old_value);
559*2de3b87aSKai Wang }
560*2de3b87aSKai Wang 
561*2de3b87aSKai Wang Dwarf_Half
562*2de3b87aSKai Wang dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value)
563*2de3b87aSKai Wang {
564*2de3b87aSKai Wang 	Dwarf_Half old_value;
565*2de3b87aSKai Wang 
566*2de3b87aSKai Wang 	old_value = dbg->dbg_frame_rule_initial_value;
567*2de3b87aSKai Wang 	dbg->dbg_frame_rule_initial_value = value;
568*2de3b87aSKai Wang 
569*2de3b87aSKai Wang 	return (old_value);
570*2de3b87aSKai Wang }
571*2de3b87aSKai Wang 
572*2de3b87aSKai Wang Dwarf_Half
573*2de3b87aSKai Wang dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
574*2de3b87aSKai Wang {
575*2de3b87aSKai Wang 	Dwarf_Half old_value;
576*2de3b87aSKai Wang 
577*2de3b87aSKai Wang 	old_value = dbg->dbg_frame_cfa_value;
578*2de3b87aSKai Wang 	dbg->dbg_frame_cfa_value = value;
579*2de3b87aSKai Wang 
580*2de3b87aSKai Wang 	return (old_value);
581*2de3b87aSKai Wang }
582*2de3b87aSKai Wang 
583*2de3b87aSKai Wang Dwarf_Half
584*2de3b87aSKai Wang dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
585*2de3b87aSKai Wang {
586*2de3b87aSKai Wang 	Dwarf_Half old_value;
587*2de3b87aSKai Wang 
588*2de3b87aSKai Wang 	old_value = dbg->dbg_frame_same_value;
589*2de3b87aSKai Wang 	dbg->dbg_frame_same_value = value;
590*2de3b87aSKai Wang 
591*2de3b87aSKai Wang 	return (old_value);
592*2de3b87aSKai Wang }
593*2de3b87aSKai Wang 
594*2de3b87aSKai Wang Dwarf_Half
595*2de3b87aSKai Wang dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
596*2de3b87aSKai Wang {
597*2de3b87aSKai Wang 	Dwarf_Half old_value;
598*2de3b87aSKai Wang 
599*2de3b87aSKai Wang 	old_value = dbg->dbg_frame_undefined_value;
600*2de3b87aSKai Wang 	dbg->dbg_frame_undefined_value = value;
601*2de3b87aSKai Wang 
602*2de3b87aSKai Wang 	return (old_value);
603*2de3b87aSKai Wang }
604