diff options
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/dwarf_frame.c')
-rw-r--r-- | usr/src/tools/ctf/dwarf/common/dwarf_frame.c | 2442 |
1 files changed, 0 insertions, 2442 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_frame.c b/usr/src/tools/ctf/dwarf/common/dwarf_frame.c deleted file mode 100644 index 3a825ee925..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_frame.c +++ /dev/null @@ -1,2442 +0,0 @@ -/* - - Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - - -#include "config.h" -#include "dwarf_incl.h" -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include "dwarf_frame.h" -#include "dwarf_arange.h" /* Using Arange as a way to build a - list */ - -#define FDE_NULL_CHECKS_AND_SET_DBG(fde,dbg ) \ - do { \ - if ((fde) == NULL) { \ - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); \ - return (DW_DLV_ERROR); \ - } \ - (dbg)= (fde)->fd_dbg; \ - if ((dbg) == NULL) { \ - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);\ - return (DW_DLV_ERROR); \ - } } while (0) - - -#define MIN(a,b) (((a) < (b))? a:b) - -static void _dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, - int last_reg_num, - int initial_value); -static int dwarf_initialize_fde_table(Dwarf_Debug dbg, - struct Dwarf_Frame_s *fde_table, - unsigned table_real_data_size, - Dwarf_Error * error); -static void dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table); - -#if 0 -/* Only used for debugging libdwarf. */ -static void dump_frame_rule(char *msg, - struct Dwarf_Reg_Rule_s *reg_rule); -#endif - - - -/* - This function is the heart of the debug_frame stuff. Don't even - think of reading this without reading both the Libdwarf and - consumer API carefully first. This function basically executes - frame instructions contained in a Cie or an Fde, but does in a - number of different ways depending on the information sought. - Start_instr_ptr points to the first byte of the frame instruction - stream, and final_instr_ptr to the to the first byte after the - last. - - The offsets returned in the frame instructions are factored. That - is they need to be multiplied by either the code_alignment_factor - or the data_alignment_factor, as appropriate to obtain the actual - offset. This makes it possible to expand an instruction stream - without the corresponding Cie. However, when an Fde frame instr - sequence is being expanded there must be a valid Cie with a pointer - to an initial table row. - - - If successful, returns DW_DLV_OK - And sets returned_count thru the pointer - if make_instr is true. - If make_instr is false returned_count - should NOT be used by the caller (returned_count - is set to 0 thru the pointer by this routine...) - If unsuccessful, returns DW_DLV_ERROR - and sets returned_error to the error code - - It does not do a whole lot of input validation being a private - function. Please make sure inputs are valid. - - (1) If make_instr is true, it makes a list of pointers to - Dwarf_Frame_Op structures containing the frame instructions - executed. A pointer to this list is returned in ret_frame_instr. - Make_instr is true only when a list of frame instructions is to be - returned. In this case since we are not interested in the contents - of the table, the input Cie can be NULL. This is the only case - where the inpute Cie can be NULL. - - (2) If search_pc is true, frame instructions are executed till - either a location is reached that is greater than the search_pc_val - provided, or all instructions are executed. At this point the - last row of the table generated is returned in a structure. - A pointer to this structure is supplied in table. - - (3) This function is also used to create the initial table row - defined by a Cie. In this case, the Dwarf_Cie pointer cie, is - NULL. For an FDE, however, cie points to the associated Cie. - - make_instr - make list of frame instr? 0/1 - ret_frame_instr - Ptr to list of ptrs to frame instrs - search_pc - Search for a pc value? 0/1 - search_pc_val - Search for this pc value - initial_loc - Initial code location value. - start_instr_ptr - Ptr to start of frame instrs. - final_instr_ptr - Ptr just past frame instrs. - table - Ptr to struct with last row. - cie - Ptr to Cie used by the Fde. - Different cies may have distinct address-sizes, so the cie - is used, not de_pointer_size. - -*/ - -int -_dwarf_exec_frame_instr(Dwarf_Bool make_instr, - Dwarf_Frame_Op ** ret_frame_instr, - Dwarf_Bool search_pc, - Dwarf_Addr search_pc_val, - Dwarf_Addr initial_loc, - Dwarf_Small * start_instr_ptr, - Dwarf_Small * final_instr_ptr, - Dwarf_Frame table, - Dwarf_Cie cie, - Dwarf_Debug dbg, - Dwarf_Half reg_num_of_cfa, - Dwarf_Sword * returned_count, - int *returned_error) -{ -#define ERROR_IF_REG_NUM_TOO_HIGH(macreg,machigh_reg) \ - do { \ - if ((macreg) >= (machigh_reg) || (macreg) < 0) { \ - SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); \ - } \ - } /*CONSTCOND */ while(0) -#define SIMPLE_ERROR_RETURN(code) \ - free(localregtab); \ - *returned_error = code; \ - return DW_DLV_ERROR - - /* Sweeps the frame instructions. */ - Dwarf_Small *instr_ptr; - - /* Register numbers not limited to just 255, thus not using - Dwarf_Small. */ - typedef int reg_num_type; - - Dwarf_Unsigned factored_N_value; - Dwarf_Signed signed_factored_N_value; - Dwarf_Addr current_loc = initial_loc; /* code location/ - pc-value - corresponding to the - frame instructions. - Starts at zero when - the caller has no - value to pass in. */ - - /* Must be min de_pointer_size bytes and must be at least sizeof - Dwarf_ufixed */ - Dwarf_Unsigned adv_loc = 0; - - int reg_count = dbg->de_frame_reg_rules_entry_count; - struct Dwarf_Reg_Rule_s *localregtab = calloc(reg_count, - sizeof(struct - Dwarf_Reg_Rule_s)); - - struct Dwarf_Reg_Rule_s cfa_reg; - - - /* This is used to end executing frame instructions. */ - /* Becomes true when search_pc is true and current_loc */ - /* is greater than search_pc_val. */ - Dwarf_Bool search_over = false; - - /* Used by the DW_FRAME_advance_loc instr */ - /* to hold the increment in pc value. */ - Dwarf_Addr adv_pc; - - /* Contains the length in bytes of */ - /* an leb128 encoded number. */ - Dwarf_Word leb128_length; - - Dwarf_Half address_size = (cie)? cie->ci_address_size: - dbg->de_pointer_size; - - /* Counts the number of frame instructions executed. */ - Dwarf_Word instr_count = 0; - - /* - These contain the current fields of the current frame - instruction. */ - Dwarf_Small fp_base_op = 0; - Dwarf_Small fp_extended_op; - reg_num_type fp_register; - - /* The value in fp_offset may be signed, though we call it - unsigned. This works ok for 2-s complement arithmetic. */ - Dwarf_Unsigned fp_offset; - Dwarf_Off fp_instr_offset; - - /* - Stack_table points to the row (Dwarf_Frame ie) being pushed or - popped by a remember or restore instruction. Top_stack points to - the top of the stack of rows. */ - Dwarf_Frame stack_table = NULL; - Dwarf_Frame top_stack = NULL; - - /* - These are used only when make_instr is true. Curr_instr is a - pointer to the current frame instruction executed. - Curr_instr_ptr, head_instr_list, and curr_instr_list are used to - form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr is - used to deallocate the structs used to form the chain. - Head_instr_block points to a contiguous list of pointers to the - Dwarf_Frame_Op structs executed. */ - Dwarf_Frame_Op *curr_instr; - Dwarf_Chain curr_instr_item, dealloc_instr_item; - Dwarf_Chain head_instr_chain = NULL; - Dwarf_Chain tail_instr_chain = NULL; - Dwarf_Frame_Op *head_instr_block; - - /* - These are the alignment_factors taken from the Cie provided. - When no input Cie is provided they are set to 1, because only - factored offsets are required. */ - Dwarf_Sword code_alignment_factor = 1; - Dwarf_Sword data_alignment_factor = 1; - - /* - This flag indicates when an actual alignment factor is needed. - So if a frame instruction that computes an offset using an - alignment factor is encountered when this flag is set, an error - is returned because the Cie did not have a valid augmentation. */ - Dwarf_Bool need_augmentation = false; - - Dwarf_Word i; - - /* Initialize first row from associated Cie. Using temp regs - explicity */ - - if (localregtab == 0) { - SIMPLE_ERROR_RETURN(DW_DLE_ALLOC_FAIL); - } - { - struct Dwarf_Reg_Rule_s *t1reg = localregtab; - struct Dwarf_Reg_Rule_s *t1end = t1reg + reg_count; - - if (cie != NULL && cie->ci_initial_table != NULL) { - struct Dwarf_Reg_Rule_s *t2reg = - cie->ci_initial_table->fr_reg; - - if (reg_count != cie->ci_initial_table->fr_reg_count) { - /* Should never happen, it makes no sense to have the - table sizes change. There is no real allowance for - the set of registers to change dynamically in a - single Dwarf_Debug (except the size can be set near - initial Dwarf_Debug creation time). */ - SIMPLE_ERROR_RETURN - (DW_DLE_FRAME_REGISTER_COUNT_MISMATCH); - } - - for (; t1reg < t1end; t1reg++, t2reg++) { - *t1reg = *t2reg; - } - cfa_reg = cie->ci_initial_table->fr_cfa_rule; - } else { - _dwarf_init_regrule_table(t1reg, - reg_count, - dbg->de_frame_rule_initial_value); - _dwarf_init_regrule_table(&cfa_reg, 1, - dbg->de_frame_rule_initial_value); - } - } - - /* - The idea here is that the code_alignment_factor and - data_alignment_factor which are needed for certain instructions - are valid only when the Cie has a proper augmentation string. So - if the augmentation is not right, only Frame instruction can be - read. */ - if (cie != NULL && cie->ci_augmentation != NULL) { - code_alignment_factor = cie->ci_code_alignment_factor; - data_alignment_factor = cie->ci_data_alignment_factor; - } else { - need_augmentation = !make_instr; - } - - instr_ptr = start_instr_ptr; - while ((instr_ptr < final_instr_ptr) && (!search_over)) { - Dwarf_Small instr = 0; - Dwarf_Small opcode = 0; - reg_num_type reg_no = 0; - - fp_instr_offset = instr_ptr - start_instr_ptr; - instr = *(Dwarf_Small *) instr_ptr; - instr_ptr += sizeof(Dwarf_Small); - - fp_base_op = (instr & 0xc0) >> 6; - if ((instr & 0xc0) == 0x00) { - opcode = instr; /* is really extended op */ - fp_extended_op = (instr & (~(0xc0))) & 0xff; - } else { - opcode = instr & 0xc0; /* is base op */ - fp_extended_op = 0; - } - - fp_register = 0; - fp_offset = 0; - switch (opcode) { - case DW_CFA_advance_loc: - { - /* base op */ - fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_pc = adv_pc * code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_pc > search_pc_val); - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_pc; - } - break; - } - - case DW_CFA_offset: - { /* base op */ - reg_no = - (reg_num_type) (instr & DW_FRAME_INSTR_OFFSET_MASK); - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr = instr_ptr + leb128_length; - - fp_register = reg_no; - fp_offset = factored_N_value; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_offset_or_block_len = - factored_N_value * data_alignment_factor; - - break; - } - - case DW_CFA_restore: - { /* base op */ - reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK); - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - fp_register = reg_no; - - if (cie != NULL && cie->ci_initial_table != NULL) - localregtab[reg_no] = - cie->ci_initial_table->fr_reg[reg_no]; - else if (!make_instr) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_MAKE_INSTR_NO_INIT); - } - - break; - } - case DW_CFA_set_loc: - { - Dwarf_Addr new_loc = 0; - - READ_UNALIGNED(dbg, new_loc, Dwarf_Addr, - instr_ptr, address_size); - instr_ptr += address_size; - if (new_loc != 0 && current_loc != 0) { - /* Pre-relocation or before current_loc is set the - test comparing new_loc and current_loc makes no - sense. Testing for non-zero (above) is a way - (fallible) to check that current_loc, new_loc - are already relocated. */ - if (new_loc <= current_loc) { - /* Within a frame, address must increase. - Seemingly it has not. Seems to be an error. */ - - SIMPLE_ERROR_RETURN - (DW_DLE_DF_NEW_LOC_LESS_OLD_LOC); - } - } - - search_over = search_pc && (new_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = new_loc; - } - fp_offset = new_loc; - break; - } - - case DW_CFA_advance_loc1: - { - fp_offset = adv_loc = *(Dwarf_Small *) instr_ptr; - instr_ptr += sizeof(Dwarf_Small); - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_loc *= code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_loc; - } - break; - } - - case DW_CFA_advance_loc2: - { - READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, - instr_ptr, sizeof(Dwarf_Half)); - instr_ptr += sizeof(Dwarf_Half); - fp_offset = adv_loc; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_loc *= code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_loc; - } - break; - } - - case DW_CFA_advance_loc4: - { - READ_UNALIGNED(dbg, adv_loc, Dwarf_Unsigned, - instr_ptr, sizeof(Dwarf_ufixed)); - instr_ptr += sizeof(Dwarf_ufixed); - fp_offset = adv_loc; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - adv_loc *= code_alignment_factor; - - search_over = search_pc && - (current_loc + adv_loc > search_pc_val); - - /* If gone past pc needed, retain old pc. */ - if (!search_over) { - current_loc = current_loc + adv_loc; - } - break; - } - - case DW_CFA_offset_extended: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);; - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_offset_or_block_len = factored_N_value * - data_alignment_factor; - - fp_register = reg_no; - fp_offset = factored_N_value; - break; - } - - case DW_CFA_restore_extended: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - if (cie != NULL && cie->ci_initial_table != NULL) { - localregtab[reg_no] = cie->ci_initial_table->fr_reg[reg_no]; - } else { - if (!make_instr) { - SIMPLE_ERROR_RETURN - (DW_DLE_DF_MAKE_INSTR_NO_INIT); - } - } - - fp_register = reg_no; - break; - } - - case DW_CFA_undefined: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - localregtab[reg_no].ru_is_off = 0; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = - dbg->de_frame_undefined_value_number; - localregtab[reg_no].ru_offset_or_block_len = 0; - - fp_register = reg_no; - break; - } - - case DW_CFA_same_value: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - localregtab[reg_no].ru_is_off = 0; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = - dbg->de_frame_same_value_number; - localregtab[reg_no].ru_offset_or_block_len = 0; - fp_register = reg_no; - break; - } - - case DW_CFA_register: - { - Dwarf_Unsigned lreg; - reg_num_type reg_noA = 0; - reg_num_type reg_noB = 0; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_noA = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_noA, reg_count); - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_noB = (reg_num_type) lreg; - - if (reg_noB > reg_count) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_REG_NUM_TOO_HIGH); - } - - - localregtab[reg_noA].ru_is_off = 0; - localregtab[reg_noA].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_noA].ru_register = reg_noB; - localregtab[reg_noA].ru_offset_or_block_len = 0; - - fp_register = reg_noA; - fp_offset = reg_noB; - break; - } - - case DW_CFA_remember_state: - { - stack_table = (Dwarf_Frame) - _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); - if (stack_table == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - for (i = 0; i < reg_count; i++) - stack_table->fr_reg[i] = localregtab[i]; - stack_table->fr_cfa_rule = cfa_reg; - - if (top_stack != NULL) - stack_table->fr_next = top_stack; - top_stack = stack_table; - - break; - } - - case DW_CFA_restore_state: - { - if (top_stack == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_POP_EMPTY_STACK); - } - stack_table = top_stack; - top_stack = stack_table->fr_next; - - for (i = 0; i < reg_count; i++) - localregtab[i] = stack_table->fr_reg[i]; - cfa_reg = stack_table->fr_cfa_rule; - - dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); - break; - } - - case DW_CFA_def_cfa: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_register = reg_no; - cfa_reg.ru_offset_or_block_len = factored_N_value; - - fp_register = reg_no; - fp_offset = factored_N_value; - break; - } - - case DW_CFA_def_cfa_register: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - cfa_reg.ru_register = reg_no; - /* Do NOT set ru_offset_or_block_len or ru_is_off here. - See dwarf2/3 spec. */ - fp_register = reg_no; - break; - } - - case DW_CFA_def_cfa_offset: - { - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_offset_or_block_len = factored_N_value; - - fp_offset = factored_N_value; - break; - } - case DW_CFA_nop: - { - break; - } - /* DWARF3 ops begin here. */ - case DW_CFA_def_cfa_expression: - { - /* A single DW_FORM_block representing a dwarf - expression. The form block establishes the way to - compute the CFA. */ - Dwarf_Unsigned block_len = 0; - - DECODE_LEB128_UWORD(instr_ptr, block_len); - cfa_reg.ru_is_off = 0; /* arbitrary */ - cfa_reg.ru_value_type = DW_EXPR_EXPRESSION; - cfa_reg.ru_offset_or_block_len = block_len; - cfa_reg.ru_block = instr_ptr; - fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; - instr_ptr += block_len; - } - break; - case DW_CFA_expression: - { - /* An unsigned leb128 value is the first operand (a - register number). The second operand is single - DW_FORM_block representing a dwarf expression. The - evaluator pushes the CFA on the evaluation stack - then evaluates the expression to compute the value - of the register contents. */ - Dwarf_Unsigned lreg = 0; - Dwarf_Unsigned block_len = 0; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - DECODE_LEB128_UWORD(instr_ptr, block_len); - localregtab[lreg].ru_is_off = 0; /* arbitrary */ - localregtab[lreg].ru_value_type = DW_EXPR_EXPRESSION; - localregtab[lreg].ru_offset_or_block_len = block_len; - localregtab[lreg].ru_block = instr_ptr; - fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; - fp_register = reg_no; - instr_ptr += block_len; - } - break; - case DW_CFA_offset_extended_sf: - { - /* The first operand is an unsigned leb128 register - number. The second is a signed factored offset. - Identical to DW_CFA_offset_extended except the - secondoperand is signed */ - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_register = reg_no; - fp_offset = signed_factored_N_value; - } - break; - case DW_CFA_def_cfa_sf: - { - /* The first operand is an unsigned leb128 register - number. The second is a signed leb128 factored - offset. Identical to DW_CFA_def_cfa except that the - second operand is signed and factored. */ - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_register = reg_no; - cfa_reg.ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_register = reg_no; - fp_offset = signed_factored_N_value; - } - break; - case DW_CFA_def_cfa_offset_sf: - { - /* The operand is a signed leb128 operand representing - a factored offset. Identical to - DW_CFA_def_cfa_offset excep the operand is signed - and factored. */ - - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - cfa_reg.ru_is_off = 1; - cfa_reg.ru_value_type = DW_EXPR_OFFSET; - cfa_reg.ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_offset = signed_factored_N_value; - } - break; - case DW_CFA_val_offset: - { - /* The first operand is an unsigned leb128 register - number. The second is a factored unsigned offset. - Makes the register be a val_offset(N) rule with N = - factored_offset*data_alignment_factor. */ - - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - - factored_N_value = - _dwarf_decode_u_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_register = reg_num_of_cfa; - localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; - localregtab[reg_no].ru_offset_or_block_len = - factored_N_value * data_alignment_factor; - - fp_offset = factored_N_value; - break; - } - case DW_CFA_val_offset_sf: - { - /* The first operand is an unsigned leb128 register - number. The second is a factored signed offset. - Makes the register be a val_offset(N) rule with N = - factored_offset*data_alignment_factor. */ - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - signed_factored_N_value = - _dwarf_decode_s_leb128(instr_ptr, &leb128_length); - instr_ptr += leb128_length; - - if (need_augmentation) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_NO_CIE_AUGMENTATION); - } - /* Do set ru_is_off here, as here factored_N_value - counts. */ - localregtab[reg_no].ru_is_off = 1; - localregtab[reg_no].ru_value_type = DW_EXPR_VAL_OFFSET; - localregtab[reg_no].ru_offset_or_block_len = - signed_factored_N_value * data_alignment_factor; - - fp_offset = signed_factored_N_value; - - } - break; - case DW_CFA_val_expression: - { - /* The first operand is an unsigned leb128 register - number. The second is a DW_FORM_block representing a - DWARF expression. The rule for the register number - becomes a val_expression(E) rule. */ - Dwarf_Unsigned lreg = 0; - Dwarf_Unsigned block_len = 0; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count); - DECODE_LEB128_UWORD(instr_ptr, block_len); - localregtab[lreg].ru_is_off = 0; /* arbitrary */ - localregtab[lreg].ru_value_type = DW_EXPR_VAL_EXPRESSION; - localregtab[lreg].ru_offset_or_block_len = block_len; - localregtab[lreg].ru_block = instr_ptr; - fp_offset = (Dwarf_Unsigned)(uintptr_t)instr_ptr; - - instr_ptr += block_len; - fp_register = reg_no; - - } - break; - - /* END DWARF3 new ops. */ - - -#ifdef DW_CFA_GNU_window_save - case DW_CFA_GNU_window_save: - { - /* no information: this just tells unwinder to restore - the window registers from the previous frame's - window save area */ - break; - } -#endif -#ifdef DW_CFA_GNU_args_size - /* single uleb128 is the current arg area size in bytes. No - register exists yet to save this in */ - case DW_CFA_GNU_args_size: - { - Dwarf_Unsigned lreg; - - DECODE_LEB128_UWORD(instr_ptr, lreg); - reg_no = (reg_num_type) lreg; - - break; - } -#endif - default: - /* ERROR, we have an opcode we know nothing about. Memory - leak here, but an error like this is not supposed to - happen so we ignore the leak. These used to be ignored, - now we notice and report. */ - SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); - - } - - if (make_instr) { - instr_count++; - - curr_instr = (Dwarf_Frame_Op *) - _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1); - if (curr_instr == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - curr_instr->fp_base_op = fp_base_op; - curr_instr->fp_extended_op = fp_extended_op; - curr_instr->fp_register = fp_register; - curr_instr->fp_offset = fp_offset; - curr_instr->fp_instr_offset = fp_instr_offset; - - curr_instr_item = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_instr_item == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - curr_instr_item->ch_item = curr_instr; - if (head_instr_chain == NULL) - head_instr_chain = tail_instr_chain = curr_instr_item; - else { - tail_instr_chain->ch_next = curr_instr_item; - tail_instr_chain = curr_instr_item; - } - } - } - - /* - If frame instruction decoding was right we would stop exactly at - final_instr_ptr. */ - if (instr_ptr > final_instr_ptr) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_FRAME_DECODING_ERROR); - } - - /* Fill in the actual output table, the space the caller passed in. */ - if (table != NULL) { - - struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg; - struct Dwarf_Reg_Rule_s *t3reg = localregtab; - struct Dwarf_Reg_Rule_s *t3end = t3reg + reg_count; - - table->fr_loc = current_loc; - for (; t3reg < t3end; t3reg++, t2reg++) { - *t2reg = *t3reg; - } - - /* CONSTCOND */ - /* Do not update the main table with the cfa_reg. - Just leave cfa_reg as cfa_reg. */ - table->fr_cfa_rule = cfa_reg; - } - - /* Dealloc anything remaining on stack. */ - for (; top_stack != NULL;) { - stack_table = top_stack; - top_stack = top_stack->fr_next; - dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME); - } - - if (make_instr) { - /* Allocate list of pointers to Dwarf_Frame_Op's. */ - head_instr_block = (Dwarf_Frame_Op *) - _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count); - if (head_instr_block == NULL) { - SIMPLE_ERROR_RETURN(DW_DLE_DF_ALLOC_FAIL); - } - - /* - Store pointers to Dwarf_Frame_Op's in this list and - deallocate the structs that chain the Dwarf_Frame_Op's. */ - curr_instr_item = head_instr_chain; - for (i = 0; i < instr_count; i++) { - *(head_instr_block + i) = - *(Dwarf_Frame_Op *) curr_instr_item->ch_item; - dealloc_instr_item = curr_instr_item; - curr_instr_item = curr_instr_item->ch_next; - dwarf_dealloc(dbg, dealloc_instr_item->ch_item, - DW_DLA_FRAME_OP); - dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN); - } - *ret_frame_instr = head_instr_block; - - *returned_count = (Dwarf_Sword) instr_count; - } else { - *returned_count = 0; - } - free(localregtab); - return DW_DLV_OK; -#undef ERROR_IF_REG_NUM_TOO_HIGH -#undef SIMPLE_ERROR_RETURN -} - -/* Depending on version, either read the return address register - as a ubyte or as an leb number. - The form of this value changed for DWARF3. -*/ -Dwarf_Unsigned -_dwarf_get_return_address_reg(Dwarf_Small * frame_ptr, - int version, unsigned long *size) -{ - Dwarf_Unsigned uvalue = 0; - Dwarf_Word leb128_length = 0; - - if (version == 1) { - *size = 1; - uvalue = *(unsigned char *) frame_ptr; - return uvalue; - } - uvalue = _dwarf_decode_u_leb128(frame_ptr, &leb128_length); - *size = leb128_length; - return uvalue; -} - - -/* Trivial consumer function. -*/ -int -dwarf_get_cie_of_fde(Dwarf_Fde fde, - Dwarf_Cie * cie_returned, Dwarf_Error * error) -{ - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - *cie_returned = fde->fd_cie; - return DW_DLV_OK; - -} - -int dwarf_get_cie_index( - Dwarf_Cie cie, - Dwarf_Signed* index, - Dwarf_Error* error ) -{ - if( cie == NULL ) - { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - - *index = cie->ci_index; - return (DW_DLV_OK); -} - - -/* - For g++ .eh_frame fde and cie. - the cie id is different as the - definition of the cie_id in an fde - is the distance back from the address of the - value to the cie. - Or 0 if this is a true cie. - Non standard dwarf, designed this way to be - convenient at run time for an allocated - (mapped into memory as part of the running image) section. -*/ -int -dwarf_get_fde_list_eh(Dwarf_Debug dbg, - Dwarf_Cie ** cie_data, - Dwarf_Signed * cie_element_count, - Dwarf_Fde ** fde_data, - Dwarf_Signed * fde_element_count, - Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_frame_eh_gnu,error); - if (res != DW_DLV_OK) { - return res; - } - - res = _dwarf_get_fde_list_internal(dbg, - cie_data, - cie_element_count, - fde_data, - fde_element_count, - dbg->de_debug_frame_eh_gnu.dss_data, - dbg->de_debug_frame_eh_gnu.dss_index, - dbg->de_debug_frame_eh_gnu.dss_size, - /* cie_id_value */ 0, - /* use_gnu_cie_calc= */ 1, - error); - return res; -} - - - -/* - For standard dwarf .debug_frame - cie_id is -1 in a cie, and - is the section offset in the .debug_frame section - of the cie otherwise. Standard dwarf -*/ -int -dwarf_get_fde_list(Dwarf_Debug dbg, - Dwarf_Cie ** cie_data, - Dwarf_Signed * cie_element_count, - Dwarf_Fde ** fde_data, - Dwarf_Signed * fde_element_count, - Dwarf_Error * error) -{ - int res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error); - if (res != DW_DLV_OK) { - return res; - } - - res = _dwarf_get_fde_list_internal(dbg, cie_data, - cie_element_count, - fde_data, - fde_element_count, - dbg->de_debug_frame.dss_data, - dbg->de_debug_frame.dss_index, - dbg->de_debug_frame.dss_size, - DW_CIE_ID, - /* use_gnu_cie_calc= */ 0, - error); - - return res; -} - - -/* - Only works on dwarf sections, not eh_frame - Given a Dwarf_Die, see if it has a - DW_AT_MIPS_fde attribute and if so use that - to get an fde offset. - Then create a Dwarf_Fde to return thru the ret_fde pointer. - Also creates a cie (pointed at from the Dwarf_Fde). -*/ -int -dwarf_get_fde_for_die(Dwarf_Debug dbg, - Dwarf_Die die, - Dwarf_Fde * ret_fde, Dwarf_Error * error) -{ - Dwarf_Attribute attr; - Dwarf_Unsigned fde_offset = 0; - Dwarf_Signed signdval = 0; - Dwarf_Fde new_fde = 0; - unsigned char *fde_ptr = 0; - unsigned char *cie_ptr = 0; - Dwarf_Unsigned cie_id = 0; - - /* Fields for the current Cie being read. */ - int res = 0; - int resattr = 0; - int sdatares = 0; - - struct cie_fde_prefix_s prefix; - struct cie_fde_prefix_s prefix_c; - - if (die == NULL) { - _dwarf_error(NULL, error, DW_DLE_DIE_NULL); - return (DW_DLV_ERROR); - } - - resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error); - if (resattr != DW_DLV_OK) { - return resattr; - } - - /* why is this formsdata? FIX */ - sdatares = dwarf_formsdata(attr, &signdval, error); - if (sdatares != DW_DLV_OK) { - return sdatares; - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error); - if (res != DW_DLV_OK) { - return res; - } - - fde_offset = signdval; - fde_ptr = (dbg->de_debug_frame.dss_data + fde_offset); - - - /* First read in the 'common prefix' to figure out what * we are to - do with this entry. */ - memset(&prefix_c, 0, sizeof(prefix_c)); - memset(&prefix, 0, sizeof(prefix)); - res = dwarf_read_cie_fde_prefix(dbg, fde_ptr, - dbg->de_debug_frame.dss_data, - dbg->de_debug_frame.dss_index, - dbg->de_debug_frame.dss_size, - &prefix, - error); - if (res == DW_DLV_ERROR) { - return res; - } - if (res == DW_DLV_NO_ENTRY) - return res; - fde_ptr = prefix.cf_addr_after_prefix; - cie_id = prefix.cf_cie_id; - /* Pass NULL, not section pointer, for 3rd argument. - de_debug_frame.dss_data has no eh_frame relevance. */ - res = dwarf_create_fde_from_after_start(dbg, &prefix, - (Dwarf_Small *) NULL, - fde_ptr, - /* use_gnu_cie_calc= */ 0, - /* Dwarf_Cie = */ 0, - &new_fde, error); - if (res == DW_DLV_ERROR) { - return res; - } else if (res == DW_DLV_NO_ENTRY) { - return res; - } - /* DW_DLV_OK */ - - /* now read the cie corresponding to the fde */ - cie_ptr = new_fde->fd_section_ptr + cie_id; - res = dwarf_read_cie_fde_prefix(dbg, cie_ptr, - dbg->de_debug_frame.dss_data, - dbg->de_debug_frame.dss_index, - dbg->de_debug_frame.dss_size, - &prefix_c, error); - if (res == DW_DLV_ERROR) { - return res; - } - if (res == DW_DLV_NO_ENTRY) - return res; - - cie_ptr = prefix_c.cf_addr_after_prefix; - cie_id = prefix_c.cf_cie_id; - - if (cie_id == DW_CIE_ID) { - int res2 = 0; - Dwarf_Cie new_cie = 0; - - /* Pass NULL, not section pointer, for 3rd argument. - de_debug_frame.dss_data has no eh_frame relevance. */ - res2 = dwarf_create_cie_from_after_start(dbg, - &prefix_c, - (Dwarf_Small *) NULL, - cie_ptr, - /* cie_count= */ 0, - /* use_gnu_cie_calc= */ - 0, &new_cie, error); - if (res2 == DW_DLV_ERROR) { - dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); - return res; - } else if (res2 == DW_DLV_NO_ENTRY) { - dwarf_dealloc(dbg, new_fde, DW_DLA_FDE); - return res; - } - new_fde->fd_cie = new_cie; - } else { - _dwarf_error(dbg, error, DW_DLE_NO_CIE_FOR_FDE); - return (DW_DLV_ERROR); - } - - *ret_fde = new_fde; - return DW_DLV_OK; -} - -/* A dwarf consumer operation, see the consumer library documentation. -*/ -int -dwarf_get_fde_range(Dwarf_Fde fde, - Dwarf_Addr * low_pc, - Dwarf_Unsigned * func_length, - Dwarf_Ptr * fde_bytes, - Dwarf_Unsigned * fde_byte_length, - Dwarf_Off * cie_offset, - Dwarf_Signed * cie_index, - Dwarf_Off * fde_offset, Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - dbg = fde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - - - /* We have always already done the section load here, so no need to - load the section. We did the section load in order to create the - Dwarf_Fde pointer passed in here. */ - - - if (low_pc != NULL) - *low_pc = fde->fd_initial_location; - if (func_length != NULL) - *func_length = fde->fd_address_range; - if (fde_bytes != NULL) - *fde_bytes = fde->fd_fde_start; - if (fde_byte_length != NULL) - *fde_byte_length = fde->fd_length; - if (cie_offset != NULL) - *cie_offset = fde->fd_cie_offset; - if (cie_index != NULL) - *cie_index = fde->fd_cie_index; - if (fde_offset != NULL) - *fde_offset = fde->fd_fde_start - fde->fd_section_ptr; - - return DW_DLV_OK; -} - -/* IRIX specific function. The exception tables - have C++ destructor information and are - at present undocumented. */ -int -dwarf_get_fde_exception_info(Dwarf_Fde fde, - Dwarf_Signed * - offset_into_exception_tables, - Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - dbg = fde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - *offset_into_exception_tables = - fde->fd_offset_into_exception_tables; - return DW_DLV_OK; -} - - -/* A consumer code function. - Given a CIE pointer, return the normal CIE data thru - pointers. - Special augmentation data is not returned here. -*/ -int -dwarf_get_cie_info(Dwarf_Cie cie, - Dwarf_Unsigned * bytes_in_cie, - Dwarf_Small * ptr_to_version, - char **augmenter, - Dwarf_Unsigned * code_alignment_factor, - Dwarf_Signed * data_alignment_factor, - Dwarf_Half * return_address_register, - Dwarf_Ptr * initial_instructions, - Dwarf_Unsigned * initial_instructions_length, - Dwarf_Error * error) -{ - Dwarf_Debug dbg; - - if (cie == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - - dbg = cie->ci_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_DBG_NULL); - return (DW_DLV_ERROR); - } - - if (ptr_to_version != NULL) - *ptr_to_version = cie->ci_cie_version_number; - if (augmenter != NULL) - *augmenter = cie->ci_augmentation; - if (code_alignment_factor != NULL) - *code_alignment_factor = cie->ci_code_alignment_factor; - if (data_alignment_factor != NULL) - *data_alignment_factor = cie->ci_data_alignment_factor; - if (return_address_register != NULL) - *return_address_register = cie->ci_return_address_register; - if (initial_instructions != NULL) - *initial_instructions = cie->ci_cie_instr_start; - if (initial_instructions_length != NULL) { - *initial_instructions_length = cie->ci_length + - cie->ci_length_size + - cie->ci_extension_size - - (cie->ci_cie_instr_start - cie->ci_cie_start); - - } - *bytes_in_cie = (cie->ci_length); - return (DW_DLV_OK); -} - -/* Return the register rules for all registers at a given pc. -*/ -static int -_dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde, - Dwarf_Addr pc_requested, - Dwarf_Frame table, - Dwarf_Half cfa_reg_col_num, - Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Cie cie = 0; - int dw_err = 0; - Dwarf_Sword icount = 0; - int res = 0; - - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - dbg = fde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - - if (pc_requested < fde->fd_initial_location || - pc_requested >= - fde->fd_initial_location + fde->fd_address_range) { - _dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE); - return (DW_DLV_ERROR); - } - - cie = fde->fd_cie; - if (cie->ci_initial_table == NULL) { - cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1); - - if (cie->ci_initial_table == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - _dwarf_init_regrule_table(cie->ci_initial_table->fr_reg, - dbg->de_frame_reg_rules_entry_count, - dbg->de_frame_rule_initial_value); - _dwarf_init_regrule_table(&cie->ci_initial_table->fr_cfa_rule, - 1, dbg->de_frame_rule_initial_value); - res = _dwarf_exec_frame_instr( /* make_instr= */ false, - /* ret_frame_instr= */ NULL, - /* search_pc */ false, - /* search_pc_val */ 0, - /* location */ 0, - cie->ci_cie_instr_start, - cie->ci_cie_instr_start + (cie->ci_length + - cie->ci_length_size + - cie->ci_extension_size - - (cie->ci_cie_instr_start - - cie->ci_cie_start)), - cie->ci_initial_table, cie, dbg, - cfa_reg_col_num, &icount, - &dw_err); - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, error, dw_err); - return (res); - } else if (res == DW_DLV_NO_ENTRY) { - return res; - } - } - - { - Dwarf_Small *instr_end = fde->fd_fde_instr_start + - fde->fd_length + - fde->fd_length_size + - fde->fd_extension_size - (fde->fd_fde_instr_start - - fde->fd_fde_start); - - res = _dwarf_exec_frame_instr( /* make_instr= */ false, - /* ret_frame_instr= */ NULL, - /* search_pc */ true, - /* search_pc_val */ pc_requested, - fde->fd_initial_location, - fde->fd_fde_instr_start, - instr_end, - table, - cie, dbg, - cfa_reg_col_num, &icount, - &dw_err); - } - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, error, dw_err); - return (res); - } else if (res == DW_DLV_NO_ENTRY) { - return res; - } - - return DW_DLV_OK; -} - -/* A consumer call for efficiently getting the register info - for all registers in one call. - - The output table rules array is size DW_REG_TABLE_SIZE. - The frame info rules array in fde_table is of size - DW_REG_TABLE_SIZE too. - - This interface really only works well with MIPS/IRIX - where DW_FRAME_CFA_COL is zero (in that case it's safe). - - It is also restricted to the case where - DW_REG_TABLE_SIZE == DW_FRAME_LAST_REG_NUM == - dbg->de_frame_reg_rules_entry_count (true for MIPS/IRIX). - If this condition is not met calling this routine can result in - incorrect output or in memory corruption. - - It is much better to use dwarf_get_fde_info_for_all_regs3() - instead of this interface. -*/ -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) -{ - - /* Table size: DW_REG_TABLE_SIZE */ - struct Dwarf_Frame_s fde_table; - Dwarf_Sword i = 0; - struct Dwarf_Reg_Rule_s *rule = NULL; - struct Dwarf_Regtable_Entry_s *out_rule = NULL; - int res = 0; - Dwarf_Debug dbg = 0; - - /* For this interface the size is fixed at compile time. */ - int output_table_real_data_size = DW_REG_TABLE_SIZE; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - - res = dwarf_initialize_fde_table(dbg, &fde_table, - output_table_real_data_size, - error); - if (res != DW_DLV_OK) - return res; - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, - &fde_table, dbg->de_frame_cfa_col_number, error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - out_rule = ®_table->rules[0]; - rule = &fde_table.fr_reg[0]; - for (i = 0; i < output_table_real_data_size; - i++, ++out_rule, ++rule) { - out_rule->dw_offset_relevant = rule->ru_is_off; - out_rule->dw_value_type = rule->ru_value_type; - out_rule->dw_regnum = rule->ru_register; - out_rule->dw_offset = rule->ru_offset_or_block_len; - } - for (; i < DW_REG_TABLE_SIZE; ++i, ++out_rule) { - out_rule->dw_offset_relevant = 0; - out_rule->dw_value_type = DW_EXPR_OFFSET; - out_rule->dw_regnum = dbg->de_frame_undefined_value_number; - out_rule->dw_offset = 0; - } - - /* The test is just in case it's not inside the table. For non-MIPS - it could be outside the table and that is just fine, it was - really a mistake to put it in the table in 1993. */ - /* CONSTCOND */ - if (dbg->de_frame_cfa_col_number < DW_REG_TABLE_SIZE) { - out_rule = ®_table->rules[dbg->de_frame_cfa_col_number]; - out_rule->dw_offset_relevant = fde_table.fr_cfa_rule.ru_is_off; - out_rule->dw_value_type = fde_table.fr_cfa_rule.ru_value_type; - out_rule->dw_regnum = fde_table.fr_cfa_rule.ru_register; - out_rule->dw_offset = - fde_table.fr_cfa_rule.ru_offset_or_block_len; - } - - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - -/* A consumer call for efficiently getting the register info - for all registers in one call. - - The output table rules array is size output_table_real_data_size. - (normally DW_REG_TABLE_SIZE). - The frame info rules array in fde_table is normally of size - DW_FRAME_LAST_REG_NUM. -*/ -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) -{ - - struct Dwarf_Frame_s fde_table; - Dwarf_Sword i = 0; - int res = 0; - struct Dwarf_Reg_Rule_s *rule = NULL; - struct Dwarf_Regtable_Entry3_s *out_rule = NULL; - Dwarf_Debug dbg = 0; - int output_table_real_data_size = reg_table->rt3_reg_table_size; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - - output_table_real_data_size = - MIN(output_table_real_data_size, - dbg->de_frame_reg_rules_entry_count); - - res = dwarf_initialize_fde_table(dbg, &fde_table, - output_table_real_data_size, - error); - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, - &fde_table, - dbg->de_frame_cfa_col_number, - error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - out_rule = ®_table->rt3_rules[0]; - rule = &fde_table.fr_reg[0]; - for (i = 0; i < output_table_real_data_size; - i++, ++out_rule, ++rule) { - out_rule->dw_offset_relevant = rule->ru_is_off; - out_rule->dw_value_type = rule->ru_value_type; - out_rule->dw_regnum = rule->ru_register; - out_rule->dw_offset_or_block_len = rule->ru_offset_or_block_len; - out_rule->dw_block_ptr = rule->ru_block; - } - for (; i < reg_table->rt3_reg_table_size; i++, ++out_rule) { - out_rule->dw_offset_relevant = 0; - out_rule->dw_value_type = DW_EXPR_OFFSET; - out_rule->dw_regnum = dbg->de_frame_undefined_value_number; - out_rule->dw_offset_or_block_len = 0; - out_rule->dw_block_ptr = 0; - } - reg_table->rt3_cfa_rule.dw_offset_relevant = - fde_table.fr_cfa_rule.ru_is_off; - reg_table->rt3_cfa_rule.dw_value_type = - fde_table.fr_cfa_rule.ru_value_type; - reg_table->rt3_cfa_rule.dw_regnum = - fde_table.fr_cfa_rule.ru_register; - reg_table->rt3_cfa_rule.dw_offset_or_block_len = - fde_table.fr_cfa_rule.ru_offset_or_block_len; - reg_table->rt3_cfa_rule.dw_block_ptr = - fde_table.fr_cfa_rule.ru_block; - - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - - -/* Gets the register info for a single register at a given PC value - for the FDE specified. - - This is the old MIPS interface and should no longer be used. - Use dwarf_get_fde_info_for_reg3() instead. -*/ -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) -{ - struct Dwarf_Frame_s fde_table; - int res = DW_DLV_ERROR; - Dwarf_Debug dbg = 0; - int output_table_real_data_size = 0; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - output_table_real_data_size = dbg->de_frame_reg_rules_entry_count; - - res = dwarf_initialize_fde_table(dbg, &fde_table, - output_table_real_data_size, - error); - if (res != DW_DLV_OK) - return res; - - if (table_column >= output_table_real_data_size) { - dwarf_free_fde_table(&fde_table); - _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); - return (DW_DLV_ERROR); - } - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = - _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, - dbg->de_frame_cfa_col_number, error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - if (fde_table.fr_reg[table_column].ru_value_type != DW_EXPR_OFFSET) { - /* The problem here is that this interface cannot deal with - other sorts of (newer) dwarf frame values. Code must - use dwarf_get_fde_info_for_reg3() to get these - values correctly. We error rather than return - misleading incomplete data. */ - dwarf_free_fde_table(&fde_table); - _dwarf_error(NULL, error, - DW_DLE_FRAME_REGISTER_UNREPRESENTABLE); - return (DW_DLV_ERROR); - } - if(table_column == dbg->de_frame_cfa_col_number) { - if (register_num != NULL) - *register_num = fde_table.fr_cfa_rule.ru_register; - if (offset != NULL) - *offset = fde_table.fr_cfa_rule.ru_offset_or_block_len; - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - *offset_relevant = fde_table.fr_cfa_rule.ru_is_off; - - } else { - if (register_num != NULL) - *register_num = fde_table.fr_reg[table_column].ru_register; - if (offset != NULL) - *offset = fde_table.fr_reg[table_column].ru_offset_or_block_len; - if (row_pc != NULL) - *row_pc = fde_table.fr_loc; - - *offset_relevant = fde_table.fr_reg[table_column].ru_is_off; - } - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - -/* In this interface, table_column of DW_FRAME_CFA_COL - is not meaningful. - Use dwarf_get_fde_info_for_cfa_reg3() to get the CFA. - Call dwarf_set_frame_cfa_value() to set the correct column - after calling dwarf_init() - (DW_FRAME_CFA_COL3 is a sensible column to use). -*/ -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_out, - Dwarf_Error * error) -{ - struct Dwarf_Frame_s fde_table; - int res = DW_DLV_ERROR; - - Dwarf_Debug dbg = 0; - int table_real_data_size = 0; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - table_real_data_size = dbg->de_frame_reg_rules_entry_count; - res = dwarf_initialize_fde_table(dbg, &fde_table, - table_real_data_size, error); - if (res != DW_DLV_OK) - return res; - if (table_column >= table_real_data_size) { - dwarf_free_fde_table(&fde_table); - _dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD); - return (DW_DLV_ERROR); - } - - /* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks - */ - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, - dbg->de_frame_cfa_col_number, - error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - if (register_num != NULL) - *register_num = fde_table.fr_reg[table_column].ru_register; - if (offset_or_block_len != NULL) - *offset_or_block_len = - fde_table.fr_reg[table_column].ru_offset_or_block_len; - if (row_pc_out != NULL) - *row_pc_out = fde_table.fr_loc; - if (block_ptr) - *block_ptr = fde_table.fr_reg[table_column].ru_block; - - /* Without value_type the data cannot be understood, so we insist - on it being present, we don't test it. */ - *value_type = fde_table.fr_reg[table_column].ru_value_type; - *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off); - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; - -} - -/* For latest DWARF, this is the preferred interface. - It more portably deals with the CFA by not - making the CFA a column number, which means - DW_FRAME_CFA_COL3 becomes, like DW_CFA_SAME_VALUE, - a special value, not something one uses as an index. - - Call dwarf_set_frame_cfa_value() to set the correct column - after calling dwarf_init() - (DW_FRAME_CFA_COL3 is a sensible column to use, and - is the default unless '--enable-oldframecol' - is used to configure libdwarf). */ -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_out, - Dwarf_Error * error) -{ - struct Dwarf_Frame_s fde_table; - int res = DW_DLV_ERROR; - Dwarf_Debug dbg = 0; - - int table_real_data_size = 0; - - FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg); - - table_real_data_size = dbg->de_frame_reg_rules_entry_count; - res = dwarf_initialize_fde_table(dbg, &fde_table, - table_real_data_size, error); - if (res != DW_DLV_OK) - return res; - res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested, &fde_table, - dbg->de_frame_cfa_col_number,error); - if (res != DW_DLV_OK) { - dwarf_free_fde_table(&fde_table); - return res; - } - - if (register_num != NULL) - *register_num = fde_table.fr_cfa_rule.ru_register; - if (offset_or_block_len != NULL) - *offset_or_block_len = - fde_table.fr_cfa_rule.ru_offset_or_block_len; - if (row_pc_out != NULL) - *row_pc_out = fde_table.fr_loc; - if (block_ptr) - *block_ptr = fde_table.fr_cfa_rule.ru_block; - - /* Without value_type the data cannot be understood, so we insist - on it being present, we don't test it. */ - *value_type = fde_table.fr_cfa_rule.ru_value_type; - *offset_relevant = fde_table.fr_cfa_rule.ru_is_off; - dwarf_free_fde_table(&fde_table); - return DW_DLV_OK; -} - - - -/* - Return pointer to the instructions in the dwarf - fde. -*/ -int -dwarf_get_fde_instr_bytes(Dwarf_Fde inFde, Dwarf_Ptr * outinstraddr, - Dwarf_Unsigned * outaddrlen, - Dwarf_Error * error) -{ - Dwarf_Unsigned len = 0; - unsigned char *instrs = 0; - Dwarf_Debug dbg = 0; - - if (inFde == NULL) { - _dwarf_error(dbg, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - - dbg = inFde->fd_dbg; - if (dbg == NULL) { - _dwarf_error(dbg, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - - instrs = inFde->fd_fde_instr_start; - - len = (inFde->fd_fde_start + inFde->fd_length + - inFde->fd_length_size + inFde->fd_extension_size) - instrs; - - *outinstraddr = instrs; - *outaddrlen = len; - return DW_DLV_OK; -} - -/* Allows getting an fde from its table via an index. - With more error checking than simply indexing oneself. -*/ -int -dwarf_get_fde_n(Dwarf_Fde * fde_data, - Dwarf_Unsigned fde_index, - Dwarf_Fde * returned_fde, Dwarf_Error * error) -{ - Dwarf_Debug dbg = 0; - Dwarf_Signed fdecount = 0; - - if (fde_data == NULL) { - _dwarf_error(dbg, error, DW_DLE_FDE_PTR_NULL); - return (DW_DLV_ERROR); - } - - FDE_NULL_CHECKS_AND_SET_DBG(*fde_data, dbg); - /* Assumes fde_data table has at least one entry. */ - fdecount = fde_data[0]->fd_is_eh? - dbg->de_fde_count_eh:dbg->de_fde_count; - if (fde_index >= fdecount) { - return (DW_DLV_NO_ENTRY); - } - *returned_fde = (*(fde_data + fde_index)); - return DW_DLV_OK; -} - - -/* - Lopc and hipc are extensions to the interface to - return the range of addresses that are described - by the returned fde. -*/ -int -dwarf_get_fde_at_pc(Dwarf_Fde * fde_data, - Dwarf_Addr pc_of_interest, - Dwarf_Fde * returned_fde, - Dwarf_Addr * lopc, - Dwarf_Addr * hipc, Dwarf_Error * error) -{ - Dwarf_Debug dbg = NULL; - Dwarf_Fde fde = NULL; - Dwarf_Fde entryfde = NULL; - Dwarf_Signed fdecount = 0; - - if (fde_data == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL); - return (DW_DLV_ERROR); - } - - /* Assumes fde_data table has at least one entry. */ - entryfde = *fde_data; - FDE_NULL_CHECKS_AND_SET_DBG(entryfde, dbg); - - if (dbg == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL); - return (DW_DLV_ERROR); - } - fdecount = entryfde->fd_is_eh? - dbg->de_fde_count_eh:dbg->de_fde_count; - { - /* The fde's are sorted by their addresses. Binary search to - find correct fde. */ - Dwarf_Signed low = 0; - Dwarf_Signed high = fdecount - 1L; - Dwarf_Signed middle = 0; - Dwarf_Fde cur_fde; - - while (low <= high) { - middle = (low + high) / 2; - cur_fde = fde_data[middle]; - if (pc_of_interest < cur_fde->fd_initial_location) { - high = middle - 1; - } else if (pc_of_interest >= - (cur_fde->fd_initial_location + - cur_fde->fd_address_range)) { - low = middle + 1; - } else { - fde = fde_data[middle]; - break; - } - } - } - - if (fde) { - if (lopc != NULL) - *lopc = fde->fd_initial_location; - if (hipc != NULL) - *hipc = - fde->fd_initial_location + fde->fd_address_range - 1; - *returned_fde = fde; - return (DW_DLV_OK); - } - - return (DW_DLV_NO_ENTRY); -} - - -/* Expands a single frame instruction block - from a specific cie - into a n array of Dwarf_Frame_Op-s. - This depends on having the cfa column set sensibly. - - Call dwarf_set_frame_cfa_value() to set the correct column - after calling dwarf_init() unless you are using - the old MIPS frame interfaces (in which case the default - will be ok). (DW_FRAME_CFA_COL3 is a sensible column to use ). -*/ -int -dwarf_expand_frame_instructions(Dwarf_Cie cie, - Dwarf_Ptr instruction, - Dwarf_Unsigned i_length, - Dwarf_Frame_Op ** returned_op_list, - Dwarf_Signed * returned_op_count, - Dwarf_Error * error) -{ - Dwarf_Sword instr_count; - int res = DW_DLV_ERROR; - int dw_err; - Dwarf_Debug dbg = 0; - - if (cie == 0) { - _dwarf_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_ERROR); - } - dbg = cie->ci_dbg; - - if (returned_op_list == 0 || returned_op_count == 0) { - _dwarf_error(dbg, error, DW_DLE_RET_OP_LIST_NULL); - return (DW_DLV_ERROR); - } - - /* The cast to Dwarf_Ptr may get a compiler warning, but it is safe - as it is just an i_length offset from 'instruction' itself. A - caller has made a big mistake if the result is not a valid - pointer. */ - res = _dwarf_exec_frame_instr( /* make_instr= */ true, - returned_op_list, - /* search_pc */ false, - /* search_pc_val */ 0, - /* location */ 0, - instruction, - (Dwarf_Ptr)((char *)instruction + i_length), - /* Dwarf_Frame */ NULL, - cie, - dbg, - dbg->de_frame_cfa_col_number, &instr_count, - &dw_err); - if (res != DW_DLV_OK) { - if (res == DW_DLV_ERROR) { - _dwarf_error(dbg, error, dw_err); - } - return (res); - } - - *returned_op_count = instr_count; - return DW_DLV_OK; -} - - -/* Used by dwarfdump -v to print offsets, for debugging - dwarf info. - The dwarf_ version is preferred over the obsolete _dwarf version. - _dwarf version kept for compatibility. -*/ -/* ARGSUSED 4 */ -int -_dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, - Dwarf_Off * fde_off, Dwarf_Off * cie_off, - Dwarf_Error * err) -{ - return dwarf_fde_section_offset(dbg,in_fde,fde_off, - cie_off,err); -} -/* ARGSUSED 4 */ -int -dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde, - Dwarf_Off * fde_off, Dwarf_Off * cie_off, - Dwarf_Error * err) -{ - char *start = 0; - char *loc = 0; - - - - start = (char *) in_fde->fd_section_ptr; - loc = (char *) in_fde->fd_fde_start; - - *fde_off = (loc - start); - *cie_off = in_fde->fd_cie_offset; - return DW_DLV_OK; -} - -/* Used by dwarfdump -v to print offsets, for debugging - dwarf info. - The dwarf_ version is preferred over the obsolete _dwarf version. - _dwarf version kept for compatibility. -*/ -/* ARGSUSED 4 */ -int -_dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, - Dwarf_Off * cie_off, Dwarf_Error * err) -{ - return dwarf_cie_section_offset(dbg,in_cie,cie_off,err); -} -/* ARGSUSED 4 */ -int -dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie, - Dwarf_Off * cie_off, Dwarf_Error * err) -{ - char *start = 0; - char *loc = 0; - - start = (char *) in_cie->ci_section_ptr; - loc = (char *) in_cie->ci_cie_start; - - *cie_off = (loc - start); - return DW_DLV_OK; -} - -/* Returns a pointer to target-specific augmentation data thru augdata - and returns the length of the data thru augdata_len. - - It's up to the consumer code to know how to interpret the bytes - of target-specific data (endian issues apply too, these - are just raw bytes pointed to). - See Linux Standard Base Core Specification version 3.0 for - the details on .eh_frame info. - - Returns DW_DLV_ERROR if fde is NULL or some other serious - error. - Returns DW_DLV_NO_ENTRY if there is no target-specific - augmentation data. - - The bytes pointed to are in the Dwarf_Cie, and as long as that - is valid the bytes are there. No 'dealloc' call is needed - for the bytes. -*/ -int -dwarf_get_cie_augmentation_data(Dwarf_Cie cie, - Dwarf_Small ** augdata, - Dwarf_Unsigned * augdata_len, - Dwarf_Error * error) -{ - if (cie == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - if (cie->ci_gnu_eh_augmentation_len == 0) { - return DW_DLV_NO_ENTRY; - } - *augdata = (Dwarf_Small *) (cie->ci_gnu_eh_augmentation_bytes); - *augdata_len = cie->ci_gnu_eh_augmentation_len; - return DW_DLV_OK; -} - - -/* Returns a pointer to target-specific augmentation data thru augdata - and returns the length of the data thru augdata_len. - - It's up to the consumer code to know how to interpret the bytes - of target-specific data (endian issues apply too, these - are just raw bytes pointed to). - See Linux Standard Base Core Specification version 3.0 for - the details on .eh_frame info. - - Returns DW_DLV_ERROR if fde is NULL or some other serious - error. - Returns DW_DLV_NO_ENTRY if there is no target-specific - augmentation data. - - The bytes pointed to are in the Dwarf_Fde, and as long as that - is valid the bytes are there. No 'dealloc' call is needed - for the bytes. - -*/ -int -dwarf_get_fde_augmentation_data(Dwarf_Fde fde, - Dwarf_Small * *augdata, - Dwarf_Unsigned * augdata_len, - Dwarf_Error * error) -{ - Dwarf_Cie cie = 0; - - if (fde == NULL) { - _dwarf_error(NULL, error, DW_DLE_FDE_NULL); - return (DW_DLV_ERROR); - } - cie = fde->fd_cie; - if (cie == NULL) { - _dwarf_error(NULL, error, DW_DLE_CIE_NULL); - return (DW_DLV_ERROR); - } - if (cie->ci_gnu_eh_augmentation_len == 0) { - return DW_DLV_NO_ENTRY; - } - *augdata = (Dwarf_Small *) fde->fd_gnu_eh_augmentation_bytes; - *augdata_len = fde->fd_gnu_eh_augmentation_len; - return DW_DLV_OK; -} - - -/* Initialize with same_value , a value which makes sense - for IRIX/MIPS. - The correct value to use is ABI dependent. - For register-windows machines most - or all registers should get DW_FRAME_UNDEFINED_VAL as the - correct initial value. - Some think DW_FRAME_UNDEFINED_VAL is always the - right value. - - For some ABIs a setting which varies by register - would be more appropriate. - - FIXME. */ - -static void -_dwarf_init_regrule_table(struct Dwarf_Reg_Rule_s *t1reg, - int last_reg_num, int initial_value) -{ - struct Dwarf_Reg_Rule_s *t1end = t1reg + last_reg_num; - - for (; t1reg < t1end; t1reg++) { - t1reg->ru_is_off = 0; - t1reg->ru_value_type = DW_EXPR_OFFSET; - t1reg->ru_register = initial_value; - t1reg->ru_offset_or_block_len = 0; - t1reg->ru_block = 0; - } -} - -#if 0 -/* Used solely for debugging libdwarf. */ -static void -dump_frame_rule(char *msg, struct Dwarf_Reg_Rule_s *reg_rule) -{ - printf - ("%s type %s (" DW_PR_DUx "), is_off " - DW_PR_DUu " reg " DW_PR_DUu " offset " DW_PR_DUx " blockp " - DW_PR_DUx "\n", - msg, - (reg_rule->ru_value_type == DW_EXPR_OFFSET) ? - "DW_EXPR_OFFSET" : - (reg_rule->ru_value_type == DW_EXPR_VAL_OFFSET) ? - "DW_EXPR_VAL_OFFSET" : - (reg_rule->ru_value_type == DW_EXPR_VAL_EXPRESSION) ? - "DW_EXPR_VAL_EXPRESSION" : - (reg_rule->ru_value_type == DW_EXPR_EXPRESSION) ? - "DW_EXPR_EXPRESSION" : "Unknown", - (Dwarf_Unsigned) reg_rule->ru_value_type, - (Dwarf_Unsigned) reg_rule->ru_is_off, - (Dwarf_Unsigned) reg_rule->ru_register, - (Dwarf_Unsigned) reg_rule->ru_offset_or_block_len, - (Dwarf_Unsigned) reg_rule->ru_block); - return; -} -#endif - -/* This allows consumers to set the 'initial value' so that - an ISA/ABI specific default can be used, dynamically, - at run time. Useful for dwarfdump and non-MIPS architectures.. - The value defaults to one of - DW_FRAME_SAME_VALUE or DW_FRAME_UNKNOWN_VALUE - but dwarfdump can dump multiple ISA/ABI objects so - we may want to get this set to what the ABI says is correct. - - Returns the value that was present before we changed it here. -*/ -Dwarf_Half -dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_rule_initial_value; - dbg->de_frame_rule_initial_value = value; - return orig; -} - -/* The following spelling for backwards compatibility. */ -Dwarf_Half -dwarf_set_frame_rule_inital_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - return dwarf_set_frame_rule_initial_value(dbg,value); -} - -/* This allows consumers to set the array size of the reg rules - table so that - an ISA/ABI specific value can be used, dynamically, - at run time. Useful for non-MIPS archtectures. - The value defaults to DW_FRAME_LAST_REG_NUM. - but dwarfdump can dump multiple ISA/ABI objects so - consumers want to get this set to what the ABI says is correct. - - Returns the value that was present before we changed it here. -*/ - -Dwarf_Half -dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_reg_rules_entry_count; - dbg->de_frame_reg_rules_entry_count = value; - return orig; -} -/* This allows consumers to set the CFA register value - * so that an ISA/ABI specific value can be used, dynamically, - * at run time. Useful for non-MIPS archtectures. - * The value defaults to DW_FRAME_CFA_COL3 and should be - * higher than any real register in the ABI. - * Dwarfdump can dump multiple ISA/ABI objects so - * consumers want to get this set to what the ABI says is correct. - - * Returns the value that was present before we changed it here. - * */ - -Dwarf_Half -dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_cfa_col_number; - dbg->de_frame_cfa_col_number = value; - return orig; -} -/* Similar to above, but for the other crucial fields for frames. */ -Dwarf_Half -dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_same_value_number; - dbg->de_frame_same_value_number = value; - return orig; -} -Dwarf_Half -dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value) -{ - Dwarf_Half orig = dbg->de_frame_same_value_number; - dbg->de_frame_undefined_value_number = value; - return orig; -} - - - - - -static int -dwarf_initialize_fde_table(Dwarf_Debug dbg, - struct Dwarf_Frame_s *fde_table, - unsigned table_real_data_size, - Dwarf_Error * error) -{ - unsigned entry_size = sizeof(struct Dwarf_Frame_s); - - fde_table->fr_loc = 0; - fde_table->fr_reg_count = table_real_data_size; - fde_table->fr_next = 0; - - fde_table->fr_reg = (struct Dwarf_Reg_Rule_s *) - calloc(entry_size, table_real_data_size); - if (fde_table->fr_reg == 0) { - _dwarf_error(dbg, error, DW_DLE_DF_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - return DW_DLV_OK; - -} -static void -dwarf_free_fde_table(struct Dwarf_Frame_s *fde_table) -{ - free(fde_table->fr_reg); - fde_table->fr_reg_count = 0; - fde_table->fr_reg = 0; -} - - -/* Return DW_DLV_OK if we succeed. else return DW_DLV_ERROR. -*/ -int -_dwarf_frame_constructor(Dwarf_Debug dbg, void *frame) -{ - struct Dwarf_Frame_s *fp = frame; - - if (!dbg) { - return DW_DLV_ERROR; - } - - fp->fr_reg = calloc(dbg->de_frame_reg_rules_entry_count, - sizeof(struct Dwarf_Reg_Rule_s)); - if (!fp->fr_reg) { - return DW_DLV_ERROR; - } - fp->fr_reg_count = dbg->de_frame_reg_rules_entry_count; - return DW_DLV_OK; -} - -void -_dwarf_frame_destructor(void *frame) -{ - struct Dwarf_Frame_s *fp = frame; - - if (fp->fr_reg) { - free(fp->fr_reg); - } - fp->fr_reg = 0; - fp->fr_reg_count = 0; -} |