xref: /aosp_15_r20/external/elfutils/libdw/cfi.h (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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