encoded-value.h revision 3c84db3b4b610bf636c4363abb6d3dac5ae020f9
13c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath/* DW_EH_PE_* support for libdw unwinder.
23c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Copyright (C) 2009 Red Hat, Inc.
33c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   This file is part of Red Hat elfutils.
43c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
53c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Red Hat elfutils is free software; you can redistribute it and/or modify
63c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   it under the terms of the GNU General Public License as published by the
73c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Free Software Foundation; version 2 of the License.
83c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
93c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Red Hat elfutils is distributed in the hope that it will be useful, but
103c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   WITHOUT ANY WARRANTY; without even the implied warranty of
113c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
123c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   General Public License for more details.
133c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
143c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   You should have received a copy of the GNU General Public License along
153c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   with Red Hat elfutils; if not, write to the Free Software Foundation,
163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
173c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
183c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   In addition, as a special exception, Red Hat, Inc. gives You the
193c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   additional right to link the code of Red Hat elfutils with code licensed
203c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   under any Open Source Initiative certified open source license
213c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   (http://www.opensource.org/licenses/index.php) which requires the
223c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   distribution of source code with any binary distribution and to
233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   distribute linked combinations of the two.  Non-GPL Code permitted under
243c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   this exception must only link to the code of Red Hat elfutils through
253c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   those well defined interfaces identified in the file named EXCEPTION
263c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   found in the source code files (the "Approved Interfaces").  The files
273c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   of Non-GPL Code may instantiate templates or use macros or inline
283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   functions from the Approved Interfaces without causing the resulting
293c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   work to be covered by the GNU General Public License.  Only Red Hat,
303c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Inc. may make changes or additions to the list of Approved Interfaces.
313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Red Hat's grant of this exception is conditioned upon your not adding
323c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   any new exceptions.  If you wish to add a new Approved Interface or
333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   exception, please contact Red Hat.  You must obey the GNU General Public
343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   License in all respects for all of the Red Hat elfutils code and other
353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   code used in conjunction with Red Hat elfutils except the Non-GPL Code
363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   covered by this exception.  If you modify this file, you may extend this
373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   exception to your version of the file, but you are not obligated to do
383c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   so.  If you do not wish to provide this exception without modification,
393c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   you must delete this exception statement from your version and license
403c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   this file solely under the GPL without exception.
413c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
423c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Red Hat elfutils is an included package of the Open Invention Network.
433c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   An included package of the Open Invention Network is a package for which
443c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Open Invention Network licensees cross-license their patents.  No patent
453c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   license is granted, either expressly or impliedly, by designation as an
463c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   included package.  Should you wish to participate in the Open Invention
473c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   Network licensing program, please visit www.openinventionnetwork.com
483c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath   <http://www.openinventionnetwork.com>.  */
493c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
503c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#ifndef _ENCODED_VALUE_H
513c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#define _ENCODED_VALUE_H 1
523c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
533c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include <dwarf.h>
543c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include <stdlib.h>
553c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#include "libdwP.h"
563c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
573c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
583c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathstatic size_t __attribute__ ((unused))
593c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathencoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
603c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath		    uint8_t encoding, const uint8_t *p)
613c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
623c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (encoding == DW_EH_PE_omit)
633c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    return 0;
643c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
653c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  switch (encoding & 0x07)
663c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
673c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_udata2:
683c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      return 2;
693c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_udata4:
703c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      return 4;
713c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_udata8:
723c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      return 8;
733c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
743c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_absptr:
753c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      return e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
763c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
773c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_uleb128:
783c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (p != NULL)
793c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	{
803c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  const uint8_t *end = p;
813c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  while (end < (uint8_t *) data->d_buf + data->d_size)
823c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	    if (*end++ & 0x80u)
833c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	      return end - p;
843c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	}
853c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
863c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    default:
873c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      abort ();
883c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      return 0;
893c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
903c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
913c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
923c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathstatic inline int __attribute__ ((unused))
933c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath__libdw_cfi_read_address_inc (const Dwarf_CFI *cache,
943c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			      const unsigned char **addrp,
953c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			      int width, Dwarf_Addr *ret)
963c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
973c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  width = width ?: cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
983c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
993c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (cache->dbg != NULL)
1003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    return __libdw_read_address_inc (cache->dbg, IDX_debug_frame,
1013c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath				     addrp, width, ret);
1023c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1033c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  /* Only .debug_frame might have relocation to consider.
1043c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath     Read plain values from .eh_frame data.  */
1053c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1063c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  if (width == 4)
1073c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    *ret = read_4ubyte_unaligned_inc (cache, *addrp);
1083c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  else
1093c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    *ret = read_8ubyte_unaligned_inc (cache, *addrp);
1103c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  return 0;
1113c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
1123c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1133c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathstatic bool __attribute__ ((unused))
1143c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrathread_encoded_value (const Dwarf_CFI *cache, uint8_t encoding, const uint8_t **p,
1153c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath		    Dwarf_Addr *result)
1163c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath{
1173c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  *result = 0;
1183c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  switch (encoding & 0x70)
1193c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
1203c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_absptr:
1213c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1223c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_pcrel:
1233c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      *result = (cache->frame_vaddr
1243c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath		 + (*p - (const uint8_t *) cache->data->d.d_buf));
1253c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1263c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_textrel:
1273c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      // ia64: segrel
1283c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      *result = cache->textrel;
1293c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1303c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_datarel:
1313c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      // i386: GOTOFF
1323c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      // ia64: gprel
1333c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      *result = cache->datarel;
1343c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1353c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_funcrel:	/* XXX */
1363c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1373c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_aligned:
1383c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      {
1393c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	const size_t address_size
1403c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  = cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
1413c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	size_t align = ((cache->frame_vaddr
1423c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			 + (*p - (const uint8_t *) cache->data->d.d_buf))
1433c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath			& (address_size - 1));
1443c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	if (align != 0)
1453c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	  *p += address_size - align;
1463c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	break;
1473c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      }
1483c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1493c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    default:
1503c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      abort ();
1513c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
1523c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1533c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  Dwarf_Addr value;
1543c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  switch (encoding & 0x0f)
1553c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    {
1563c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_udata2:
1573c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      value = read_2ubyte_unaligned_inc (cache, *p);
1583c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1593c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1603c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_sdata2:
1613c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      value = read_2sbyte_unaligned_inc (cache, *p);
1623c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1633c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1643c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_udata4:
1653c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (__libdw_cfi_read_address_inc (cache, p, 4, &value))
1663c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	return false;
1673c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1683c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1693c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_sdata4:
1703c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (__libdw_cfi_read_address_inc (cache, p, 4, &value))
1713c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	return false;
1723c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      value = (Dwarf_Sword) (Elf32_Sword) value; /* Sign-extend.  */
1733c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1743c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1753c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_udata8:
1763c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_sdata8:
1773c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (__libdw_cfi_read_address_inc (cache, p, 8, &value))
1783c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	return false;
1793c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1803c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1813c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_absptr:
1823c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      if (__libdw_cfi_read_address_inc (cache, p, 0, &value))
1833c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath	return false;
1843c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1853c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1863c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_uleb128:
1873c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      get_uleb128 (value, *p);
1883c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1893c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1903c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    case DW_EH_PE_sleb128:
1913c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      get_sleb128 (value, *p);
1923c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      break;
1933c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1943c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    default:
1953c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath      abort ();
1963c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath    }
1973c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
1983c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  *result += value;
1993c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath  return false;
2003c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath}
2013c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath
2023c84db3b4b610bf636c4363abb6d3dac5ae020f9Roland McGrath#endif	/* encoded-value.h */
203