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