1*7304104dSAndroid Build Coastguard Worker /* Internal definitions for libdw CFI interpreter. 2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2009-2010, 2013, 2015 Red Hat, Inc. 3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils. 4*7304104dSAndroid Build Coastguard Worker 5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify 6*7304104dSAndroid Build Coastguard Worker it under the terms of either 7*7304104dSAndroid Build Coastguard Worker 8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free 9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at 10*7304104dSAndroid Build Coastguard Worker your option) any later version 11*7304104dSAndroid Build Coastguard Worker 12*7304104dSAndroid Build Coastguard Worker or 13*7304104dSAndroid Build Coastguard Worker 14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free 15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at 16*7304104dSAndroid Build Coastguard Worker your option) any later version 17*7304104dSAndroid Build Coastguard Worker 18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here. 19*7304104dSAndroid Build Coastguard Worker 20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but 21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of 22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23*7304104dSAndroid Build Coastguard Worker General Public License for more details. 24*7304104dSAndroid Build Coastguard Worker 25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and 26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If 27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */ 28*7304104dSAndroid Build Coastguard Worker 29*7304104dSAndroid Build Coastguard Worker #ifndef _UNWINDP_H 30*7304104dSAndroid Build Coastguard Worker #define _UNWINDP_H 1 31*7304104dSAndroid Build Coastguard Worker 32*7304104dSAndroid Build Coastguard Worker #include "libdwP.h" 33*7304104dSAndroid Build Coastguard Worker #include "libelfP.h" 34*7304104dSAndroid Build Coastguard Worker struct ebl; 35*7304104dSAndroid Build Coastguard Worker 36*7304104dSAndroid Build Coastguard Worker /* Cached CIE representation. */ 37*7304104dSAndroid Build Coastguard Worker struct dwarf_cie 38*7304104dSAndroid Build Coastguard Worker { 39*7304104dSAndroid Build Coastguard Worker Dwarf_Off offset; /* Our position, as seen in FDEs' CIE_pointer. */ 40*7304104dSAndroid Build Coastguard Worker 41*7304104dSAndroid Build Coastguard Worker Dwarf_Word code_alignment_factor; 42*7304104dSAndroid Build Coastguard Worker Dwarf_Sword data_alignment_factor; 43*7304104dSAndroid Build Coastguard Worker Dwarf_Word return_address_register; 44*7304104dSAndroid Build Coastguard Worker 45*7304104dSAndroid Build Coastguard Worker size_t fde_augmentation_data_size; 46*7304104dSAndroid Build Coastguard Worker 47*7304104dSAndroid Build Coastguard Worker // play out to initial state 48*7304104dSAndroid Build Coastguard Worker const uint8_t *initial_instructions; 49*7304104dSAndroid Build Coastguard Worker const uint8_t *initial_instructions_end; 50*7304104dSAndroid Build Coastguard Worker 51*7304104dSAndroid Build Coastguard Worker const Dwarf_Frame *initial_state; 52*7304104dSAndroid Build Coastguard Worker 53*7304104dSAndroid Build Coastguard Worker uint8_t fde_encoding; /* DW_EH_PE_* for addresses in FDEs. */ 54*7304104dSAndroid Build Coastguard Worker uint8_t lsda_encoding; /* DW_EH_PE_* for LSDA in FDE augmentation. */ 55*7304104dSAndroid Build Coastguard Worker 56*7304104dSAndroid Build Coastguard Worker bool sized_augmentation_data; /* Saw 'z': FDEs have self-sized data. */ 57*7304104dSAndroid Build Coastguard Worker bool signal_frame; /* Saw 'S': FDE is for a signal frame. */ 58*7304104dSAndroid Build Coastguard Worker }; 59*7304104dSAndroid Build Coastguard Worker 60*7304104dSAndroid Build Coastguard Worker /* Cached FDE representation. */ 61*7304104dSAndroid Build Coastguard Worker struct dwarf_fde 62*7304104dSAndroid Build Coastguard Worker { 63*7304104dSAndroid Build Coastguard Worker struct dwarf_cie *cie; 64*7304104dSAndroid Build Coastguard Worker 65*7304104dSAndroid Build Coastguard Worker /* This FDE describes PC values in [start, end). */ 66*7304104dSAndroid Build Coastguard Worker Dwarf_Addr start; 67*7304104dSAndroid Build Coastguard Worker Dwarf_Addr end; 68*7304104dSAndroid Build Coastguard Worker 69*7304104dSAndroid Build Coastguard Worker const uint8_t *instructions; 70*7304104dSAndroid Build Coastguard Worker const uint8_t *instructions_end; 71*7304104dSAndroid Build Coastguard Worker }; 72*7304104dSAndroid Build Coastguard Worker 73*7304104dSAndroid Build Coastguard Worker /* This holds everything we cache about the CFI from each ELF file's 74*7304104dSAndroid Build Coastguard Worker .debug_frame or .eh_frame section. */ 75*7304104dSAndroid Build Coastguard Worker struct Dwarf_CFI_s 76*7304104dSAndroid Build Coastguard Worker { 77*7304104dSAndroid Build Coastguard Worker /* Dwarf handle we came from. If null, this is .eh_frame data. */ 78*7304104dSAndroid Build Coastguard Worker Dwarf *dbg; 79*7304104dSAndroid Build Coastguard Worker #define CFI_IS_EH(cfi) ((cfi)->dbg == NULL) 80*7304104dSAndroid Build Coastguard Worker 81*7304104dSAndroid Build Coastguard Worker /* Data of the .debug_frame or .eh_frame section. */ 82*7304104dSAndroid Build Coastguard Worker Elf_Data_Scn *data; 83*7304104dSAndroid Build Coastguard Worker const unsigned char *e_ident; /* For EI_DATA and EI_CLASS. */ 84*7304104dSAndroid Build Coastguard Worker 85*7304104dSAndroid Build Coastguard Worker Dwarf_Addr frame_vaddr; /* DW_EH_PE_pcrel, address of frame section. */ 86*7304104dSAndroid Build Coastguard Worker Dwarf_Addr textrel; /* DW_EH_PE_textrel base address. */ 87*7304104dSAndroid Build Coastguard Worker Dwarf_Addr datarel; /* DW_EH_PE_datarel base address. */ 88*7304104dSAndroid Build Coastguard Worker 89*7304104dSAndroid Build Coastguard Worker /* Location of next unread entry in the section. */ 90*7304104dSAndroid Build Coastguard Worker Dwarf_Off next_offset; 91*7304104dSAndroid Build Coastguard Worker 92*7304104dSAndroid Build Coastguard Worker /* Search tree for the CIEs, indexed by CIE_pointer (section offset). */ 93*7304104dSAndroid Build Coastguard Worker void *cie_tree; 94*7304104dSAndroid Build Coastguard Worker 95*7304104dSAndroid Build Coastguard Worker /* Search tree for the FDEs, indexed by PC address. */ 96*7304104dSAndroid Build Coastguard Worker void *fde_tree; 97*7304104dSAndroid Build Coastguard Worker 98*7304104dSAndroid Build Coastguard Worker /* Search tree for parsed DWARF expressions, indexed by raw pointer. */ 99*7304104dSAndroid Build Coastguard Worker void *expr_tree; 100*7304104dSAndroid Build Coastguard Worker 101*7304104dSAndroid Build Coastguard Worker /* Backend hook. */ 102*7304104dSAndroid Build Coastguard Worker struct ebl *ebl; 103*7304104dSAndroid Build Coastguard Worker 104*7304104dSAndroid Build Coastguard Worker /* Binary search table in .eh_frame_hdr section. */ 105*7304104dSAndroid Build Coastguard Worker const uint8_t *search_table; 106*7304104dSAndroid Build Coastguard Worker size_t search_table_len; 107*7304104dSAndroid Build Coastguard Worker Dwarf_Addr search_table_vaddr; 108*7304104dSAndroid Build Coastguard Worker size_t search_table_entries; 109*7304104dSAndroid Build Coastguard Worker uint8_t search_table_encoding; 110*7304104dSAndroid Build Coastguard Worker 111*7304104dSAndroid Build Coastguard Worker uint16_t e_machine; 112*7304104dSAndroid Build Coastguard Worker 113*7304104dSAndroid Build Coastguard Worker /* True if the file has a byte order different from the host. */ 114*7304104dSAndroid Build Coastguard Worker bool other_byte_order; 115*7304104dSAndroid Build Coastguard Worker 116*7304104dSAndroid Build Coastguard Worker /* Default rule for registers not previously mentioned 117*7304104dSAndroid Build Coastguard Worker is same_value, not undefined. */ 118*7304104dSAndroid Build Coastguard Worker bool default_same_value; 119*7304104dSAndroid Build Coastguard Worker }; 120*7304104dSAndroid Build Coastguard Worker 121*7304104dSAndroid Build Coastguard Worker 122*7304104dSAndroid Build Coastguard Worker enum dwarf_frame_rule 123*7304104dSAndroid Build Coastguard Worker { 124*7304104dSAndroid Build Coastguard Worker reg_unspecified, /* Uninitialized state. */ 125*7304104dSAndroid Build Coastguard Worker reg_undefined, /* DW_CFA_undefined */ 126*7304104dSAndroid Build Coastguard Worker reg_same_value, /* DW_CFA_same_value */ 127*7304104dSAndroid Build Coastguard Worker reg_offset, /* DW_CFA_offset_extended et al */ 128*7304104dSAndroid Build Coastguard Worker reg_val_offset, /* DW_CFA_val_offset et al */ 129*7304104dSAndroid Build Coastguard Worker reg_register, /* DW_CFA_register */ 130*7304104dSAndroid Build Coastguard Worker reg_expression, /* DW_CFA_expression */ 131*7304104dSAndroid Build Coastguard Worker reg_val_expression, /* DW_CFA_val_expression */ 132*7304104dSAndroid Build Coastguard Worker }; 133*7304104dSAndroid Build Coastguard Worker 134*7304104dSAndroid Build Coastguard Worker /* This describes what we know about an individual register. */ 135*7304104dSAndroid Build Coastguard Worker struct dwarf_frame_register 136*7304104dSAndroid Build Coastguard Worker { 137*7304104dSAndroid Build Coastguard Worker enum dwarf_frame_rule rule:3; 138*7304104dSAndroid Build Coastguard Worker 139*7304104dSAndroid Build Coastguard Worker /* The meaning of the value bits depends on the rule: 140*7304104dSAndroid Build Coastguard Worker 141*7304104dSAndroid Build Coastguard Worker Rule Value 142*7304104dSAndroid Build Coastguard Worker ---- ----- 143*7304104dSAndroid Build Coastguard Worker undefined unused 144*7304104dSAndroid Build Coastguard Worker same_value unused 145*7304104dSAndroid Build Coastguard Worker offset(N) N (register saved at CFA + value) 146*7304104dSAndroid Build Coastguard Worker val_offset(N) N (register = CFA + value) 147*7304104dSAndroid Build Coastguard Worker register(R) R (register = register #value) 148*7304104dSAndroid Build Coastguard Worker expression(E) section offset of DW_FORM_block containing E 149*7304104dSAndroid Build Coastguard Worker (register saved at address E computes) 150*7304104dSAndroid Build Coastguard Worker val_expression(E) section offset of DW_FORM_block containing E 151*7304104dSAndroid Build Coastguard Worker (register = value E computes) 152*7304104dSAndroid Build Coastguard Worker */ 153*7304104dSAndroid Build Coastguard Worker Dwarf_Sword value:(sizeof (Dwarf_Sword) * 8 - 3); 154*7304104dSAndroid Build Coastguard Worker }; 155*7304104dSAndroid Build Coastguard Worker 156*7304104dSAndroid Build Coastguard Worker /* This holds instructions for unwinding frame at a particular PC location 157*7304104dSAndroid Build Coastguard Worker described by an FDE. */ 158*7304104dSAndroid Build Coastguard Worker struct Dwarf_Frame_s 159*7304104dSAndroid Build Coastguard Worker { 160*7304104dSAndroid Build Coastguard Worker /* This frame description covers PC values in [start, end). */ 161*7304104dSAndroid Build Coastguard Worker Dwarf_Addr start; 162*7304104dSAndroid Build Coastguard Worker Dwarf_Addr end; 163*7304104dSAndroid Build Coastguard Worker 164*7304104dSAndroid Build Coastguard Worker Dwarf_CFI *cache; 165*7304104dSAndroid Build Coastguard Worker 166*7304104dSAndroid Build Coastguard Worker /* Previous state saved by DW_CFA_remember_state, or .cie->initial_state, 167*7304104dSAndroid Build Coastguard Worker or NULL in an initial_state pseudo-frame. */ 168*7304104dSAndroid Build Coastguard Worker Dwarf_Frame *prev; 169*7304104dSAndroid Build Coastguard Worker 170*7304104dSAndroid Build Coastguard Worker /* The FDE that generated this frame state. This points to its CIE, 171*7304104dSAndroid Build Coastguard Worker which has the return_address_register and signal_frame flag. */ 172*7304104dSAndroid Build Coastguard Worker struct dwarf_fde *fde; 173*7304104dSAndroid Build Coastguard Worker 174*7304104dSAndroid Build Coastguard Worker /* The CFA is unknown, is R+N, or is computed by a DWARF expression. 175*7304104dSAndroid Build Coastguard Worker A bogon in the CFI can indicate an invalid/incalculable rule. 176*7304104dSAndroid Build Coastguard Worker We store that as cfa_invalid rather than barfing when processing it, 177*7304104dSAndroid Build Coastguard Worker so callers can ignore the bogon unless they really need that CFA. */ 178*7304104dSAndroid Build Coastguard Worker enum { cfa_undefined, cfa_offset, cfa_expr, cfa_invalid } cfa_rule; 179*7304104dSAndroid Build Coastguard Worker union 180*7304104dSAndroid Build Coastguard Worker { 181*7304104dSAndroid Build Coastguard Worker Dwarf_Op offset; 182*7304104dSAndroid Build Coastguard Worker Dwarf_Block expr; 183*7304104dSAndroid Build Coastguard Worker } cfa_data; 184*7304104dSAndroid Build Coastguard Worker /* We store an offset rule as a DW_OP_bregx operation. */ 185*7304104dSAndroid Build Coastguard Worker #define cfa_val_reg cfa_data.offset.number 186*7304104dSAndroid Build Coastguard Worker #define cfa_val_offset cfa_data.offset.number2 187*7304104dSAndroid Build Coastguard Worker 188*7304104dSAndroid Build Coastguard Worker size_t nregs; 189*7304104dSAndroid Build Coastguard Worker struct dwarf_frame_register regs[]; 190*7304104dSAndroid Build Coastguard Worker }; 191*7304104dSAndroid Build Coastguard Worker 192*7304104dSAndroid Build Coastguard Worker 193*7304104dSAndroid Build Coastguard Worker /* Clean up the data structure and all it points to. */ 194*7304104dSAndroid Build Coastguard Worker extern void __libdw_destroy_frame_cache (Dwarf_CFI *cache) 195*7304104dSAndroid Build Coastguard Worker __nonnull_attribute__ (1) internal_function; 196*7304104dSAndroid Build Coastguard Worker 197*7304104dSAndroid Build Coastguard Worker /* Enter a CIE encountered while reading through for FDEs. */ 198*7304104dSAndroid Build Coastguard Worker extern void __libdw_intern_cie (Dwarf_CFI *cache, Dwarf_Off offset, 199*7304104dSAndroid Build Coastguard Worker const Dwarf_CIE *info) 200*7304104dSAndroid Build Coastguard Worker __nonnull_attribute__ (1, 3) internal_function; 201*7304104dSAndroid Build Coastguard Worker 202*7304104dSAndroid Build Coastguard Worker /* Look up a CIE_pointer for random access. */ 203*7304104dSAndroid Build Coastguard Worker extern struct dwarf_cie *__libdw_find_cie (Dwarf_CFI *cache, Dwarf_Off offset) 204*7304104dSAndroid Build Coastguard Worker __nonnull_attribute__ (1) internal_function; 205*7304104dSAndroid Build Coastguard Worker 206*7304104dSAndroid Build Coastguard Worker 207*7304104dSAndroid Build Coastguard Worker /* Look for an FDE covering the given PC address. */ 208*7304104dSAndroid Build Coastguard Worker extern struct dwarf_fde *__libdw_find_fde (Dwarf_CFI *cache, 209*7304104dSAndroid Build Coastguard Worker Dwarf_Addr address) 210*7304104dSAndroid Build Coastguard Worker __nonnull_attribute__ (1) internal_function; 211*7304104dSAndroid Build Coastguard Worker 212*7304104dSAndroid Build Coastguard Worker /* Look for an FDE by its offset in the section. */ 213*7304104dSAndroid Build Coastguard Worker extern struct dwarf_fde *__libdw_fde_by_offset (Dwarf_CFI *cache, 214*7304104dSAndroid Build Coastguard Worker Dwarf_Off offset) 215*7304104dSAndroid Build Coastguard Worker __nonnull_attribute__ (1) internal_function; 216*7304104dSAndroid Build Coastguard Worker 217*7304104dSAndroid Build Coastguard Worker /* Process the FDE that contains the given PC address, 218*7304104dSAndroid Build Coastguard Worker to yield the frame state when stopped there. 219*7304104dSAndroid Build Coastguard Worker The return value is a DWARF_E_* error code. */ 220*7304104dSAndroid Build Coastguard Worker extern int __libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde, 221*7304104dSAndroid Build Coastguard Worker Dwarf_Addr address, Dwarf_Frame **frame) 222*7304104dSAndroid Build Coastguard Worker __nonnull_attribute__ (1, 2, 4) internal_function; 223*7304104dSAndroid Build Coastguard Worker 224*7304104dSAndroid Build Coastguard Worker 225*7304104dSAndroid Build Coastguard Worker /* Dummy struct for memory-access.h macros. */ 226*7304104dSAndroid Build Coastguard Worker #define BYTE_ORDER_DUMMY(var, e_ident) \ 227*7304104dSAndroid Build Coastguard Worker const struct { bool other_byte_order; } var = \ 228*7304104dSAndroid Build Coastguard Worker { ((BYTE_ORDER == LITTLE_ENDIAN && e_ident[EI_DATA] == ELFDATA2MSB) \ 229*7304104dSAndroid Build Coastguard Worker || (BYTE_ORDER == BIG_ENDIAN && e_ident[EI_DATA] == ELFDATA2LSB)) } 230*7304104dSAndroid Build Coastguard Worker 231*7304104dSAndroid Build Coastguard Worker 232*7304104dSAndroid Build Coastguard Worker INTDECL (dwarf_next_cfi) 233*7304104dSAndroid Build Coastguard Worker INTDECL (dwarf_getcfi) 234*7304104dSAndroid Build Coastguard Worker INTDECL (dwarf_getcfi_elf) 235*7304104dSAndroid Build Coastguard Worker INTDECL (dwarf_cfi_end) 236*7304104dSAndroid Build Coastguard Worker INTDECL (dwarf_cfi_addrframe) 237*7304104dSAndroid Build Coastguard Worker 238*7304104dSAndroid Build Coastguard Worker #endif /* unwindP.h */ 239