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