diff options
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/dwarf_frame.h')
| -rw-r--r-- | usr/src/tools/ctf/dwarf/common/dwarf_frame.h | 274 |
1 files changed, 244 insertions, 30 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_frame.h b/usr/src/tools/ctf/dwarf/common/dwarf_frame.h index 5338ce678c..ceb686335b 100644 --- a/usr/src/tools/ctf/dwarf/common/dwarf_frame.h +++ b/usr/src/tools/ctf/dwarf/common/dwarf_frame.h @@ -1,6 +1,6 @@ /* - Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. + Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. 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 @@ -17,12 +17,12 @@ 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., 59 Temple Place - Suite 330, Boston MA 02111-1307, + 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., 1600 Amphitheatre Pky, + Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, Mountain View, CA 94043, or: http://www.sgi.com @@ -62,25 +62,38 @@ * is an LEB128 data item that denotes the size (in bytes) of * the augmented fields (not including the size of * "length_of_augmented_fields" itself). - * This implementation of libdwarf will assume that the length of - * augmented fields follow the augmenter string when the augmentation - * starts with the string "z". It will skip over any augmented fields - * that it does not understand to the start of initial instructions - * (in case of CIE) or the instruction table (in case of FDE). - * - * Future sgi versions of cie or fde should use "z1", "z2" as the - * augmenter strings and it should guarantee that all the above fields - * are laid out in the same fashion. Older libraries will continue to be able - * to read all the old data, skipping over newly added data items. + + * Handling of cie augmentation strings is necessarly a heuristic. + * See dwarf_frame.c for the currently known augmentation strings. + + + ---START SGI-ONLY COMMENT: + * SGI-IRIX versions of cie or fde were intended to use "z1", "z2" as the + * augmenter strings if required for new augmentation. + * However, that never happened (as of March 2005). * - * The fde's augmented by the string "z" have a new field (signed constant, 4 - byte field) - * called offset_into_exception_tables, following the length_of_augmented field. - * This field contains an offset into the "_MIPS_eh_region", which describes - * the exception handling tables. + * The fde's augmented by the string "z" have a new field + * (signed constant, 4 byte field) + * called offset_into_exception_tables, following the + * length_of_augmented field. This field contains an offset + * into the "_MIPS_eh_region", which describes + * the IRIX CC exception handling tables. + ---END SGI-ONLY COMMENT + + + * GNU .eh_frame has an augmentation string of z[RLP]* (gcc 3.4) + * The similarity to IRIX 'z' (and proposed but never + * implemented IRIX z1, z2 etc) was confusing things. + * If the section is .eh_frame then 'z' means GNU exception + * information 'Augmentation Data' not IRIX 'z'. + * See The Linux Standard Base Core Specification version 3.0 */ -#define DW_DEBUG_FRAME_VERSION 1 +#define DW_DEBUG_FRAME_VERSION 1 /* DWARF2 */ +#define DW_DEBUG_FRAME_VERSION3 3 /* DWARF3 */ +#define DW_DEBUG_FRAME_VERSION4 4 /* DWARF4 */ +/* The following is SGI/IRIX specific, and probably no longer + in use anywhere. */ #define DW_DEBUG_FRAME_AUGMENTER_STRING "mti v1" /* The value of the offset field for Cie's. */ @@ -101,8 +114,9 @@ struct Dwarf_Reg_Rule_s { /* Is a flag indicating whether the rule includes the offset - field, ie whether the ru_offset field is valid or not. It is - important, since reg+offset (offset of 0) is different from + field, ie whether the ru_offset field is valid or not. + Applies only if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. + It is important, since reg+offset (offset of 0) is different from just 'register' since the former means 'read memory at address given by the sum of register contents plus offset to get the value'. whereas the latter means 'the value is in the register'. @@ -113,13 +127,27 @@ struct Dwarf_Reg_Rule_s { DW_FRAME_CFA_COL. */ - Dwarf_Sbyte ru_is_off; + Dwarf_Sbyte ru_is_off; + + /* DW_EXPR_OFFSET (0, DWARF2) + DW_EXPR_VAL_OFFSET 1 (dwarf2/3) + DW_EXPR_EXPRESSION 2 (dwarf2/3) + DW_EXPR_VAL_EXPRESSION 3 (dwarf2/3) + See dwarf_frame.h. */ + Dwarf_Sbyte ru_value_type; /* Register involved in this rule. */ Dwarf_Half ru_register; - /* Offset to add to register, if indicated by ru_is_offset. */ - Dwarf_Addr ru_offset; + /* Offset to add to register, if indicated by ru_is_offset + and if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET. + If DW_EXPR_EXPRESSION or DW_EXPR_VAL_EXPRESSION + this is DW_FORM_block block-length, not offset. */ + Dwarf_Unsigned ru_offset_or_block_len; + + /* For DW_EXPR_EXPRESSION DW_EXPR_VAL_EXPRESSION these is set, + else 0. */ + Dwarf_Small *ru_block; }; typedef struct Dwarf_Frame_s *Dwarf_Frame; @@ -128,6 +156,9 @@ typedef struct Dwarf_Frame_s *Dwarf_Frame; This structure represents a row of the frame table. Fr_loc is the pc value for this row, and Fr_reg contains the rule for each column. + + Entry DW_FRAME_CFA_COL of fr_reg was the tradional MIPS + way of setting CFA. cfa_rule is the new one. */ struct Dwarf_Frame_s { @@ -135,7 +166,12 @@ struct Dwarf_Frame_s { Dwarf_Addr fr_loc; /* Rules for all the registers in this row. */ - struct Dwarf_Reg_Rule_s fr_reg[DW_FRAME_LAST_REG_NUM]; + struct Dwarf_Reg_Rule_s fr_cfa_rule; + + /* fr_reg_count is the the number of + entries of the fr_reg array. */ + unsigned long fr_reg_count; + struct Dwarf_Reg_Rule_s *fr_reg; Dwarf_Frame fr_next; }; @@ -148,6 +184,39 @@ struct Dwarf_Frame_Op_List_s { Dwarf_Frame_Op_List fl_next; }; +/* See dwarf_frame.c for the heuristics used to set the + Dwarf_Cie ci_augmentation_type. + + This succinctly helps interpret the size and meaning of .debug_frame + and (for gcc) .eh_frame. + + In the case of gcc .eh_frame (gcc 3.3, 3.4) + z may be followed by one or more of + L R P. + +*/ +enum Dwarf_augmentation_type { + aug_empty_string, /* Default empty augmentation string. */ + aug_irix_exception_table, /* IRIX plain "z", + for exception handling, IRIX CC compiler. + Proposed z1 z2 ... never implemented. */ + aug_gcc_eh_z, /* gcc z augmentation, (including + L R P variations). gcc 3.3 3.4 exception + handling in eh_frame. */ + aug_irix_mti_v1, /* IRIX "mti v1" augmentation string. Probably + never in any released SGI-IRIX compiler. */ + aug_eh, /* For gcc .eh_frame, "eh" is the string., + gcc 1,2, egcs. Older values. */ + aug_armcc, /* "armcc+" meaning the cfa calculation + is corrected to be standard (output by + Arm C RVCT 3.0 SP1 and later). See + http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html + for details. */ + aug_unknown, /* Unknown augmentation, we cannot do much. */ + aug_past_last +}; + + /* This structure contains all the pertinent info for a Cie. Most of the fields are taken straight from the definition of a Cie. @@ -158,7 +227,7 @@ struct Dwarf_Frame_Op_List_s { row generated by the instructions for this Cie. */ struct Dwarf_Cie_s { - Dwarf_Word ci_length; + Dwarf_Unsigned ci_length; char *ci_augmentation; Dwarf_Small ci_code_alignment_factor; Dwarf_Sbyte ci_data_alignment_factor; @@ -170,6 +239,38 @@ struct Dwarf_Cie_s { Dwarf_Cie ci_next; Dwarf_Small ci_length_size; Dwarf_Small ci_extension_size; + Dwarf_Half ci_cie_version_number; + enum Dwarf_augmentation_type ci_augmentation_type; + + /* The following 2 for GNU .eh_frame exception handling + Augmentation Data. Set if ci_augmentation_type + is aug_gcc_eh_z. Zero if unused. */ + Dwarf_Unsigned ci_gnu_eh_augmentation_len; + Dwarf_Ptr ci_gnu_eh_augmentation_bytes; + + /* These are extracted from the gnu eh_frame + augmentation if the + augmentation begins with 'z'. See Linux LSB documents. + Otherwize these are zero. */ + unsigned char ci_gnu_personality_handler_encoding; + unsigned char ci_gnu_lsda_encoding; + unsigned char ci_gnu_fde_begin_encoding; + + /* If 'P' augmentation present, is handler addr. Else + is zero. */ + Dwarf_Addr ci_gnu_personality_handler_addr; + + + /* In creating list of cie's (which will become an array) + record the position so fde can get it on fde creation. */ + Dwarf_Unsigned ci_index; + Dwarf_Small * ci_section_ptr; + /* DWARF4 adds address size and segment size to the CIE: the .debug_info + section may not always be present to allow libdwarf to + find address_size from the compilation-unit. */ + Dwarf_Half ci_address_size; + Dwarf_Half ci_segment_size; + }; /* @@ -183,9 +284,9 @@ struct Dwarf_Cie_s { points to the associated Dwarf_Debug structure. */ struct Dwarf_Fde_s { - Dwarf_Word fd_length; + Dwarf_Unsigned fd_length; Dwarf_Addr fd_cie_offset; - Dwarf_Sword fd_cie_index; + Dwarf_Unsigned fd_cie_index; Dwarf_Cie fd_cie; Dwarf_Addr fd_initial_location; Dwarf_Small *fd_initial_loc_pos; @@ -193,10 +294,31 @@ struct Dwarf_Fde_s { Dwarf_Small *fd_fde_start; Dwarf_Small *fd_fde_instr_start; Dwarf_Debug fd_dbg; + + /* fd_offset_into_exception_tables is SGI/IRIX exception table + offset. Unused and zero if not IRIX .debug_frame. */ Dwarf_Signed fd_offset_into_exception_tables; + Dwarf_Fde fd_next; Dwarf_Small fd_length_size; Dwarf_Small fd_extension_size; + /* So we know from an fde which 'count' of fde-s in + Dwarf_Debug applies: eh or standard. */ + Dwarf_Small fd_is_eh; + /* The following 2 for GNU .eh_frame exception handling + Augmentation Data. Set if CIE ci_augmentation_type + is aug_gcc_eh_z. Zero if unused. */ + Dwarf_Unsigned fd_gnu_eh_augmentation_len; + Dwarf_Ptr fd_gnu_eh_augmentation_bytes; + Dwarf_Addr fd_gnu_eh_lsda; /* If 'L' augmentation letter + present: is address of the + Language Specific Data Area (LSDA). If not 'L" is zero. */ + + /* The following 3 are about the Elf section the FDEs come from. */ + Dwarf_Small * fd_section_ptr; + Dwarf_Unsigned fd_section_length; + Dwarf_Unsigned fd_section_index; + }; @@ -205,3 +327,95 @@ int Dwarf_Off ** offsetlist, Dwarf_Signed * returncount, Dwarf_Error * err); + +int +_dwarf_get_fde_list_internal(Dwarf_Debug dbg, + Dwarf_Cie ** cie_data, + Dwarf_Signed * cie_element_count, + Dwarf_Fde ** fde_data, + Dwarf_Signed * fde_element_count, + Dwarf_Small * section_ptr, + Dwarf_Unsigned section_index, + Dwarf_Unsigned section_length, + Dwarf_Unsigned cie_id_value, + int use_gnu_cie_calc, /* If non-zero, + this is gcc eh_frame. */ + Dwarf_Error * error); + +enum Dwarf_augmentation_type +_dwarf_get_augmentation_type(Dwarf_Debug dbg, + Dwarf_Small *augmentation_string, + int is_gcc_eh_frame); + +Dwarf_Unsigned _dwarf_get_return_address_reg(Dwarf_Small *frame_ptr, + int version, + unsigned long *size); + +/* Temporary recording of crucial cie/fde prefix data. + * Vastly simplifies some argument lists. + */ +struct cie_fde_prefix_s { + /* cf_start_addr is a pointer to the first byte of this fde/cie + we are reading now. */ + Dwarf_Small * cf_start_addr; + Dwarf_Small * cf_addr_after_prefix; + Dwarf_Unsigned cf_length; + int cf_local_length_size; + int cf_local_extension_size; + Dwarf_Unsigned cf_cie_id; + Dwarf_Small * cf_cie_id_addr; /* used for eh_frame calculations. */ + + /* Simplifies passing around these values to create fde having + these here. */ + /* cf_section_ptr is a pointer to the first byte + of the object section the prefix is read from. */ + Dwarf_Small * cf_section_ptr; + Dwarf_Unsigned cf_section_index; + Dwarf_Unsigned cf_section_length; +}; + +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); + + +int dwarf_read_cie_fde_prefix(Dwarf_Debug dbg, + Dwarf_Small *frame_ptr_in, + Dwarf_Small *section_ptr_in, + Dwarf_Unsigned section_index_in, + Dwarf_Unsigned section_length_in, + struct cie_fde_prefix_s *prefix_out, + Dwarf_Error *error); + +int dwarf_create_fde_from_after_start(Dwarf_Debug dbg, + struct cie_fde_prefix_s * prefix, + Dwarf_Small *section_pointer, + Dwarf_Small *frame_ptr, + int use_gnu_cie_calc, + Dwarf_Cie cie_ptr_in, + Dwarf_Fde *fde_ptr_out, + Dwarf_Error *error); + +int dwarf_create_cie_from_after_start(Dwarf_Debug dbg, + struct cie_fde_prefix_s *prefix, + Dwarf_Small* section_pointer, + Dwarf_Small* frame_ptr, + Dwarf_Unsigned cie_count, + int use_gnu_cie_calc, + Dwarf_Cie *cie_ptr_out, + Dwarf_Error *error); + + +int _dwarf_frame_constructor(Dwarf_Debug dbg,void * ); +void _dwarf_frame_destructor (void *); |
