xref: /aosp_15_r20/external/elfutils/libdw/cfi.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* CFI program execution.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2009-2010, 2014, 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 #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker 
33*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
34*7304104dSAndroid Build Coastguard Worker #include "libebl.h"
35*7304104dSAndroid Build Coastguard Worker #include "cfi.h"
36*7304104dSAndroid Build Coastguard Worker #include "memory-access.h"
37*7304104dSAndroid Build Coastguard Worker #include "encoded-value.h"
38*7304104dSAndroid Build Coastguard Worker #include "system.h"
39*7304104dSAndroid Build Coastguard Worker #include <assert.h>
40*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
41*7304104dSAndroid Build Coastguard Worker #include <string.h>
42*7304104dSAndroid Build Coastguard Worker 
43*7304104dSAndroid Build Coastguard Worker #define CFI_PRIMARY_MAX	0x3f
44*7304104dSAndroid Build Coastguard Worker 
45*7304104dSAndroid Build Coastguard Worker static Dwarf_Frame *
duplicate_frame_state(const Dwarf_Frame * original,Dwarf_Frame * prev)46*7304104dSAndroid Build Coastguard Worker duplicate_frame_state (const Dwarf_Frame *original,
47*7304104dSAndroid Build Coastguard Worker 		       Dwarf_Frame *prev)
48*7304104dSAndroid Build Coastguard Worker {
49*7304104dSAndroid Build Coastguard Worker   size_t size = offsetof (Dwarf_Frame, regs[original->nregs]);
50*7304104dSAndroid Build Coastguard Worker   Dwarf_Frame *copy = malloc (size);
51*7304104dSAndroid Build Coastguard Worker   if (likely (copy != NULL))
52*7304104dSAndroid Build Coastguard Worker     {
53*7304104dSAndroid Build Coastguard Worker       memcpy (copy, original, size);
54*7304104dSAndroid Build Coastguard Worker       copy->prev = prev;
55*7304104dSAndroid Build Coastguard Worker     }
56*7304104dSAndroid Build Coastguard Worker   return copy;
57*7304104dSAndroid Build Coastguard Worker }
58*7304104dSAndroid Build Coastguard Worker 
59*7304104dSAndroid Build Coastguard Worker static inline bool
enough_registers(Dwarf_Word reg,Dwarf_Frame ** pfs,int * result)60*7304104dSAndroid Build Coastguard Worker enough_registers (Dwarf_Word reg, Dwarf_Frame **pfs, int *result)
61*7304104dSAndroid Build Coastguard Worker {
62*7304104dSAndroid Build Coastguard Worker   /* Don't allow insanely large register numbers.  268435456 registers
63*7304104dSAndroid Build Coastguard Worker      should be enough for anybody.  And very large values might overflow
64*7304104dSAndroid Build Coastguard Worker      the array size and offsetof calculations below.  */
65*7304104dSAndroid Build Coastguard Worker   if (unlikely (reg >= INT32_MAX / sizeof ((*pfs)->regs[0])))
66*7304104dSAndroid Build Coastguard Worker     {
67*7304104dSAndroid Build Coastguard Worker       *result = DWARF_E_INVALID_CFI;
68*7304104dSAndroid Build Coastguard Worker       return false;
69*7304104dSAndroid Build Coastguard Worker     }
70*7304104dSAndroid Build Coastguard Worker 
71*7304104dSAndroid Build Coastguard Worker   if ((*pfs)->nregs <= reg)
72*7304104dSAndroid Build Coastguard Worker     {
73*7304104dSAndroid Build Coastguard Worker        size_t size = offsetof (Dwarf_Frame, regs[reg + 1]);
74*7304104dSAndroid Build Coastguard Worker        Dwarf_Frame *bigger = realloc (*pfs, size);
75*7304104dSAndroid Build Coastguard Worker        if (unlikely (bigger == NULL))
76*7304104dSAndroid Build Coastguard Worker          {
77*7304104dSAndroid Build Coastguard Worker            *result = DWARF_E_NOMEM;
78*7304104dSAndroid Build Coastguard Worker            return false;
79*7304104dSAndroid Build Coastguard Worker          }
80*7304104dSAndroid Build Coastguard Worker        else
81*7304104dSAndroid Build Coastguard Worker          {
82*7304104dSAndroid Build Coastguard Worker            eu_static_assert (reg_unspecified == 0);
83*7304104dSAndroid Build Coastguard Worker            memset (bigger->regs + bigger->nregs, 0,
84*7304104dSAndroid Build Coastguard Worker                    (reg + 1 - bigger->nregs) * sizeof bigger->regs[0]);
85*7304104dSAndroid Build Coastguard Worker            bigger->nregs = reg + 1;
86*7304104dSAndroid Build Coastguard Worker            *pfs = bigger;
87*7304104dSAndroid Build Coastguard Worker          }
88*7304104dSAndroid Build Coastguard Worker      }
89*7304104dSAndroid Build Coastguard Worker   return true;
90*7304104dSAndroid Build Coastguard Worker }
91*7304104dSAndroid Build Coastguard Worker 
92*7304104dSAndroid Build Coastguard Worker static inline void
require_cfa_offset(Dwarf_Frame * fs)93*7304104dSAndroid Build Coastguard Worker require_cfa_offset (Dwarf_Frame *fs)
94*7304104dSAndroid Build Coastguard Worker {
95*7304104dSAndroid Build Coastguard Worker   if (unlikely (fs->cfa_rule != cfa_offset))
96*7304104dSAndroid Build Coastguard Worker     fs->cfa_rule = cfa_invalid;
97*7304104dSAndroid Build Coastguard Worker }
98*7304104dSAndroid Build Coastguard Worker 
99*7304104dSAndroid Build Coastguard Worker /* Returns a DWARF_E_* error code, usually NOERROR or INVALID_CFI.
100*7304104dSAndroid Build Coastguard Worker    Frees *STATE on failure.  */
101*7304104dSAndroid Build Coastguard Worker static int
execute_cfi(Dwarf_CFI * cache,const struct dwarf_cie * cie,Dwarf_Frame ** state,const uint8_t * program,const uint8_t * const end,bool abi_cfi,Dwarf_Addr loc,Dwarf_Addr find_pc)102*7304104dSAndroid Build Coastguard Worker execute_cfi (Dwarf_CFI *cache,
103*7304104dSAndroid Build Coastguard Worker 	     const struct dwarf_cie *cie,
104*7304104dSAndroid Build Coastguard Worker 	     Dwarf_Frame **state,
105*7304104dSAndroid Build Coastguard Worker 	     const uint8_t *program, const uint8_t *const end, bool abi_cfi,
106*7304104dSAndroid Build Coastguard Worker 	     Dwarf_Addr loc, Dwarf_Addr find_pc)
107*7304104dSAndroid Build Coastguard Worker {
108*7304104dSAndroid Build Coastguard Worker   /* The caller should not give us anything out of range.  */
109*7304104dSAndroid Build Coastguard Worker   assert (loc <= find_pc);
110*7304104dSAndroid Build Coastguard Worker 
111*7304104dSAndroid Build Coastguard Worker   int result = DWARF_E_NOERROR;
112*7304104dSAndroid Build Coastguard Worker 
113*7304104dSAndroid Build Coastguard Worker #define cfi_assert(ok) do {						      \
114*7304104dSAndroid Build Coastguard Worker     if (likely (ok)) break;						      \
115*7304104dSAndroid Build Coastguard Worker     result = DWARF_E_INVALID_CFI;					      \
116*7304104dSAndroid Build Coastguard Worker     goto out;								      \
117*7304104dSAndroid Build Coastguard Worker   } while (0)
118*7304104dSAndroid Build Coastguard Worker 
119*7304104dSAndroid Build Coastguard Worker   Dwarf_Frame *fs = *state;
120*7304104dSAndroid Build Coastguard Worker 
121*7304104dSAndroid Build Coastguard Worker #define register_rule(regno, r_rule, r_value) do {	\
122*7304104dSAndroid Build Coastguard Worker     if (unlikely (! enough_registers (regno, &fs, &result)))	\
123*7304104dSAndroid Build Coastguard Worker       goto out;						\
124*7304104dSAndroid Build Coastguard Worker     fs->regs[regno].rule = reg_##r_rule;		\
125*7304104dSAndroid Build Coastguard Worker     fs->regs[regno].value = (r_value);			\
126*7304104dSAndroid Build Coastguard Worker   } while (0)
127*7304104dSAndroid Build Coastguard Worker 
128*7304104dSAndroid Build Coastguard Worker   while (program < end)
129*7304104dSAndroid Build Coastguard Worker     {
130*7304104dSAndroid Build Coastguard Worker       uint8_t opcode = *program++;
131*7304104dSAndroid Build Coastguard Worker       Dwarf_Word regno;
132*7304104dSAndroid Build Coastguard Worker       Dwarf_Word offset;
133*7304104dSAndroid Build Coastguard Worker       Dwarf_Word sf_offset;
134*7304104dSAndroid Build Coastguard Worker       Dwarf_Word operand = opcode & CFI_PRIMARY_MAX;
135*7304104dSAndroid Build Coastguard Worker       switch (opcode)
136*7304104dSAndroid Build Coastguard Worker 	{
137*7304104dSAndroid Build Coastguard Worker 	  /* These cases move LOC, i.e. "create a new table row".  */
138*7304104dSAndroid Build Coastguard Worker 
139*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_advance_loc1:
140*7304104dSAndroid Build Coastguard Worker 	  operand = *program++;
141*7304104dSAndroid Build Coastguard Worker 	  FALLTHROUGH;
142*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_advance_loc + 0 ... DW_CFA_advance_loc + CFI_PRIMARY_MAX:
143*7304104dSAndroid Build Coastguard Worker 	advance_loc:
144*7304104dSAndroid Build Coastguard Worker 	  loc += operand * cie->code_alignment_factor;
145*7304104dSAndroid Build Coastguard Worker 	  break;
146*7304104dSAndroid Build Coastguard Worker 
147*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_advance_loc2:
148*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program + 2 <= end);
149*7304104dSAndroid Build Coastguard Worker 	  operand = read_2ubyte_unaligned_inc (cache, program);
150*7304104dSAndroid Build Coastguard Worker 	  goto advance_loc;
151*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_advance_loc4:
152*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program + 4 <= end);
153*7304104dSAndroid Build Coastguard Worker 	  operand = read_4ubyte_unaligned_inc (cache, program);
154*7304104dSAndroid Build Coastguard Worker 	  goto advance_loc;
155*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_MIPS_advance_loc8:
156*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program + 8 <= end);
157*7304104dSAndroid Build Coastguard Worker 	  operand = read_8ubyte_unaligned_inc (cache, program);
158*7304104dSAndroid Build Coastguard Worker 	  goto advance_loc;
159*7304104dSAndroid Build Coastguard Worker 
160*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_set_loc:
161*7304104dSAndroid Build Coastguard Worker 	  if (likely (!read_encoded_value (cache, cie->fde_encoding,
162*7304104dSAndroid Build Coastguard Worker 					   &program, &loc)))
163*7304104dSAndroid Build Coastguard Worker 	    break;
164*7304104dSAndroid Build Coastguard Worker 	  result = INTUSE(dwarf_errno) ();
165*7304104dSAndroid Build Coastguard Worker 	  goto out;
166*7304104dSAndroid Build Coastguard Worker 
167*7304104dSAndroid Build Coastguard Worker 	  /* Now all following cases affect this row, but do not touch LOC.
168*7304104dSAndroid Build Coastguard Worker 	     These cases end with 'continue'.  We only get out of the
169*7304104dSAndroid Build Coastguard Worker 	     switch block for the row-copying (LOC-moving) cases above.  */
170*7304104dSAndroid Build Coastguard Worker 
171*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_def_cfa:
172*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
173*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
174*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (offset, program, end);
175*7304104dSAndroid Build Coastguard Worker 	def_cfa:
176*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_rule = cfa_offset;
177*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_val_reg = operand;
178*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_val_offset = offset;
179*7304104dSAndroid Build Coastguard Worker 	  /* Prime the rest of the Dwarf_Op so dwarf_frame_cfa can use it.  */
180*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_data.offset.atom = DW_OP_bregx;
181*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_data.offset.offset = 0;
182*7304104dSAndroid Build Coastguard Worker 	  continue;
183*7304104dSAndroid Build Coastguard Worker 
184*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_def_cfa_register:
185*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (regno, program, end);
186*7304104dSAndroid Build Coastguard Worker 	  require_cfa_offset (fs);
187*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_val_reg = regno;
188*7304104dSAndroid Build Coastguard Worker 	  continue;
189*7304104dSAndroid Build Coastguard Worker 
190*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_def_cfa_sf:
191*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
192*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
193*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (sf_offset, program, end);
194*7304104dSAndroid Build Coastguard Worker 	  offset = sf_offset * cie->data_alignment_factor;
195*7304104dSAndroid Build Coastguard Worker 	  goto def_cfa;
196*7304104dSAndroid Build Coastguard Worker 
197*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_def_cfa_offset:
198*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (offset, program, end);
199*7304104dSAndroid Build Coastguard Worker 	def_cfa_offset:
200*7304104dSAndroid Build Coastguard Worker 	  require_cfa_offset (fs);
201*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_val_offset = offset;
202*7304104dSAndroid Build Coastguard Worker 	  continue;
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_def_cfa_offset_sf:
205*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (sf_offset, program, end);
206*7304104dSAndroid Build Coastguard Worker 	  offset = sf_offset * cie->data_alignment_factor;
207*7304104dSAndroid Build Coastguard Worker 	  goto def_cfa_offset;
208*7304104dSAndroid Build Coastguard Worker 
209*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_def_cfa_expression:
210*7304104dSAndroid Build Coastguard Worker 	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
211*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
212*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (operand <= (Dwarf_Word) (end - program));
213*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_rule = cfa_expr;
214*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_data.expr.data = (unsigned char *) program;
215*7304104dSAndroid Build Coastguard Worker 	  fs->cfa_data.expr.length = operand;
216*7304104dSAndroid Build Coastguard Worker 	  program += operand;
217*7304104dSAndroid Build Coastguard Worker 	  continue;
218*7304104dSAndroid Build Coastguard Worker 
219*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_undefined:
220*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (regno, program, end);
221*7304104dSAndroid Build Coastguard Worker 	  register_rule (regno, undefined, 0);
222*7304104dSAndroid Build Coastguard Worker 	  continue;
223*7304104dSAndroid Build Coastguard Worker 
224*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_same_value:
225*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (regno, program, end);
226*7304104dSAndroid Build Coastguard Worker 	  register_rule (regno, same_value, 0);
227*7304104dSAndroid Build Coastguard Worker 	  continue;
228*7304104dSAndroid Build Coastguard Worker 
229*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_offset_extended:
230*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
231*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
232*7304104dSAndroid Build Coastguard Worker 	  FALLTHROUGH;
233*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_offset + 0 ... DW_CFA_offset + CFI_PRIMARY_MAX:
234*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (offset, program, end);
235*7304104dSAndroid Build Coastguard Worker 	  offset *= cie->data_alignment_factor;
236*7304104dSAndroid Build Coastguard Worker 	offset_extended:
237*7304104dSAndroid Build Coastguard Worker 	  register_rule (operand, offset, offset);
238*7304104dSAndroid Build Coastguard Worker 	  continue;
239*7304104dSAndroid Build Coastguard Worker 
240*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_offset_extended_sf:
241*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
242*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
243*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (sf_offset, program, end);
244*7304104dSAndroid Build Coastguard Worker 	offset_extended_sf:
245*7304104dSAndroid Build Coastguard Worker 	  offset = sf_offset * cie->data_alignment_factor;
246*7304104dSAndroid Build Coastguard Worker 	  goto offset_extended;
247*7304104dSAndroid Build Coastguard Worker 
248*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_GNU_negative_offset_extended:
249*7304104dSAndroid Build Coastguard Worker 	  /* GNU extension obsoleted by DW_CFA_offset_extended_sf.  */
250*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
251*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
252*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (offset, program, end);
253*7304104dSAndroid Build Coastguard Worker 	  sf_offset = -offset;
254*7304104dSAndroid Build Coastguard Worker 	  goto offset_extended_sf;
255*7304104dSAndroid Build Coastguard Worker 
256*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_val_offset:
257*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
258*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
259*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (offset, program, end);
260*7304104dSAndroid Build Coastguard Worker 	  offset *= cie->data_alignment_factor;
261*7304104dSAndroid Build Coastguard Worker 	val_offset:
262*7304104dSAndroid Build Coastguard Worker 	  register_rule (operand, val_offset, offset);
263*7304104dSAndroid Build Coastguard Worker 	  continue;
264*7304104dSAndroid Build Coastguard Worker 
265*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_val_offset_sf:
266*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
267*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
268*7304104dSAndroid Build Coastguard Worker 	  get_sleb128 (sf_offset, program, end);
269*7304104dSAndroid Build Coastguard Worker 	  offset = sf_offset * cie->data_alignment_factor;
270*7304104dSAndroid Build Coastguard Worker 	  goto val_offset;
271*7304104dSAndroid Build Coastguard Worker 
272*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_register:
273*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (regno, program, end);
274*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
275*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
276*7304104dSAndroid Build Coastguard Worker 	  register_rule (regno, register, operand);
277*7304104dSAndroid Build Coastguard Worker 	  continue;
278*7304104dSAndroid Build Coastguard Worker 
279*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_expression:
280*7304104dSAndroid Build Coastguard Worker 	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
281*7304104dSAndroid Build Coastguard Worker 	  assert (! abi_cfi);
282*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (regno, program, end);
283*7304104dSAndroid Build Coastguard Worker 	  offset = program - (const uint8_t *) cache->data->d.d_buf;
284*7304104dSAndroid Build Coastguard Worker 	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
285*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
286*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
287*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (operand <= (Dwarf_Word) (end - program));
288*7304104dSAndroid Build Coastguard Worker 	  program += operand;
289*7304104dSAndroid Build Coastguard Worker 	  register_rule (regno, expression, offset);
290*7304104dSAndroid Build Coastguard Worker 	  continue;
291*7304104dSAndroid Build Coastguard Worker 
292*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_val_expression:
293*7304104dSAndroid Build Coastguard Worker 	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
294*7304104dSAndroid Build Coastguard Worker 	  assert (! abi_cfi);
295*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (regno, program, end);
296*7304104dSAndroid Build Coastguard Worker 	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
297*7304104dSAndroid Build Coastguard Worker 	  offset = program - (const uint8_t *) cache->data->d.d_buf;
298*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (program < end);
299*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
300*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (operand <= (Dwarf_Word) (end - program));
301*7304104dSAndroid Build Coastguard Worker 	  program += operand;
302*7304104dSAndroid Build Coastguard Worker 	  register_rule (regno, val_expression, offset);
303*7304104dSAndroid Build Coastguard Worker 	  continue;
304*7304104dSAndroid Build Coastguard Worker 
305*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_restore_extended:
306*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
307*7304104dSAndroid Build Coastguard Worker 	  FALLTHROUGH;
308*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_restore + 0 ... DW_CFA_restore + CFI_PRIMARY_MAX:
309*7304104dSAndroid Build Coastguard Worker 
310*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (abi_cfi) && likely (opcode == DW_CFA_restore))
311*7304104dSAndroid Build Coastguard Worker 	    {
312*7304104dSAndroid Build Coastguard Worker 	      /* Special case hack to give backend abi_cfi a shorthand.  */
313*7304104dSAndroid Build Coastguard Worker 	      cache->default_same_value = true;
314*7304104dSAndroid Build Coastguard Worker 	      continue;
315*7304104dSAndroid Build Coastguard Worker 	    }
316*7304104dSAndroid Build Coastguard Worker 
317*7304104dSAndroid Build Coastguard Worker 	  /* This can't be used in the CIE's own initial instructions.  */
318*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (cie->initial_state != NULL);
319*7304104dSAndroid Build Coastguard Worker 
320*7304104dSAndroid Build Coastguard Worker 	  /* Restore the CIE's initial rule for this register.  */
321*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (! enough_registers (operand, &fs, &result)))
322*7304104dSAndroid Build Coastguard Worker 	    goto out;
323*7304104dSAndroid Build Coastguard Worker 	  if (cie->initial_state->nregs > operand)
324*7304104dSAndroid Build Coastguard Worker 	    fs->regs[operand] = cie->initial_state->regs[operand];
325*7304104dSAndroid Build Coastguard Worker 	  else
326*7304104dSAndroid Build Coastguard Worker 	    fs->regs[operand].rule = reg_unspecified;
327*7304104dSAndroid Build Coastguard Worker 	  continue;
328*7304104dSAndroid Build Coastguard Worker 
329*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_remember_state:
330*7304104dSAndroid Build Coastguard Worker 	  {
331*7304104dSAndroid Build Coastguard Worker 	    /* Duplicate the state and chain the copy on.  */
332*7304104dSAndroid Build Coastguard Worker 	    Dwarf_Frame *copy = duplicate_frame_state (fs, fs);
333*7304104dSAndroid Build Coastguard Worker 	    if (unlikely (copy == NULL))
334*7304104dSAndroid Build Coastguard Worker 	      {
335*7304104dSAndroid Build Coastguard Worker 		result = DWARF_E_NOMEM;
336*7304104dSAndroid Build Coastguard Worker 		goto out;
337*7304104dSAndroid Build Coastguard Worker 	      }
338*7304104dSAndroid Build Coastguard Worker 	    fs = copy;
339*7304104dSAndroid Build Coastguard Worker 	    continue;
340*7304104dSAndroid Build Coastguard Worker 	  }
341*7304104dSAndroid Build Coastguard Worker 
342*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_restore_state:
343*7304104dSAndroid Build Coastguard Worker 	  {
344*7304104dSAndroid Build Coastguard Worker 	    /* Pop the current state off and use the old one instead.  */
345*7304104dSAndroid Build Coastguard Worker 	    Dwarf_Frame *prev = fs->prev;
346*7304104dSAndroid Build Coastguard Worker 	    cfi_assert (prev != NULL);
347*7304104dSAndroid Build Coastguard Worker 	    free (fs);
348*7304104dSAndroid Build Coastguard Worker 	    fs = prev;
349*7304104dSAndroid Build Coastguard Worker 	    continue;
350*7304104dSAndroid Build Coastguard Worker 	  }
351*7304104dSAndroid Build Coastguard Worker 
352*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_nop:
353*7304104dSAndroid Build Coastguard Worker 	  continue;
354*7304104dSAndroid Build Coastguard Worker 
355*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_GNU_window_save: /* DW_CFA_AARCH64_negate_ra_state */
356*7304104dSAndroid Build Coastguard Worker 	  if (cache->e_machine == EM_AARCH64)
357*7304104dSAndroid Build Coastguard Worker 	    {
358*7304104dSAndroid Build Coastguard Worker 	      /* Toggles the return address state, indicating whether
359*7304104dSAndroid Build Coastguard Worker 		 the return address is encrypted or not on
360*7304104dSAndroid Build Coastguard Worker 		 aarch64. XXX not handled yet.  */
361*7304104dSAndroid Build Coastguard Worker 	    }
362*7304104dSAndroid Build Coastguard Worker 	  else
363*7304104dSAndroid Build Coastguard Worker 	    {
364*7304104dSAndroid Build Coastguard Worker 	      /* This is magic shorthand used only by SPARC.  It's
365*7304104dSAndroid Build Coastguard Worker 		 equivalent to a bunch of DW_CFA_register and
366*7304104dSAndroid Build Coastguard Worker 		 DW_CFA_offset operations.  */
367*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (! enough_registers (31, &fs, &result)))
368*7304104dSAndroid Build Coastguard Worker 		goto out;
369*7304104dSAndroid Build Coastguard Worker 	      for (regno = 8; regno < 16; ++regno)
370*7304104dSAndroid Build Coastguard Worker 		{
371*7304104dSAndroid Build Coastguard Worker 		  /* Find each %oN in %iN.  */
372*7304104dSAndroid Build Coastguard Worker 		  fs->regs[regno].rule = reg_register;
373*7304104dSAndroid Build Coastguard Worker 		  fs->regs[regno].value = regno + 16;
374*7304104dSAndroid Build Coastguard Worker 		}
375*7304104dSAndroid Build Coastguard Worker 	      unsigned int address_size;
376*7304104dSAndroid Build Coastguard Worker 	      address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
377*7304104dSAndroid Build Coastguard Worker 			      ? 4 : 8);
378*7304104dSAndroid Build Coastguard Worker 	      for (; regno < 32; ++regno)
379*7304104dSAndroid Build Coastguard Worker 		{
380*7304104dSAndroid Build Coastguard Worker 		  /* Find %l0..%l7 and %i0..%i7 in a block at the CFA.  */
381*7304104dSAndroid Build Coastguard Worker 		  fs->regs[regno].rule = reg_offset;
382*7304104dSAndroid Build Coastguard Worker 		  fs->regs[regno].value = (regno - 16) * address_size;
383*7304104dSAndroid Build Coastguard Worker 		}
384*7304104dSAndroid Build Coastguard Worker 	    }
385*7304104dSAndroid Build Coastguard Worker 	  continue;
386*7304104dSAndroid Build Coastguard Worker 
387*7304104dSAndroid Build Coastguard Worker 	case DW_CFA_GNU_args_size:
388*7304104dSAndroid Build Coastguard Worker 	  /* XXX is this useful for anything? */
389*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (operand, program, end);
390*7304104dSAndroid Build Coastguard Worker 	  continue;
391*7304104dSAndroid Build Coastguard Worker 
392*7304104dSAndroid Build Coastguard Worker 	default:
393*7304104dSAndroid Build Coastguard Worker 	  cfi_assert (false);
394*7304104dSAndroid Build Coastguard Worker 	  continue;
395*7304104dSAndroid Build Coastguard Worker 	}
396*7304104dSAndroid Build Coastguard Worker 
397*7304104dSAndroid Build Coastguard Worker       /* We get here only for the cases that have just moved LOC.  */
398*7304104dSAndroid Build Coastguard Worker       cfi_assert (cie->initial_state != NULL);
399*7304104dSAndroid Build Coastguard Worker       if (find_pc >= loc)
400*7304104dSAndroid Build Coastguard Worker 	/* This advance has not yet reached FIND_PC.  */
401*7304104dSAndroid Build Coastguard Worker 	fs->start = loc;
402*7304104dSAndroid Build Coastguard Worker       else
403*7304104dSAndroid Build Coastguard Worker 	{
404*7304104dSAndroid Build Coastguard Worker 	  /* We have just advanced past the address we're looking for.
405*7304104dSAndroid Build Coastguard Worker 	     The state currently described is what we want to see.  */
406*7304104dSAndroid Build Coastguard Worker 	  fs->end = loc;
407*7304104dSAndroid Build Coastguard Worker 	  break;
408*7304104dSAndroid Build Coastguard Worker 	}
409*7304104dSAndroid Build Coastguard Worker     }
410*7304104dSAndroid Build Coastguard Worker 
411*7304104dSAndroid Build Coastguard Worker   /* "The end of the instruction stream can be thought of as a
412*7304104dSAndroid Build Coastguard Worker      DW_CFA_set_loc (initial_location + address_range) instruction."
413*7304104dSAndroid Build Coastguard Worker      (DWARF 3.0 Section 6.4.3)
414*7304104dSAndroid Build Coastguard Worker 
415*7304104dSAndroid Build Coastguard Worker      When we fall off the end of the program without an advance_loc/set_loc
416*7304104dSAndroid Build Coastguard Worker      that put us past FIND_PC, the final state left by the FDE program
417*7304104dSAndroid Build Coastguard Worker      applies to this address (the caller ensured it was inside the FDE).
418*7304104dSAndroid Build Coastguard Worker      This address (FDE->end) is already in FS->end as set by the caller.  */
419*7304104dSAndroid Build Coastguard Worker 
420*7304104dSAndroid Build Coastguard Worker #undef register_rule
421*7304104dSAndroid Build Coastguard Worker #undef cfi_assert
422*7304104dSAndroid Build Coastguard Worker 
423*7304104dSAndroid Build Coastguard Worker  out:
424*7304104dSAndroid Build Coastguard Worker 
425*7304104dSAndroid Build Coastguard Worker   /* Pop any remembered states left on the stack.  */
426*7304104dSAndroid Build Coastguard Worker   while (fs->prev != NULL)
427*7304104dSAndroid Build Coastguard Worker     {
428*7304104dSAndroid Build Coastguard Worker       Dwarf_Frame *prev = fs->prev;
429*7304104dSAndroid Build Coastguard Worker       fs->prev = prev->prev;
430*7304104dSAndroid Build Coastguard Worker       free (prev);
431*7304104dSAndroid Build Coastguard Worker     }
432*7304104dSAndroid Build Coastguard Worker 
433*7304104dSAndroid Build Coastguard Worker   if (likely (result == DWARF_E_NOERROR))
434*7304104dSAndroid Build Coastguard Worker     *state = fs;
435*7304104dSAndroid Build Coastguard Worker   else
436*7304104dSAndroid Build Coastguard Worker     free (fs);
437*7304104dSAndroid Build Coastguard Worker 
438*7304104dSAndroid Build Coastguard Worker   return result;
439*7304104dSAndroid Build Coastguard Worker }
440*7304104dSAndroid Build Coastguard Worker 
441*7304104dSAndroid Build Coastguard Worker static int
cie_cache_initial_state(Dwarf_CFI * cache,struct dwarf_cie * cie)442*7304104dSAndroid Build Coastguard Worker cie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie)
443*7304104dSAndroid Build Coastguard Worker {
444*7304104dSAndroid Build Coastguard Worker   int result = DWARF_E_NOERROR;
445*7304104dSAndroid Build Coastguard Worker 
446*7304104dSAndroid Build Coastguard Worker   if (likely (cie->initial_state != NULL))
447*7304104dSAndroid Build Coastguard Worker     return result;
448*7304104dSAndroid Build Coastguard Worker 
449*7304104dSAndroid Build Coastguard Worker   /* This CIE has not been used before.  Play out its initial
450*7304104dSAndroid Build Coastguard Worker      instructions and cache the initial state that results.
451*7304104dSAndroid Build Coastguard Worker      First we'll let the backend fill in the default initial
452*7304104dSAndroid Build Coastguard Worker      state for this machine's ABI.  */
453*7304104dSAndroid Build Coastguard Worker 
454*7304104dSAndroid Build Coastguard Worker   Dwarf_CIE abi_info = { DW_CIE_ID_64, NULL, NULL, 1, 1, -1, "", NULL, 0, 0 };
455*7304104dSAndroid Build Coastguard Worker 
456*7304104dSAndroid Build Coastguard Worker   /* Make sure we have a backend handle cached.  */
457*7304104dSAndroid Build Coastguard Worker   if (unlikely (cache->ebl == NULL))
458*7304104dSAndroid Build Coastguard Worker     {
459*7304104dSAndroid Build Coastguard Worker       cache->ebl = ebl_openbackend (cache->data->s->elf);
460*7304104dSAndroid Build Coastguard Worker       if (unlikely (cache->ebl == NULL))
461*7304104dSAndroid Build Coastguard Worker 	cache->ebl = (void *) -1l;
462*7304104dSAndroid Build Coastguard Worker     }
463*7304104dSAndroid Build Coastguard Worker 
464*7304104dSAndroid Build Coastguard Worker   /* Fetch the ABI's default CFI program.  */
465*7304104dSAndroid Build Coastguard Worker   if (likely (cache->ebl != (void *) -1l)
466*7304104dSAndroid Build Coastguard Worker       && unlikely (ebl_abi_cfi (cache->ebl, &abi_info) < 0))
467*7304104dSAndroid Build Coastguard Worker     return DWARF_E_UNKNOWN_ERROR;
468*7304104dSAndroid Build Coastguard Worker 
469*7304104dSAndroid Build Coastguard Worker   Dwarf_Frame *cie_fs = calloc (1, sizeof (Dwarf_Frame));
470*7304104dSAndroid Build Coastguard Worker   if (unlikely (cie_fs == NULL))
471*7304104dSAndroid Build Coastguard Worker     return DWARF_E_NOMEM;
472*7304104dSAndroid Build Coastguard Worker 
473*7304104dSAndroid Build Coastguard Worker   /* If the default state of any register is not "undefined"
474*7304104dSAndroid Build Coastguard Worker      (i.e. call-clobbered), then the backend supplies instructions
475*7304104dSAndroid Build Coastguard Worker      for the standard initial state.  */
476*7304104dSAndroid Build Coastguard Worker   if (abi_info.initial_instructions_end > abi_info.initial_instructions)
477*7304104dSAndroid Build Coastguard Worker     {
478*7304104dSAndroid Build Coastguard Worker       /* Dummy CIE for backend's instructions.  */
479*7304104dSAndroid Build Coastguard Worker       struct dwarf_cie abi_cie =
480*7304104dSAndroid Build Coastguard Worker 	{
481*7304104dSAndroid Build Coastguard Worker 	  .code_alignment_factor = abi_info.code_alignment_factor,
482*7304104dSAndroid Build Coastguard Worker 	  .data_alignment_factor = abi_info.data_alignment_factor,
483*7304104dSAndroid Build Coastguard Worker 	};
484*7304104dSAndroid Build Coastguard Worker       result = execute_cfi (cache, &abi_cie, &cie_fs,
485*7304104dSAndroid Build Coastguard Worker 			    abi_info.initial_instructions,
486*7304104dSAndroid Build Coastguard Worker 			    abi_info.initial_instructions_end, true,
487*7304104dSAndroid Build Coastguard Worker 			    0, (Dwarf_Addr) -1l);
488*7304104dSAndroid Build Coastguard Worker     }
489*7304104dSAndroid Build Coastguard Worker 
490*7304104dSAndroid Build Coastguard Worker   /* Now run the CIE's initial instructions.  */
491*7304104dSAndroid Build Coastguard Worker   if (cie->initial_instructions_end > cie->initial_instructions
492*7304104dSAndroid Build Coastguard Worker       && likely (result == DWARF_E_NOERROR))
493*7304104dSAndroid Build Coastguard Worker     result = execute_cfi (cache, cie, &cie_fs,
494*7304104dSAndroid Build Coastguard Worker 			  cie->initial_instructions,
495*7304104dSAndroid Build Coastguard Worker 			  cie->initial_instructions_end, false,
496*7304104dSAndroid Build Coastguard Worker 			  0, (Dwarf_Addr) -1l);
497*7304104dSAndroid Build Coastguard Worker 
498*7304104dSAndroid Build Coastguard Worker   if (likely (result == DWARF_E_NOERROR))
499*7304104dSAndroid Build Coastguard Worker     {
500*7304104dSAndroid Build Coastguard Worker       /* Now we have the initial state of things that all
501*7304104dSAndroid Build Coastguard Worker 	 FDEs using this CIE will start from.  */
502*7304104dSAndroid Build Coastguard Worker       cie_fs->cache = cache;
503*7304104dSAndroid Build Coastguard Worker       cie->initial_state = cie_fs;
504*7304104dSAndroid Build Coastguard Worker     }
505*7304104dSAndroid Build Coastguard Worker 
506*7304104dSAndroid Build Coastguard Worker   return result;
507*7304104dSAndroid Build Coastguard Worker }
508*7304104dSAndroid Build Coastguard Worker 
509*7304104dSAndroid Build Coastguard Worker int
510*7304104dSAndroid Build Coastguard Worker internal_function
__libdw_frame_at_address(Dwarf_CFI * cache,struct dwarf_fde * fde,Dwarf_Addr address,Dwarf_Frame ** frame)511*7304104dSAndroid Build Coastguard Worker __libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
512*7304104dSAndroid Build Coastguard Worker 			  Dwarf_Addr address, Dwarf_Frame **frame)
513*7304104dSAndroid Build Coastguard Worker {
514*7304104dSAndroid Build Coastguard Worker   int result = cie_cache_initial_state (cache, fde->cie);
515*7304104dSAndroid Build Coastguard Worker   if (likely (result == DWARF_E_NOERROR))
516*7304104dSAndroid Build Coastguard Worker     {
517*7304104dSAndroid Build Coastguard Worker       Dwarf_Frame *fs = duplicate_frame_state (fde->cie->initial_state, NULL);
518*7304104dSAndroid Build Coastguard Worker       if (unlikely (fs == NULL))
519*7304104dSAndroid Build Coastguard Worker 	return DWARF_E_NOMEM;
520*7304104dSAndroid Build Coastguard Worker 
521*7304104dSAndroid Build Coastguard Worker       fs->fde = fde;
522*7304104dSAndroid Build Coastguard Worker       fs->start = fde->start;
523*7304104dSAndroid Build Coastguard Worker       fs->end = fde->end;
524*7304104dSAndroid Build Coastguard Worker 
525*7304104dSAndroid Build Coastguard Worker       result = execute_cfi (cache, fde->cie, &fs,
526*7304104dSAndroid Build Coastguard Worker 			    fde->instructions, fde->instructions_end, false,
527*7304104dSAndroid Build Coastguard Worker 			    fde->start, address);
528*7304104dSAndroid Build Coastguard Worker       if (likely (result == DWARF_E_NOERROR))
529*7304104dSAndroid Build Coastguard Worker 	*frame = fs;
530*7304104dSAndroid Build Coastguard Worker     }
531*7304104dSAndroid Build Coastguard Worker   return result;
532*7304104dSAndroid Build Coastguard Worker }
533