13c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath/* CFI program execution.
2a1ea2423c0245d4a9f84523bcb5cb7cc96a27ec8Mark Wielaard   Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
43c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
73c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
213c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   WITHOUT ANY WARRANTY; without even the implied warranty of
223c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   General Public License for more details.
243c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
293c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#ifdef HAVE_CONFIG_H
303c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath# include <config.h>
313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#endif
323c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include <dwarf.h>
343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include "../libebl/libebl.h"
353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include "cfi.h"
363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include "memory-access.h"
373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include "encoded-value.h"
381d67c0c87a56349f7a0169e6bef6385696d86af2Jan Kratochvil#include "system.h"
393c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include <assert.h>
403c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include <stdlib.h>
413c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include <string.h>
423c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
433c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#define CFI_PRIMARY_MAX	0x3f
443c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
453c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathstatic Dwarf_Frame *
463c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathduplicate_frame_state (const Dwarf_Frame *original,
473c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath		       Dwarf_Frame *prev)
483c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
493c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  size_t size = offsetof (Dwarf_Frame, regs[original->nregs]);
503c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  Dwarf_Frame *copy = malloc (size);
513c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (likely (copy != NULL))
523c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
533c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      memcpy (copy, original, size);
543c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      copy->prev = prev;
553c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
563c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  return copy;
573c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
583c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
5934bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsiehstatic inline bool
6034bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsiehenough_registers (Dwarf_Word reg, Dwarf_Frame **pfs, int *result)
6134bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh{
6234bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh  /* Don't allow insanely large register numbers.  268435456 registers
6334bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh     should be enough for anybody.  And very large values might overflow
6434bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh     the array size and offsetof calculations below.  */
6534bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh  if (unlikely (reg >= INT32_MAX / sizeof ((*pfs)->regs[0])))
6634bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh    {
6734bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh      *result = DWARF_E_INVALID_CFI;
6834bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh      return false;
6934bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh    }
7034bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh
7134bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh  if ((*pfs)->nregs <= reg)
7234bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh    {
7334bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh       size_t size = offsetof (Dwarf_Frame, regs[reg + 1]);
7434bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh       Dwarf_Frame *bigger = realloc (*pfs, size);
7534bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh       if (unlikely (bigger == NULL))
7634bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh         {
7734bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh           *result = DWARF_E_NOMEM;
7834bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh           return false;
7934bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh         }
8034bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh       else
8134bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh         {
8234bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh           eu_static_assert (reg_unspecified == 0);
8334bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh           memset (bigger->regs + bigger->nregs, 0,
8434bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh                   (reg + 1 - bigger->nregs) * sizeof bigger->regs[0]);
8534bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh           bigger->nregs = reg + 1;
8634bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh           *pfs = bigger;
8734bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh         }
8834bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh     }
8934bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh  return true;
9034bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh}
9134bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh
9234bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsiehstatic inline void
9334bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsiehrequire_cfa_offset (Dwarf_Frame *fs)
9434bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh{
9534bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh  if (unlikely (fs->cfa_rule != cfa_offset))
9634bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh    fs->cfa_rule = cfa_invalid;
9734bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh}
9834bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh
993f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath/* Returns a DWARF_E_* error code, usually NOERROR or INVALID_CFI.
1003f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath   Frees *STATE on failure.  */
1013c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathstatic int
1023c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathexecute_cfi (Dwarf_CFI *cache,
1033c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     const struct dwarf_cie *cie,
1043c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     Dwarf_Frame **state,
1053c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     const uint8_t *program, const uint8_t *const end, bool abi_cfi,
1063c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     Dwarf_Addr loc, Dwarf_Addr find_pc)
1073c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
1083c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* The caller should not give us anything out of range.  */
1093c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  assert (loc <= find_pc);
1103c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1113c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  int result = DWARF_E_NOERROR;
1123c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1133c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#define cfi_assert(ok) do {						      \
1143c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    if (likely (ok)) break;						      \
1153c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    result = DWARF_E_INVALID_CFI;					      \
1163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    goto out;								      \
1173c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  } while (0)
1183c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1193c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  Dwarf_Frame *fs = *state;
1203b10ac0ade6aae156b76884421eb82985b4e9be8Roland McGrath
1213c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#define register_rule(regno, r_rule, r_value) do {	\
12234bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh    if (unlikely (! enough_registers (regno, &fs, &result)))	\
1233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      goto out;						\
1243c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    fs->regs[regno].rule = reg_##r_rule;		\
1253c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    fs->regs[regno].value = (r_value);			\
1263c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  } while (0)
1273c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  while (program < end)
1293c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
1303c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      uint8_t opcode = *program++;
1313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      Dwarf_Word regno;
1323c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      Dwarf_Word offset;
1333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      Dwarf_Word sf_offset;
1343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      Dwarf_Word operand = opcode & CFI_PRIMARY_MAX;
1353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      switch (opcode)
1363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	{
1373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* These cases move LOC, i.e. "create a new table row".  */
1383c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1393c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_advance_loc1:
1403c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  operand = *program++;
1413c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_advance_loc + 0 ... DW_CFA_advance_loc + CFI_PRIMARY_MAX:
1423c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	advance_loc:
1433c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  loc += operand * cie->code_alignment_factor;
1443c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  break;
1453c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1463c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_advance_loc2:
1477a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program + 2 <= end);
1483c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  operand = read_2ubyte_unaligned_inc (cache, program);
1493c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto advance_loc;
1503c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_advance_loc4:
1517a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program + 4 <= end);
1523c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  operand = read_4ubyte_unaligned_inc (cache, program);
1533c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto advance_loc;
1543c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_MIPS_advance_loc8:
1557a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program + 8 <= end);
1563c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  operand = read_8ubyte_unaligned_inc (cache, program);
1573c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto advance_loc;
1583c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1593c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_set_loc:
1603f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath	  if (likely (!read_encoded_value (cache, cie->fde_encoding,
1613f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath					   &program, &loc)))
1623f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath	    break;
1633f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath	  result = INTUSE(dwarf_errno) ();
1643f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath	  goto out;
1653c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1663c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* Now all following cases affect this row, but do not touch LOC.
1673c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     These cases end with 'continue'.  We only get out of the
1683c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     switch block for the row-copying (LOC-moving) cases above.  */
1693c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1703c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_def_cfa:
1717a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
1727a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
1737a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (offset, program, end);
1743c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	def_cfa:
1753c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  fs->cfa_rule = cfa_offset;
17655195e58ba85adc5c7f4cb6902c462854093c153Roland McGrath	  fs->cfa_val_reg = operand;
17755195e58ba85adc5c7f4cb6902c462854093c153Roland McGrath	  fs->cfa_val_offset = offset;
1783c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* Prime the rest of the Dwarf_Op so dwarf_frame_cfa can use it.  */
1793c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  fs->cfa_data.offset.atom = DW_OP_bregx;
1803c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  fs->cfa_data.offset.offset = 0;
1813c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
1823c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1833c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_def_cfa_register:
1847a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (regno, program, end);
18534bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh	  require_cfa_offset (fs);
18655195e58ba85adc5c7f4cb6902c462854093c153Roland McGrath	  fs->cfa_val_reg = regno;
1873c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
1883c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1893c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_def_cfa_sf:
1907a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
1917a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
1927a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_sleb128 (sf_offset, program, end);
1933c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  offset = sf_offset * cie->data_alignment_factor;
1943c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto def_cfa;
1953c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1963c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_def_cfa_offset:
1977a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (offset, program, end);
1983c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	def_cfa_offset:
19934bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh	  require_cfa_offset (fs);
20055195e58ba85adc5c7f4cb6902c462854093c153Roland McGrath	  fs->cfa_val_offset = offset;
2013c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2023c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2033c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_def_cfa_offset_sf:
2047a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_sleb128 (sf_offset, program, end);
20555195e58ba85adc5c7f4cb6902c462854093c153Roland McGrath	  offset = sf_offset * cie->data_alignment_factor;
2063c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto def_cfa_offset;
2073c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2083c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_def_cfa_expression:
2093c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
2107a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2113c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  cfi_assert (operand <= (Dwarf_Word) (end - program));
2123c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  fs->cfa_rule = cfa_expr;
2133c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  fs->cfa_data.expr.data = (unsigned char *) program;
2143c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  fs->cfa_data.expr.length = operand;
2153c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  program += operand;
2163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2173c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2183c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_undefined:
2197a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (regno, program, end);
2203c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  register_rule (regno, undefined, 0);
2213c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2223c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_same_value:
2247a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (regno, program, end);
2253c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  register_rule (regno, same_value, 0);
2263c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2273c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_offset_extended:
2297a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2307a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
2313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_offset + 0 ... DW_CFA_offset + CFI_PRIMARY_MAX:
2327a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (offset, program, end);
2333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  offset *= cie->data_alignment_factor;
2343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	offset_extended:
2353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  register_rule (operand, offset, offset);
2363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2383c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_offset_extended_sf:
2397a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2407a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_sleb128 (sf_offset, program, end);
2413c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	offset_extended_sf:
2423c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  offset = sf_offset * cie->data_alignment_factor;
2433c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto offset_extended;
2443c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2453c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_GNU_negative_offset_extended:
2463c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* GNU extension obsoleted by DW_CFA_offset_extended_sf.  */
2477a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2487a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
2497a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (offset, program, end);
2503c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  sf_offset = -offset;
2513c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto offset_extended_sf;
2523c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2533c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_val_offset:
2547a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2557a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
2567a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (offset, program, end);
2573c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  offset *= cie->data_alignment_factor;
2583c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	val_offset:
2593c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  register_rule (operand, val_offset, offset);
2603c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2613c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2623c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_val_offset_sf:
2637a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2647a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
2657a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_sleb128 (sf_offset, program, end);
2663c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  offset = sf_offset * cie->data_alignment_factor;
2673c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  goto val_offset;
2683c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2693c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_register:
2707a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (regno, program, end);
2717a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
2727a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2733c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  register_rule (regno, register, operand);
2743c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2753c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2763c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_expression:
2773dec3e110bb2a2453156868e1221dc8192399e3eMark Wielaard	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
2783dec3e110bb2a2453156868e1221dc8192399e3eMark Wielaard	  assert (! abi_cfi);
2797a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (regno, program, end);
2803c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  offset = program - (const uint8_t *) cache->data->d.d_buf;
2813c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
2827a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  cfi_assert (program < end);
2837a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2843c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  cfi_assert (operand <= (Dwarf_Word) (end - program));
2853c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  program += operand;
2863c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  register_rule (regno, expression, offset);
2873c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
2883c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2893c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_val_expression:
2903dec3e110bb2a2453156868e1221dc8192399e3eMark Wielaard	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
2913dec3e110bb2a2453156868e1221dc8192399e3eMark Wielaard	  assert (! abi_cfi);
2927a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (regno, program, end);
2933c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
2943c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  offset = program - (const uint8_t *) cache->data->d.d_buf;
2957a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
2963c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  cfi_assert (operand <= (Dwarf_Word) (end - program));
2973c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  program += operand;
2983c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  register_rule (regno, val_expression, offset);
2993c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
3003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3013c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_restore_extended:
3027a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
3033c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_restore + 0 ... DW_CFA_restore + CFI_PRIMARY_MAX:
3043c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3053c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  if (unlikely (abi_cfi) && likely (opcode == DW_CFA_restore))
3063c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    {
3073c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      /* Special case hack to give backend abi_cfi a shorthand.  */
3083c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      cache->default_same_value = true;
3093c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      continue;
3103c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    }
3113c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3123c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* This can't be used in the CIE's own initial instructions.  */
3133c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  cfi_assert (cie->initial_state != NULL);
3143c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3153c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* Restore the CIE's initial rule for this register.  */
31634bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh	  if (unlikely (! enough_registers (operand, &fs, &result)))
3173c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    goto out;
3183c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  if (cie->initial_state->nregs > operand)
3193c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    fs->regs[operand] = cie->initial_state->regs[operand];
3203c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  else
3213c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    fs->regs[operand].rule = reg_unspecified;
3223c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
3233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3243c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_remember_state:
3253c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  {
3263c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    /* Duplicate the state and chain the copy on.  */
3273c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    Dwarf_Frame *copy = duplicate_frame_state (fs, fs);
3283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    if (unlikely (copy == NULL))
3293c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      {
3303c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath		result = DWARF_E_NOMEM;
3313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath		goto out;
3323c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      }
3333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    fs = copy;
3343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    continue;
3353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  }
3363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_restore_state:
3383c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  {
3393c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    /* Pop the current state off and use the old one instead.  */
3403c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    Dwarf_Frame *prev = fs->prev;
3413c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    cfi_assert (prev != NULL);
3423c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    free (fs);
3433c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    fs = prev;
3443f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath	    continue;
3453c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  }
3463c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3473c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_nop:
3483c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
3493c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3503c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_GNU_window_save:
3513c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* This is magic shorthand used only by SPARC.  It's equivalent
3523c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     to a bunch of DW_CFA_register and DW_CFA_offset operations.  */
35334bb96a2c181846291ea863928003faaec3a9f55Chih-Hung Hsieh	  if (unlikely (! enough_registers (31, &fs, &result)))
3543c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    goto out;
3553c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  for (regno = 8; regno < 16; ++regno)
3563c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    {
3573c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      /* Find each %oN in %iN.  */
3583c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      fs->regs[regno].rule = reg_register;
3593c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      fs->regs[regno].value = regno + 16;
3603c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    }
3613c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  unsigned int address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
3623c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath				       ? 4 : 8);
3633c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  for (; regno < 32; ++regno)
3643c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    {
3653c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      /* Find %l0..%l7 and %i0..%i7 in a block at the CFA.  */
3663c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      fs->regs[regno].rule = reg_offset;
3673c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      fs->regs[regno].value = (regno - 16) * address_size;
3683c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    }
3693c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
3703c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3713c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	case DW_CFA_GNU_args_size:
3723c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* XXX is this useful for anything? */
3737a053473c7bedd22e3db39c444a4cd8f97eace25Mark Wielaard	  get_uleb128 (operand, program, end);
3743c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
3753c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3763c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	default:
3773c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  cfi_assert (false);
3783c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  continue;
3793c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	}
3803c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3813c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      /* We get here only for the cases that have just moved LOC.  */
382c70ebc0587ad1c549a3fe7f16a563bf4d6782aa7Roland McGrath      cfi_assert (cie->initial_state != NULL);
3833c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (find_pc >= loc)
3843c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	/* This advance has not yet reached FIND_PC.  */
3853c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	fs->start = loc;
3863c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      else
3873c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	{
3883c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  /* We have just advanced past the address we're looking for.
3893c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	     The state currently described is what we want to see.  */
3903c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  fs->end = loc;
3913c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  break;
3923c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	}
3933c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
3943c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3953c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* "The end of the instruction stream can be thought of as a
3963c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     DW_CFA_set_loc (initial_location + address_range) instruction."
3973c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     (DWARF 3.0 Section 6.4.3)
3983c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
3993c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     When we fall off the end of the program without an advance_loc/set_loc
4003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     that put us past FIND_PC, the final state left by the FDE program
4013c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     applies to this address (the caller ensured it was inside the FDE).
4023c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     This address (FDE->end) is already in FS->end as set by the caller.  */
4033c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4043c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#undef register_rule
4053c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#undef cfi_assert
4063c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4073c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath out:
4083c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4093c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* Pop any remembered states left on the stack.  */
4103c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  while (fs->prev != NULL)
4113c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
4123c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      Dwarf_Frame *prev = fs->prev;
4133c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      fs->prev = prev->prev;
4143c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      free (prev);
4153c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
4163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4173f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath  if (likely (result == DWARF_E_NOERROR))
4183c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    *state = fs;
4193f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath  else
4203f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath    free (fs);
4213c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4223c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  return result;
4233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
4243c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4253c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathstatic int
4263c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathcie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie)
4273c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
4283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  int result = DWARF_E_NOERROR;
4293c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4303c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (likely (cie->initial_state != NULL))
4313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    return result;
4323c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* This CIE has not been used before.  Play out its initial
4343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     instructions and cache the initial state that results.
4353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     First we'll let the backend fill in the default initial
4363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     state for this machine's ABI.  */
4373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4383c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  Dwarf_CIE abi_info = { DW_CIE_ID_64, NULL, NULL, 1, 1, -1, "", NULL, 0, 0 };
4393c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4403c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* Make sure we have a backend handle cached.  */
4413c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (unlikely (cache->ebl == NULL))
4423c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
4433c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      cache->ebl = ebl_openbackend (cache->data->s->elf);
4443c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (unlikely (cache->ebl == NULL))
4453c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	cache->ebl = (void *) -1l;
4463c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
4473c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4483c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* Fetch the ABI's default CFI program.  */
4493c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (likely (cache->ebl != (void *) -1l)
4503c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      && unlikely (ebl_abi_cfi (cache->ebl, &abi_info) < 0))
4513c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    return DWARF_E_UNKNOWN_ERROR;
4523c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4533c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  Dwarf_Frame *cie_fs = calloc (1, sizeof (Dwarf_Frame));
4543c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (unlikely (cie_fs == NULL))
4553c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    return DWARF_E_NOMEM;
4563c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4573c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* If the default state of any register is not "undefined"
4583c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     (i.e. call-clobbered), then the backend supplies instructions
4593c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     for the standard initial state.  */
4603c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (abi_info.initial_instructions_end > abi_info.initial_instructions)
4613c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
4623c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      /* Dummy CIE for backend's instructions.  */
4633c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      struct dwarf_cie abi_cie =
4643c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	{
4653c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  .code_alignment_factor = abi_info.code_alignment_factor,
4663c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  .data_alignment_factor = abi_info.data_alignment_factor,
4673c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	};
4683c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      result = execute_cfi (cache, &abi_cie, &cie_fs,
4693c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			    abi_info.initial_instructions,
4703c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			    abi_info.initial_instructions_end, true,
4713c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			    0, (Dwarf_Addr) -1l);
4723c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
4733c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4743c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* Now run the CIE's initial instructions.  */
4753c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (cie->initial_instructions_end > cie->initial_instructions
4763c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      && likely (result == DWARF_E_NOERROR))
4773c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    result = execute_cfi (cache, cie, &cie_fs,
4783c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			  cie->initial_instructions,
4793c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			  cie->initial_instructions_end, false,
4803c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			  0, (Dwarf_Addr) -1l);
4813c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4823f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath  if (likely (result == DWARF_E_NOERROR))
4833c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
4843f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath      /* Now we have the initial state of things that all
4853f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath	 FDEs using this CIE will start from.  */
4863f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath      cie_fs->cache = cache;
4873f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath      cie->initial_state = cie_fs;
4883c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
4893c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4903c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  return result;
4913c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
4923c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
4933c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathint
4943c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathinternal_function
4953c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath__libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
4963c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			  Dwarf_Addr address, Dwarf_Frame **frame)
4973c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
4983c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  int result = cie_cache_initial_state (cache, fde->cie);
4993c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (likely (result == DWARF_E_NOERROR))
5003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
5013c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      Dwarf_Frame *fs = duplicate_frame_state (fde->cie->initial_state, NULL);
5023c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (unlikely (fs == NULL))
5033c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	return DWARF_E_NOMEM;
5043c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
5053c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      fs->fde = fde;
5063c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      fs->start = fde->start;
5073c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      fs->end = fde->end;
5083c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
5093c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      result = execute_cfi (cache, fde->cie, &fs,
5103c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			    fde->instructions, fde->instructions_end, false,
5113c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			    fde->start, address);
5123f9d955d56d62bcca1e6d97eb17649b3b0f38accRoland McGrath      if (likely (result == DWARF_E_NOERROR))
5133c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	*frame = fs;
5143c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
5153c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  return result;
5163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
517